Chang a color in an image to black

9 views (last 30 days)
Khoa Tran
Khoa Tran on 21 Jul 2021
Commented: Khoa Tran on 21 Jul 2021
Hi everyone, i have this code to change a color in the image that i want to black (by entering the name of color). But i got a problem with orange because when i tried to change the orange, it mix with red color. Can anyone tell me how to fix this?
clc;
originalImage = imread('coloredChips.png'); % Load original ColoredChips.png image
[rows, columns, channels] = size(originalImage); % Get the dimensions of the image
% Check if the iamge is not RGB
if channels~=3
error('the image needs to be RGB')
end
% Display the original image
subplot(2,1,1);
imshow(originalImage);
% These masks select the chips in the image
maskR = originalImage(:,:,1) >= 173 & originalImage(:,:,2) < 68 & (10 < originalImage(:,:,3) & originalImage(:,:,3) < 200);
maskG = originalImage(:,:,1) < 60 & originalImage(:,:,2) > 100 & originalImage(:,:,3) < 150;
maskB = originalImage(:,:,1) < 20 & (30 < originalImage(:,:,2) & originalImage(:,:,2) < 100) & originalImage(:,:,3) > 150;
maskY = originalImage(:,:,1) > 200 & originalImage(:,:,2) > 200 & originalImage(:,:,3) < 160;
maskO = (originalImage(:,:,1) > 120 & originalImage(:,:,1) < 255) & (originalImage(:,:,2) < 55 & originalImage(:,:,3) < 20) | (originalImage(:,:,2) > 50 & originalImage(:,:,2) < 122) & originalImage(:,:,3) < 80;
%Change the color to blackre
black = [0 0 0];
% Create the new image from orginal image
newImage = originalImage;
% Taking input from user
color = input('Enter color to remove: ', 's');
% Change the color according to the input
while true
if (lower(color) == "red")
selectedmask = repmat(maskR,[1 1 3]);
break
elseif (lower(color) == "green")
selectedmask = repmat(maskG,[1 1 3]);
break
elseif (lower(color) == "blue")
selectedmask = repmat(maskB,[1 1 3]);
break
elseif (lower(color) == "yellow")
selectedmask = repmat(maskY,[1 1 3]);
break
elseif (lower(color) == "orange")
selectedmask = repmat(maskMagenta,[1 1 3]);
break
else
disp("Wrong color or Color not found.");
break
end
end
newImage(selectedmask) = 0;
newImage = newImage + uint8(selectedmask.*permute(black,[1 3 2]));
% Display the new image
subplot(2,1,2);
imshow(newImage);

Accepted Answer

DGM
DGM on 21 Jul 2021
Edited: DGM on 21 Jul 2021
Improving selectivity of the orange mask is really only half the battle; you'd need to also restrict the red mask to keep them from overlapping -- but maybe this isn't the best approach anyway. The red and reddish-orange chips contain colors which are poorly separated in RGB. It's not merely that they are close to each other, it's that they lie in a volume which cannot be trivially selected by a rectangular box selection as the above RGB thresholds generate. Let's use the Color Thresholder app to look at where the color points lie:
It would be impractical to separate them in RGB using non-overlapping box selections. It also explains why it's hard to include the dark edges of the chips in the selection. Of course, I'm using a simplified image to just describe red versus orange. In reality, you have to deal with trying to isolate the chips from the background and everything else too, so you can see why RGB gets problematic:
In HSV and YCC, the color points are well-separated, but the CT app only allows polar selections in HSV, not in YCC or other models. It may be easiest to perform the selections in HSV, though you're going to have to change some things for that to work. If you select HSV and continue, you can generate a selection interactively and then export it as a function template. The primary thing to note is that the HSV image will be floating point, in the range [0 1]. We're still doing a box selection, but in quasi-polar coordinates, so the selected volume isn't a rectangular prism anymore.
Again, loops aren't necessary, but some things could be rearranged to make the new selections easier to build.
originalImage = imread('coloredChips.png'); % Load original ColoredChips.png image
[rows, columns, channels] = size(originalImage); % Get the dimensions of the image
if channels~=3
error('the image needs to be RGB')
end
% Display the original images
subplot(2,1,1);
imshow(originalImage);
% instead of building all the masks first, let's just define the thresholds
hsvpict = rgb2hsv(originalImage);
thR = [0.961 1; 0.578 1; 0 1];
thG = [0.402 0.453; 0.578 1; 0 1];
thB = [0.578 0.642; 0.578 1; 0 1];
thO = [0.019 0.073; 0.578 1; 0 1];
thY = [0.150 0.184; 0.578 1; 0 1];
% select the nominal chip color
colormode = 'orange';
outpict = originalImage;
switch lower(colormode)
case 'red'
selectedth = thR;
case 'green'
selectedth = thG;
case 'blue'
selectedth = thB;
case 'orange'
selectedth = thO;
case 'yellow'
selectedth = thY;
otherwise
error('you got an error')
end
% make the selection as a closed box
selectedmask = (hsvpict(:,:,1) >= selectedth(1,1)) & (hsvpict(:,:,1) <= selectedth(1,2)) & ...
(hsvpict(:,:,2) >= selectedth(2,1)) & (hsvpict(:,:,2) <= selectedth(2,2)) & ...
(hsvpict(:,:,3) >= selectedth(3,1)) & (hsvpict(:,:,3) <= selectedth(3,2));
% clean up selection to get rid of cross-selection in shadow areas
selectedmask = bwareaopen(selectedmask,100);
% if color replacement isn't needed, this simplifies
selectedmask = repmat(selectedmask,[1 1 3]);
outpict(selectedmask) = 0;
subplot(2,1,2);
imshow(outpict);
Red and orange are still very close to each other and overlap in the shadow regions. The color selection technique gives us an adequate, but not completely unique selection between red and orange. The small isolated cross-selected regions can be removed using basic morphological operations.

More Answers (1)

Walter Roberson
Walter Roberson on 21 Jul 2021
elseif (lower(color) == "orange")
selectedmask = repmat(maskMagenta,[1 1 3]);
You do not define maskMagenta in your code, and it seems unlikely that you want to use a magenta mask for orange.
  1 Comment
Khoa Tran
Khoa Tran on 21 Jul 2021
sorry, maskMagenta is maskO, i changed it but it still mix

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!