How to apply Gaussian blur to a specific area (oval) in an image?

26 ビュー (過去 30 日間)
Neuro
Neuro 2023 年 5 月 8 日
コメント済み: Neuro 2023 年 5 月 9 日
Hi. I have an image processing problem. I have images of faces (JPG, freely available for research purposes) which I inserted in gray ovals (see example below). All images share the same dimensions. My question: how can you apply Gaussian blur to the pixels around the edge of the oval, i.e., where the pixels of the oval edge and the face image meet. My aim is to decrease contrast in the specific perimeter so the faces look embedded in their gray background.
Can someone help me with this?
This is the script I wrote to add the gray oval, but I haven't figured out how to add the Gaussian blur:
% Specify the input and output directories
input_dir = '/X';
output_dir = '/Y';
% Get a list of all the JPG files in the input directory
file_list = dir(fullfile(input_dir, '*.jpg'));
% Loop over each file in the list
for i = 1:numel(file_list)
% Load the image
img = imread(fullfile(input_dir, file_list(i).name));
% Get the size of the image
[rows, cols, ~] = size(img);
% Create a meshgrid of x and y coordinates
[x, y] = meshgrid(1:cols, 1:rows);
% Calculate the x and y coordinates of the center of the image
center_x = (cols+1)/2;
center_y = (rows+1)/2;
% Calculate the radius of the oval
radius_x = center_x - 1;
radius_y = center_y - 1;
% Create a mask for the oval using the x and y coordinates, center, and radii
mask = ((x-center_x)/radius_x).^2 + ((y-center_y)/radius_y).^2 <= 1;
% Create a copy of the original image with the contour region masked out
masked_img = img;
masked_img(repmat(~mask, [1, 1, 3])) = 220;
% Construct the output filename with 'REG' at the end
[~, filename, ext] = fileparts(file_list(i).name);
output_filename = [filename, 'REG', ext];
% Save the masked image to the output directory with the modified filename
imwrite(masked_img, fullfile(output_dir, output_filename));
end

採用された回答

DGM
DGM 2023 年 5 月 8 日
編集済み: DGM 2023 年 5 月 8 日
ideally, you'd do this during composition instead of afterwards. Doing it afterwards is double the work.
Here is one example
And here's a more rudimentary example without specialized tools
The rest is the task of generating the mask.
Here is an example of doing the composition, starting with an image, a background color, and a logical mask.
% load foreground image
FG = imread('cameraman.tif'); % raw single-channel source
% background color
BG = [0.4 0.04 0.25]; % any color tuple
% mask parameters
center = [128 128]; % [x y]
radius = 128;
blurwidth = 30;
% i assume you start with a logical mask
% you can create this interactively with drawcircle() or drawellipse()
% but i'm going to do it programmatically
imshow(FG);
ROI = images.roi.Circle(gca);
ROI.Center = center;
ROI.Radius = radius-blurwidth/2; % create the mask undersize
mask = createMask(ROI);
% soften the mask
mask = imgaussfilt(double(mask),blurwidth/4);
% compose the foreground image with the solid-color background
outpict = im2double(FG).*mask + permute(BG,[1 3 2]).*(1-mask);
outpict = im2uint8(outpict);
imshow(outpict,'border','tight')
Note that I created the mask undersize to begin with instead of eroding it. This is simpler and helps avoid complications if the mask ever gets close to the image border.
EDIT: This is an example doing the same thing with an ellipse ROI object instead
% load foreground image
FG = imread('cameraman.tif'); % raw single-channel source
% background color
BG = [0.4 0.25 0.04]; % a tuple
% mask parameters
center = [128 128]; % [x y]
semiaxes = [150 90];
angle = -45;
blurwidth = 30;
% i assume you start with a logical mask
% you can create this interactively with drawcircle() or drawellipse()
% but i'm going to do it programmatically
imshow(FG);
ROI = images.roi.Ellipse(gca);
ROI.Center = center;
ROI.SemiAxes = semiaxes-blurwidth/2;
ROI.RotationAngle = mod(angle,360);
mask = createMask(ROI);
% soften the mask
mask = imgaussfilt(double(mask),blurwidth/4);
% compose the foreground image with the solid-color background
outpict = im2double(FG).*mask + permute(BG,[1 3 2]).*(1-mask);
outpict = im2uint8(outpict);
imshow(outpict,'border','tight')
  4 件のコメント
DGM
DGM 2023 年 5 月 8 日
Try this. I removed some parts so that I can run it here as a demo.
% parameters
blurwidth = 20;
bgcolor = 220/255;
% get file list, etc
% ...
% Loop over each file in the list
%for i = 1:numel(file_list)
% Load the image
% ...
% for sake of the demo, i'm reusing this image
img = imread('cameraman.tif');
% Get the size of the image
[rows, cols, ~] = size(img);
% Create a meshgrid of x and y coordinates
[x, y] = meshgrid(1:cols, 1:rows);
% Calculate the x and y coordinates of the center of the image
center_x = (cols+1)/2;
center_y = (rows+1)/2;
% Calculate the radius of the oval
radius_x = center_x - 1 - blurwidth/2;
radius_y = center_y - 1 - blurwidth/2;
% Create a mask for the oval using the x and y coordinates, center, and radii
mask = ((x-center_x)/radius_x).^2 + ((y-center_y)/radius_y).^2 <= 1;
% soften the mask
mask = imgaussfilt(double(mask),blurwidth/4);
% Create a copy of the original image with the contour region masked out
masked_img = im2double(img).*mask + permute(bgcolor,[1 3 2]).*(1-mask);
masked_img = im2uint8(masked_img);
% show it for sake of the demo
imshow(masked_img)
% write the file
% ...
%end
Neuro
Neuro 2023 年 5 月 9 日
@DGM Thanks! This worked wonderfully :)

サインインしてコメントする。

その他の回答 (2 件)

Matt J
Matt J 2023 年 5 月 8 日
編集済み: Matt J 2023 年 5 月 8 日
1.Make a logical mask of the oval
2. Erode the mask by 1 pixel (imerode)
3. Use imgaussfilt to filter the whole image
4. Restore the pixels in the interior of the oval using the mask from step 2

Image Analyst
Image Analyst 2023 年 5 月 8 日
Use imgaussfilt on the whole image. Then get an annular mask that is just the edges of the oval. Replace the pixels in that annular mask region of the original iamge with the blurred pixels. Let me know if you can't figure it out.

製品


リリース

R2022b

Community Treasure Hunt

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

Start Hunting!

Translated by