Is it possible to only blur a subregion of an image, instead of the whole image with OpenCV, to save some computational cost?
EDIT: One important point is that when blurring the boundary of the subregion, one should use the existing image content as much as possible; only when the convolution exceeds the boundary of the original image, an extrapolation or other artificial border conditions can be used.
Python - OpenCV & PyQT5 together In Gaussian Blur operation, the image is convolved with a Gaussian filter instead of the box filter. The Gaussian filter is a low-pass filter that removes the high-frequency components are reduced. src − A Mat object representing the source (input image) for this operation.
To average blur an image, we use the cv2. blur function. This function requires two arguments: the image we want to blur and the size of the kernel.
To get any kind of strong/wide and correct blur, you're going to need a 2-pass effect. One pass can't sample enough pixels (and certainly can't do so fast enough); two passes decreases complexity from n^2 to 2n, allowing much larger sampling areas and stronger blur.
To blur the whole image, assuming you want to overwrite the original (In-place filtering is supported by cv::GaussianBlur), you will have something like
cv::GaussianBlur(image, image, Size(0, 0), 4);
To blur just a region use Mat::operator()(const Rect& roi) to extract the region:
cv::Rect region(x, y, w, h);
cv::GaussianBlur(image(region), image(region), Size(0, 0), 4);
Or if you want the blurred output in a separate image:
cv::Rect region(x, y, w, h);
cv::Mat blurred_region;
cv::GaussianBlur(image(region), blurred_region, Size(0, 0), 4);
The above uses the default BORDER_CONSTANT
option that just assumes everything outside the image is 0 when doing the blurring.
I am not sure what it does with pixels at the edge of a region. You can force it to ignore pixels outside the region (BORDER_CONSTANT|BORDER_ISOLATE). SO it think it probably does use the pixels outside the region. You need to compare the results from above with:
const int bsize = 10;
cv::Rect region(x, y, w, h);
cv::Rect padded_region(x - bsize, y - bsize, w + 2 * bsize, h + 2 * bsize)
cv::Mat blurred_padded_region;
cv::GaussianBlur(image(padded_region), blurred_padded_region, Size(0, 0), 4);
cv::Mat blurred_region = blurred_padded_region(cv::Rect(bsize, bsize, w, h));
// and you can then copy that back into the original image if you want:
blurred_region.copyTo(image(region));
Here's how to do it in Python. The idea is to select a ROI, blur it, then insert it back into the image
import cv2
# Read in image
image = cv2.imread('1.png')
# Create ROI coordinates
topLeft = (60, 140)
bottomRight = (340, 250)
x, y = topLeft[0], topLeft[1]
w, h = bottomRight[0] - topLeft[0], bottomRight[1] - topLeft[1]
# Grab ROI with Numpy slicing and blur
ROI = image[y:y+h, x:x+w]
blur = cv2.GaussianBlur(ROI, (51,51), 0)
# Insert ROI back into image
image[y:y+h, x:x+w] = blur
cv2.imshow('blur', blur)
cv2.imshow('image', image)
cv2.waitKey()
Before ->
After
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With