I had the same issue and here's the solution that actually worked for me (and it works on any contour) :
import cv2 as cv
import numpy as np
Here I define the list of vertices of an example polygon ROI:
roi_corners = np.array([[(180,300),(120,540),(110,480),(160,350)]],dtype = np.int32)
Read the original Image:
image = cv.imread('image.jpeg')
create a blurred copy of the entire image:
blurred_image = cv.GaussianBlur(image,(43, 43), 30)
create a mask for the ROI and fill in the ROI with (255,255,255) color :
mask = np.zeros(image.shape, dtype=np.uint8)
channel_count = image.shape[2]
ignore_mask_color = (255,)*channel_count
cv.fillPoly(mask, roi_corners, ignore_mask_color)
create a mask for everywhere in the original image except the ROI, (hence mask_inverse) :
mask_inverse = np.ones(mask.shape).astype(np.uint8)*255 - mask
combine all the masks and above images in the following way :
final_image = cv.bitwise_and(blurred_image, mask) + cv.bitwise_and(image, mask_inverse)
here's a example of an original image witth the ROI being the oblique license plate (a parallelogram):
and the resulting image:
