How to blur with a controlled area?

Hello, I have to be able to blur only specific part of a .jpg, however the size needs to be about 200 pixels by 200 pixels with a threshold of about plus or minus 4 pixels. The hint my teacher gave was to change the color values into the average of the surrounding plus or minus 4 color values. The last step is to recombine these three new color layers. I have not learned how to manipulate a section of the color layers so that they are blurred, any help would be greatly appreciated.

 Accepted Answer

I don't know what that means. Do you mean that you might have a, say, 10 megapixel image but you want to blur only a 200x200 +/- 4? In other words, blur an area that's somewhere between 39,996 and 40,004 pixels? How would you specify where that small area is located inside your 10 megapixel image? Here's some code snippets that may be helpful
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Mask by some binary image.
maskedRed = redChannel .* mask;
maskedGreen = greenChannel .* mask;
maskedBlue = blueChannel .* mask;
% Recombine separate channels into a single RGB image.
rgbImage = cat(3, redChannel, greenChannel, blueChannel);
maskedRgbImage = cat(3, maskedRed, maskedGreen, maskedBlue);
% Blur an image (average in a window)
blurredImage = conv2(redChannel, ones(windowWidth)/windowWidth^2, 'same');
Note: this is not a working script - it's just some snippets. See what you can get with those code statements I gave you. Write back with your program if you need more hints.
I'm not sure what it means to change a pixel into the average of the surrounding pixels plus or minus 4 color values. The pixel is either the average value or it's some other value, like the average+4 or the average-4, but you have to specify because the pixel has to have one value, not a range of values.

28 Comments

Note: in what IA wrote, windowWidth should be (distance_backwards + distance_forward + 1 for current location), which would be (4 + 4 + 1) = 9
Oh, is that what "plus or minus 4 color values" meant? I thought it had something to do with the color (intensity) values, but you're probably right. So then, do you have any idea what "200 pixels by 200 pixels with a threshold of about plus or minus 4 pixels" means? What's being thresholded? It almost sounds like some kind of Photoshop magic-wand type of region growing (where the area varies depending on some gray level tolerance), but I doubt it.
Billy
Billy on 21 Nov 2012
Edited: Billy on 21 Nov 2012
Well the main objective is to blur the center of an image and I used size to get an array of [353 300 3] So I assumed the area I would be working with was 172:180 by row and 146 to 154 by column to get the center, but i am not sure that is entirely correct. And to clarify, each pixel I guess is defined as the average of its surrounding 4 and the blur has an area of plus or minus 100 pixels around the center. This is the best I can do clarifying. At least now I will be able to get started. Thank you.
Also, the 200 by 200 comes from the variable of 100 being a 2 by 2 area. My teacher defined this area as the central region.
Clear as mud. But the averaging would be like this
blurredGreenChannel = conv2(greenChannel, [0,1,0;1,0,1;0,1,0]/4, 'same');
That will take the average of the pixel above, below, to the left, and to the right of the central pixel. Basically the kernel is like a + sign with the middle missing.
Billy
Billy on 21 Nov 2012
Edited: Billy on 21 Nov 2012
I share that sentiment with you, and seeing as this is for an introductory class, I am sure you can see it is unreasonably difficult. I am not sure that I should post the prompt to the question the way I did last time, I was notified by the teacher that as long as the work is not done for me it is fine and so I will try to make the best of the snippets of code you gave me. Thank you very much for the help.
172:180 and 145:154 would not be 200 pixels by 200 pixels, it would be 9 by 10. You need to rethink how to place 200 units centered inside 353 units.
Each pixel is surrounded by at least 8 pixels, unless you wish to restrict to the four pixels up + down + left + right. The mask for that would be
[0 1/4 0; 1/4 0 1/4; 0 1/4 0]
and note that in this mask the value of the pixel itself is ignored ("defined as the average of its surrounding 4" does not allow the pixel itself to be considered.)
Billy
Billy on 21 Nov 2012
Edited: Billy on 21 Nov 2012
Is it from 76.5:276 row wise and 50:250? The hint for the average of its surrounding 4 was to use mean of mean function.
You cannot have 1/2 a row; you need to round up or round down.
50:250 would be 201 locations.
You can use mean() if you want, but it will take you more programming than using conv2(). See blockproc()
I checked out block proc, would standard deviation give me the desired effect with the block size of 200 by 200, if so, I think I will just do that.
% blurredGreenChannel = conv2(greenChannel, [0,1,0;1,0,1;0,1,0]/4, 'same');
blurredBlueChannel = conv2(blueChannel, [0,1,0;1,0,1;0,1,0]/4, 'same');
blurredRedChannel = conv2(redChannel, [0,1,0;1,0,1;0,1,0]/4, 'same');
microbes= cat(3, blurredRedChannel, blurredGreenChannel, blurredBlueChannel);
image(microbes)
So I tried this but at the end I ended up with an error that my truecolor Cdata values were out of the range of 0 to 1.
uint8() the values returned by conv2()
blurredBlueChannel = uint8(conv2(blueChannel, [0,1,0;1,0,1;0,1,0]/4, 'same'));
Woah! Thank You, I think I can use this to restrict the blur to just a part of the image. I was wondering why the uint8 fixed the problem of the truecolor values?
When the data class is uint8(), MATLAB expects the range of values to be 0 to 255. When the data class is single precision or double precision, MATLAB expects the range of values to be 0 to 1. You were operating on values that are in the range 0 to 255 (that is, the input was uint8), but conv2() produces a double precision value, leading to double precision values in the range 0 to 255 (with 1/4's and 1/2's possible.) You had to either scale down to 0 to 1, or convert back to uint8.
If just a rectangle is to be blurred, you can blur the whole image and just assign the part that needs to be assigned:
outputImage = inputImage; % Initialize
% Now assign just the rectangle we want from the blurred image.
outputImage(row1:row2, col1:col2) = blurredImage(row1:row2, col1:col2);
Of course you need to specify what the rows and columns are.
So I tried to use the rectangle of (76:275, 51:250) in my 353 by 300 image but my result was a weird thermal image and there is always a warning about conv2 values on values of class uint8 are obsolete. Here is my prgress so far. Is the order of the code incorrect?
if true
% figure
blurredGreen = uint8(conv2(green, [0,1,0;1,0,1;0,1,0]/4, 'same'));
blurredBlue = uint8(conv2(blue, [0,1,0;1,0,1;0,1,0]/4, 'same'));
blurredRed = uint8(conv2(red, [0,1,0;1,0,1;0,1,0]/4, 'same'));
microbes= cat(3, blurredRed, blurredGreen, blurredBlue);
microbe=microbes;
blurred_microbes(76:275, 51:250)=microbe(76:275, 51:250);
image(blurred_microbes)
end
conv2() the double() of the RGB panes.
You do not appear to initialize blurred_microbes ? Is it initialized with your original image? If it is then the order of statements looks okay.
Billy
Billy on 21 Nov 2012
Edited: Billy on 21 Nov 2012
I tried to conv2 the double of the rgb panes, but I did not have enough input arguments and I think I have now intialized blurred_microbes. Here's what's changed. And when I run it I only get a blank figure window.
if true
blurredGreen = uint8(conv2(green, [0,1,0;1,0,1;0,1,0]/4, 'same'));
blurredBlue = uint8(conv2(blue, [0,1,0;1,0,1;0,1,0]/4, 'same'));
blurredRed = uint8(conv2(red, [0,1,0;1,0,1;0,1,0]/4, 'same'));
blurredGreen=conv2(double(blurredGreen));
blurredBlue= conv2(double(blurredBlue));
blurredRed= conv2(double(blurredRed));
microbes= cat(3, blurredRed, blurredGreen, blurredBlue);
blurred_microbes=microbes;
blurred_microbes(76:275, 51:250)=microbes(76:275, 51:250);
image(blurred_microbes)
end
blurredGreen = uint8(conv2(double(green), [0,1,0;1,0,1;0,1,0]/4, 'same'));
Ok I changed it but the image that is resulted is the whole image blurred. does blurred_microbes have to be initialized with the unaltered photo, because in my code, blurred_microbes is = to the microbes that was redefined in the line of code before it.
Billy, look at my last comment above. I tell you how to blur the whole image, but then take just a rectangular region in the original and assign the blurred values to it. If you're still stumped, upload your image and your code and we'll see if we can correct it.
Heres the image and the code I have for this is:
figure
size(microbes);
RR=100;
PX=4;
row=[ceil((353/2))-RR-1:ceil((353/2))+RR];
column=[ceil((300/2))-RR:ceil((300/2))+RR-1];
blurredGreen=uint8(conv2(double(green), [0,1,0;1,0,1;0,1,0]/PX, 'same'));
blurredBlue=uint8(conv2(double(blue), [0,1,0;1,0,1;0,1,0]/PX, 'same'));
blurredRed=uint8(conv2(double(red), [0,1,0;1,0,1;0,1,0]/PX, 'same'));
microbes=cat(3, blurredRed, blurredGreen, blurredBlue);
blurred_microbes=imread('microbes.jpg');
blurred_microbes(row,column)=microbes(row, column);
image(blurred_microbes(row,column))
axis off
You only copied a 2D slice.
blurred_microbes(row,column,:)=microbes(row, column,:);
Billy
Billy on 22 Nov 2012
Edited: Billy on 22 Nov 2012
I really owe guys a big one. I will definitely remember to cite you guys in my assignment. Thanks for putting up with me.
Hold on, One last thing, how would I make this blur of this rectangle apply to my original image. Basically, how do I make it look like the original image outside of that box that I created.
Your code should already do that; the point where you re-read your image and use it to initialize blurred_microbes should result in it looking like your original image outside the box.
By the way, no need to re-read your image: just don't overwrite "microbes" and that variable will remain the original image.
Ya I got it to work all I needed to do was axis image. Thanks again.
What Walter said was 100% accurate. axis image doesn't have anything to do with whether your image is the original image or the blurred image outside of your rectangular ROI. Though sometimes that (axis image) seems to change the aspect ratio, if your aspect ratio got changed for some reason.

Sign in to comment.

More Answers (1)

DGM
DGM on 22 Jun 2022
If the user has Image Processing Toolbox, using roifilt2() or even imfilter()/imgaussfilt() could simplify the task. For a small ROI within a large image, using roifilt2() can avoid excess computations, but it's limited to strictly logical (hard) masking behavior. It tends to lose a lot of that speed advantage when processing RGB images since it has to process each channel independently due to the fact that it only supports single-channel inputs. Whether that's of concern is a question for you to decide.
An example of using roifilt2() on an RGB image can be found here:
An example of doing blurring (hard and soft masks) using basic composition methods and basic MATLAB/IPT tools can be found here:
An example of doing soft-masked blurring using purpose-built composition tools can be found here (the last face-blurring example):

Asked:

on 21 Nov 2012

Answered:

DGM
on 22 Jun 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!