'How to create a zoned of gradation area on the edge of ROI in opencv python

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



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 fmw42