filling holes in the masked image please help me to replace blue color background of given giraffe image with forest image.

3 views (last 30 days)
i want to fill all the holes in masked image i tried imfill code but still not working on it
and i done but it's not satisfied for me
what i should i do and please tell me where to but the code if you have an idea
this code:
img1=imread('giraffe.jpg'); %reading girrafe image using imread
img2=imread('forest.jpg');%reading forest image using imread
subplot(1,2,1),imshow(img1),title('Giraffe Image');
subplot(1,2,2),imshow(img2),title('Forest Image')
[r, c, b]=size(img1); %Read size of img1,[height, width], resulting in a three dimensional matrix.
size_img2=imresize(img2,[r c]); %resizeing the image same width & highet with giraffe image
Masked_image=createMask(img1); %Calling the fuction which created by Createmask
figure;
imshow(Masked_image),title('Masked Giraffe image'); %show image by imshow
gs=size_img2.*uint8(~Masked_image); %Defining parameters
figure;
fill_holes=imbinarize(Masked_image, 0.1);
imfill(fill_holes,'holes')
%----------------------------------------------------------------------------
I=gs+img1.*uint8(Masked_image); %giraffe image transformed with forest image
A = [1 0.5 0; 0 1 0; 0 0 1]; %Transform the image
tform = affine2d(A); %object stores information about a 2-D affine geometric transformation and enables forward and inverse transformations.
J = imwarp(I,tform); %warp the image using imwarp
imshow(J), title('warp Giraffe in Forest Image');
figure;
subplot(2,1,1),imshow(gs),title('Forest with masked Giraffe Image'); %Subplot plot both images
subplot(2,1,2),imshow(I), title('Giraffe in Forest image');
Createmask code:
function [BW,maskedRGBImage] = createMask_1(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 11-Dec-2022
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.597;
channel1Max = 0.507;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.000;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end

Answers (2)

Cris LaPierre
Cris LaPierre on 12 Dec 2022
I would try using imclose. You can add this to your function, or process the output of your function.
img = imread('giraffe.jpg');
[BW,maskedRGBImage] = createMask_1(img);
% Use morphology to remove small 'holes'
se = strel('disk',4);
closedBW = imclose(BW,se);
figure
imshow(closedBW)
function [BW,maskedRGBImage] = createMask_1(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 11-Dec-2022
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.597;
channel1Max = 0.507;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.000;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
  1 Comment
Cris LaPierre
Cris LaPierre on 13 Dec 2022
You may be interested in going through the Image Processing for Engineering and Science Specialization MathWorks has created on Coursera. It's free to enroll, and will introduce you to this and more. It includes the following courses:
  • Introduction to Image Processing
  • Image Segmentation, Filtering, and Region Analysis
  • Automating Image Processing

Sign in to comment.


DGM
DGM on 13 Dec 2022
Edited: DGM on 13 Dec 2022
See this thread about the same image set. For what it's worth, I didn't have the source images, but it should be a start.
EDIT: Oh. That's a different giraffe. Well. I'm going to follow the examples given in the linked thread, so read that. While this image is more forgiving than the other one, logical masking still has limitations.
% read images
BG = imread('forest.jpg'); % RGB
FG = imread('giraffe.jpg'); % RGB
% create a mask using HSV
FGhsv = rgb2hsv(FG);
hlim = [0.307 0.839];
slim = [0.318 1];
vlim = [0.318 1];
mask = (FGhsv(:,:,1) >= hlim(1)) & (FGhsv(:,:,1) <= hlim(2)) ...
& (FGhsv(:,:,2) >= slim(1)) & (FGhsv(:,:,2) <= slim(2)) ...
& (FGhsv(:,:,3) >= vlim(1)) & (FGhsv(:,:,3) <= vlim(2));
% select a portion of the background and scale it to correspond
sz = imsize(FG,2);
os = [10 0];
w = 265;
h = w/sz(2)*sz(1);
BG = imresize(BG(os(1)+(1:h),os(2)+(1:w),:),sz);
% composite images
outpict = replacepixels(FG,BG,~mask);
% display
imshow(outpict)
Note that I didn't do anything to remove holes. In this particular instance, I didn't need to because of the thresholds I'd used. Especially when dealing with JPG images, single-axis selection in HSV often runs into the ambiguities in the color model. H becomes ambiguous where S is small; S becomes ambiguous where V is small. V is maximized for a broad range of saturated colors that are visually distant from white. It pays to constrain more than one axis.
The above thread links to others which demonstrate basic image composition without using purpose-built tools like MIMT replacepixels(). To keep some things local, this is how it could be done for the case of a logical mask.
% composite images
%outpict = replacepixels(FG,BG,~mask); % requires MIMT
% the rudimentary way
mask = repmat(~mask,[1 1 3]);
outpict = BG;
outpict(mask) = FG(mask);
Note that doing the composition this way relies on the images having the same class, data scale, and number of color channels. It also relies on the mask being an actual logical-class array.
Alternatively, adapting the color-distance example helps here as well. A little extra effort makes the composition more plausible.
% read images
BG = imread('forest.jpg'); % RGB
FG = imread('giraffe.jpg'); % RGB
% find color distance
targetblue = [71.6 -8.752 -40.61];
D = rgb2lab(FG); % convert
D = sqrt(sum((D-ctflop(targetblue)).^2,3)); % color distance in LAB
% construct FG alpha from the distance map
FGA = imadjust(simnorm(D),[0.15 0.5]); % normalize, adjust
% fill interior minima in FGA
FGAfill = imadjust(simnorm(D),[0.2 0.35]); % normalize, adjust
FGAfill = bwareafilt(FGAfill>0.01,1);
FGAfill = mat2gray(bwdist(~FGAfill),[0 4]);
FGA = max(FGA,FGAfill);
% adjust FG color cast
Tr = [0 0 0; 0 0 0; 0 0.02 0.02];
Tg = [0 0 0; 0 0 0; 0 0.02 0.02];
Tb = [0 0 0; 0 0 0; -0.1 -0.05 -0.1];
Tsat = [0.5 0.7 1 1 1];
FG = tonergb(FG,Tr,Tg,Tb,Tsat,'preserve');
% select a portion of the background and scale it to correspond
sz = imsize(FG,2);
os = [10 0];
w = 265;
h = w/sz(2)*sz(1);
BG = imresize(BG(os(1)+(1:h),os(2)+(1:w),:),sz);
% add highlight overlay to BG for emphasis
gradpict = lingrad(size(BG),[0.5 1; 0.5 0],[0 0 0; 68 102 104],'linear');
BG = imblend(gradpict,BG,1,'colordodge',0.5);
% defocus the bg for effect
fk = fspecial('disk',10);
BG = imfilter(BG,fk,'replicate');
% composite images
outpict = replacepixels(FG,BG,FGA);
% display
imshow(outpict)
And you can always go further ...
% read images
BG = imread('forest.jpg'); % RGB
FG = imread('giraffe.jpg'); % RGB
% find color distance
targetblue = [71.6 -8.752 -40.61];
D = rgb2lab(FG); % convert
D = sqrt(sum((D-ctflop(targetblue)).^2,3)); % color distance in LAB
% construct FG alpha from the distance map
FGA = imadjust(simnorm(D),[0.15 0.5]); % normalize, adjust
% fill interior minima in FGA
FGAfill = imadjust(simnorm(D),[0.2 0.35]); % normalize, adjust
FGAfill = bwareafilt(FGAfill>0.01,1);
FGAfill = mat2gray(bwdist(~FGAfill),[0 5]);
FGA = max(FGA,FGAfill);
% adjust overall FG color cast
Tr = [0 0 0; 0 0 0; 0 0.02 0.02];
Tg = [0 0 0; 0 0 0; 0 0.02 0.02];
Tb = [0 0 0; 0 0 0; -0.1 -0.05 -0.1];
Tsat = [0.5 0.7 1 1 1];
FG = tonergb(FG,Tr,Tg,Tb,Tsat,'preserve');
% create a copy of the FG which is further shifted away from blue
Tr = [0 0 0; 0 0 0; 0 0 0];
Tg = [0 0 0; 0 0 0; -0.1 0 0];
Tb = [0 0 0; 0 0 0; -0.4 -0.3 -0.1];
Tsat = [1 1 1 1 1];
FGt = tonergb(FG,Tr,Tg,Tb,Tsat,'preserve');
% composite the two to adjust the fringe areas (e.g. whiskers) where linear blending occurs
FG = replacepixels(FG,FGt,FGAfill);
% select a portion of the background and scale it to correspond
sz = imsize(FG,2);
os = [10 0];
w = 265;
h = w/sz(2)*sz(1);
BG = imresize(BG(os(1)+(1:h),os(2)+(1:w),:),sz);
% add highlight overlay to BG for emphasis
gradpict = lingrad(size(BG),[0.5 1; 0.5 0],[0 0 0; 68 102 104],'linear');
BG = imblend(gradpict,BG,1,'colordodge',0.5);
% defocus the bg for effect
fk = fspecial('disk',10);
BG = imfilter(BG,fk,'replicate');
% try to reconstruct the lost whiskers using an underlay
wk = imadjust(simnorm(D),[0.07 0.35],[1 0]);
wk2 = radgrad(sz,[385 736]./sz,0.25,[0;255],'linear');
wk2 = imadjust(wk2,[0.3 0.7]);
wk = imblend(wk,wk2,1,'screen');
BG = imblend(wk,BG,1,'multiply');
% composite images
outpict = replacepixels(FG,BG,FGA);
% display
imshow(outpict)

Community Treasure Hunt

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

Start Hunting!