How can I change the red chips to black as the red and orange overlap a lot and the edges and shadows are still red/orange with my code.

6 views (last 30 days)
This is my code:
I = imread('coloredChips.png'); % Load original ColoredChips.png image
[rows, columns, channels] = size(I); % Get the dimensions of the image
% Display the original images
subplot(1,2,1);
imshow(I);
% loops are unnecessary
% your mask does not depend on color selection
% and your color selection does not select what you think it selects
% these masks (very) roughly select the chips in the image
maskR = I(:,:,1) > 200 & I(:,:,2) < 60 & I(:,:,3) < 100;
maskG = I(:,:,1) < 50 & I(:,:,2) > 100 & I(:,:,3) < 150;
maskB = I(:,:,1) < 10 & I(:,:,2) < 100 & I(:,:,3) > 220;
% i'm not dealing with a tedious prompt. feel free to change
prompt = 'Specify color you want to change in an image : ';
colormode = input(prompt, 's');
% you can also specify a color other than black
newcolor = [0 0 0];
outpict = I;
switch lower(colormode)
case 'red'
selectedmask = repmat(maskR,[1 1 3]);
case 'green'
selectedmask = repmat(maskG,[1 1 3]);
case 'blue'
selectedmask = repmat(maskB,[1 1 3]);
otherwise
error('ha ha you typed the wrong thing and got an error')
end
outpict(selectedmask) = 0;
outpict = outpict + uint8(selectedmask.*permute(newcolor,[1 3 2]));
% of course, that depends on the class of the input image
subplot(1,2,2);
imshow(outpict);

Accepted Answer

DGM
DGM on 28 Apr 2022
Edited: DGM on 4 Nov 2022
Continuing from this question, I suppose that the masking can be better done in something other than RGB. Getting perfect fits at the edge is going to take some fiddling, and depending on the goals, it might not even be necessary or appropriate. Since I don't know what the requirements are, I'll just throw this out there.
Doing the masking in HSV is easier. The masks can be adjusted as you see fit. As you grow the masks in an attempt to get more of the (e.g.) orange edges, you'll also start selecting red edges and other shadows. You can clean up the speckles and small unwanted selections using bwareaopen().
If you want to simply grow the masks by a small amount, you can use imdilate().
If you want to use a feathered mask, that's a different story.
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);
% these masks roughly select the chips in the image
% rows are [minvalue maxvalue]; columns are [H; S; V]
rangeR = [0.963 0.016; 0.258 1; 0.338 1];
rangeG = [0.380 0.453; 0.258 1; 0.338 1];
rangeB = [0.568 0.648; 0.258 1; 0.338 1];
rangeO = [0.020 0.064; 0.500 1; 0.338 1];
rangeY = [0.153 0.188; 0.338 1; 0.000 1];
hsvpict = rgb2hsv(originalImage);
% i'm not dealing with a tedious prompt. things like this are why function parameters exist.
colormode = 'orange';
%newcolor = [250 50 220];
newcolor = [0 0 0];
outpict = originalImage;
switch lower(colormode)
case 'red'
% this case is different, since the mask has to cross H = 0.
% the logical operations aren't the same for each page,
% so the vectorized approach won't work neatly here.
selectedmask = hsvpict(:,:,1) >= rangeR(1,1) | hsvpict(:,:,1) <= rangeR(1,2) ...
& hsvpict(:,:,2) >= rangeR(2,1) & hsvpict(:,:,2) <= rangeR(2,2) ...
& hsvpict(:,:,3) >= rangeR(3,1) & hsvpict(:,:,3) <= rangeR(3,2);
case 'green'
selectedmask = all(hsvpict >= permute(rangeG(:,1),[2 3 1]),3) ...
& all(hsvpict <= permute(rangeG(:,2),[2 3 1]),3);
case 'blue'
selectedmask = all(hsvpict >= permute(rangeB(:,1),[2 3 1]),3) ...
& all(hsvpict <= permute(rangeB(:,2),[2 3 1]),3);
case 'orange'
selectedmask = all(hsvpict >= permute(rangeO(:,1),[2 3 1]),3) ...
& all(hsvpict <= permute(rangeO(:,2),[2 3 1]),3);
case 'yellow'
selectedmask = all(hsvpict >= permute(rangeY(:,1),[2 3 1]),3) ...
& all(hsvpict <= permute(rangeY(:,2),[2 3 1]),3);
otherwise
error('ha ha you typed the wrong thing and got an error')
end
% clean the mask
selectedmask = bwareaopen(selectedmask,100);
% maybe dilate it if you want
selectedmask = imdilate(selectedmask,ones(3));
% of course, this depends on the class of the input image
selectedmask = uint8(repmat(selectedmask,[1 1 3]));
outpict = outpict.*(1-selectedmask) + selectedmask.*permute(uint8(newcolor),[1 3 2]);
%adjustedimg = imtweak(outpict.*selectedmask,'lchuv',[1 1 -0.30]);
%outpict = outpict.*(1-selectedmask) + adjustedimg;
%subplot(2,1,2);
imshow(outpict);
If you insist on using interactive input() prompts to get the target and replacement colors from the user, refer to this hint:

More Answers (0)

Community Treasure Hunt

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

Start Hunting!