Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gaussian blurring with OpenCV: only blurring a subregion of an image?

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.

like image 575
xuhdev Avatar asked Jun 12 '14 22:06

xuhdev


People also ask

How does Gaussian blur work OpenCV?

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.

How do you blur the image in OpenCV and different types of blurring techniques?

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.

How do I make my Gaussian blur stronger?

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.


2 Answers

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));
like image 129
Bull Avatar answered Nov 30 '22 23:11

Bull


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

like image 39
nathancy Avatar answered Dec 01 '22 00:12

nathancy