-1

I have a binary image (white and black), the where Region of Interest (ROI) is black. The shape of ROI is irregular and the location of ROI can be anywhere in the frame.

I want to have a smooth gradation at the edge of the ROI (black -> dark grey -> grey -> light grey -> white).

I research the links below, however those cannot solve my problem:

  1. How to blur some portion of Image in Android?
  2. OpenCV - How to achieve a gradual image blur effect?
  3. Combining 2 images with transparent mask in opencv
  4. Gradient mask blending in opencv python

Example of ROI - original image, the REAL Shape is irregular and Location is anywhere:

example of ROI - original image, the REAL Shape is irregular and Location is anywhere

Expected result - in the edge of ROI the is gradation part changing from stright line to dash line: black -> dark grey -> grey -> light grey -> white:

expectation image - in the edge of ROI the is gradation part changing from stright line to dash line: black -> dark grey -> grey -> light grey -> white

han
  • 1
  • 1
  • 1
    Are you looking for [distance transform](https://docs.opencv.org/3.4/d2/dbd/tutorial_distance_transform.html) ? – Jeru Luke Apr 07 '22 at 07:42
  • Seems it is not my expectation. I want to keep the size and shape of ROI almost the same, and only a little part in the edge, e.g. 15 pixel the gradation area is located. I have using GaussianBlur() to make the edge smoother however the smooth part did not contain gradation from black to white. – han Apr 07 '22 at 07:56
  • Please provide enough code so others can better understand or reproduce the problem. – Community Apr 07 '22 at 14:07
  • @han using Gaussian blur **will** have a gradient change from black to white. How else do you want your result? – Jeru Luke Apr 07 '22 at 14:52
  • Do you want the gradient inside the black or outside the black region – fmw42 Apr 07 '22 at 15:32
  • @JeruLuke my expectation the gradient will have a zone. I think it has been answered by fmw42. – han Apr 08 '22 at 02:56
  • @fmw42 if I want the gradient inside the black region should I invert black region into white color and vice verse before I apply the distance transform? I've tried change parameter distanceType and maskSize in cv2.distanceTransform() but the gradient seems outside the black region. – han Apr 11 '22 at 00:19
  • Yes, inverts so rectangle is white and outside is black. The documentation says "Calculates the distance to the closest zero pixel for each pixel of the source image." – fmw42 Apr 11 '22 at 04:46

1 Answers1

2

Here is one way to do that for an outer gradient in Python/OpenCV.

 - Read the input
 - Convert to grayscale
 - Threshold to binary
 - Apply a distance transform
 - Stretch it to full dynamic range
 - Stretch to limit the gradient to a short distance around the rectangle
 - Save the output

Input:

enter image description here

import cv2
import numpy as np
import skimage.exposure

# read image
img = cv2.imread('rect_black.jpg')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold to binary
thresh = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY)[1]

# apply distance transform
distimg = cv2.distanceTransform(thresh, cv2.DIST_L2, 3)

# scale distance image to full dynamic range
distimg = skimage.exposure.rescale_intensity(distimg, in_range='image', out_range=(0,255)).astype(np.uint8)

# scale distance image to form limited gradient border
result = skimage.exposure.rescale_intensity(distimg, in_range=(0,25), out_range=(0,255)).astype(np.uint8)

# save result
cv2.imwrite('rect_black_distance.png',distimg)
cv2.imwrite('rect_black_result.png',result)

# show the images
cv2.imshow("distance", distimg)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Stretched Distance Image:

enter image description here

Result:

enter image description here

Note: In place of the distance transform, one could just use a Gaussian blur.

fmw42
  • 46,825
  • 10
  • 62
  • 80