Change a specific color in an image to another one

19 views (last 30 days)
I want my program to change a color in the user's input in coloredChips.png to black. How can i do it? I have tried but it failed. As you can see, i input RED but the image is still red, not black.
format compact
clc;
close all;
clear;
originalImage = imread('coloredChips.png'); % Load original ColoredChips.png image
[rows, columns, numberOfColorBands] = size(originalImage); % Get the dimensions of the image
% Display the original images
subplot(2,1,1);
imshow(originalImage);
% Extract the individual red, green, and blue color channels.
redChannel = originalImage(:, :, 1);
greenChannel = originalImage(:, :, 2);
blueChannel = originalImage(:, :, 3);
black = redChannel == 0 & greenChannel == 0 & blueChannel == 0;
color = input("Enter color to remove(RED,GREEN,BLUE): ", 's'); % taking input from user
for row = 1 : rows %iterating over each pizel of image
for column = 1 : columns
if color == "RED"
originalImage(black) = 0; % if input is red we'll make red channel value for this pixel to 0
elseif color == "GREEN"
originalImage(black) = 0; % if input is green we'll make red channel value for this pixel to 0
else
originalImage(black) = 0; % if input is green we'll make red channel value for this pixel to 0
end
end
end
rgb = cat(3, redChannel, greenChannel, blueChannel);
subplot(2,1,2);
imshow(rgb);
  2 Comments
KSSV
KSSV on 14 Jul 2021
Why you have failed? What is your input and expected output? You should attach images for help.
Khoa Tran
Khoa Tran on 14 Jul 2021
sorry, so this is my result. The red color is still the same. I want it to be black

Sign in to comment.

Accepted Answer

DGM
DGM on 14 Jul 2021
Edited: DGM on 2 May 2022
EDIT 5/2022: I've posted a number of variations of answers on this same question. For a more comprehensive answer of this same assignment, see this post. For a more elaborate color replacement task using the same image, see this post.
ORIGINAL ANSWER:
Bear with me. My connection is worse than normal, and the scripts on this site simply break below about 300 kbps. I can't afford to include any images, and this will probably take a dozen attempts to post.
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);
% 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 = originalImage(:,:,1) > 200 & originalImage(:,:,2) < 100 & originalImage(:,:,3) < 100;
maskG = originalImage(:,:,1) < 50 & originalImage(:,:,2) > 100 & originalImage(:,:,3) < 150;
maskB = originalImage(:,:,1) < 10 & originalImage(:,:,2) < 100 & originalImage(:,:,3) > 220;
% i'm not dealing with a tedious prompt. feel free to change
colormode = 'Green';
% you can also specify a color other than black
newcolor = [250 50 220];
outpict = originalImage;
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(2,1,2);
imshow(outpict);
EDIT: modified to fix copypaste error and added option to specify replacement color.
  6 Comments
DGM
DGM on 14 Jul 2021
Edited: DGM on 14 Jul 2021
Well in a general sense, what's going on is we're looking at the values in the individual color channels and comparing them against some selected thresholds. The result is the intersection of those three logical masks, and is itself a single-channel logical image with the same height and width as the original image.
More specifically, the color that's being selected isn't as broad as just "red". It's a range of reddish colors which dominate the red chips from this particular image. If you open the original image with imshow() and use the datatip tool, you can inspect the red chips and see what typical color values look like. I just picked some threshold values that roughly select the chips. How exact the selection needs to be depends on the goal, but more exact selections may be easier to achieve using a color model other than RGB. Using both upper and lower thresholds per channel would also help improve the selectivity of the process.
Tangentially, if the goal is to simply adjust the color of certain objects, this entire approach might not be the best way. Masking and filling obliterates any sort of texture or contour present in the masked area. Adjusting the hue or other color properties may be an alternative, depending on the goals. For example:
% ...
selectedmask = uint8(repmat(selectedmask,[1 1 3])); % as before
% instead of replacing the region with a solid color
% simply adjust the color properties of the region
adjustedimg = imtweak(outpict.*selectedmask,'lchuv',[1 1 -0.30]);
outpict = outpict.*(1-selectedmask) + adjustedimg;
% ...
The above code uses imtweak() from MIMT on the File Exchange, but there are other ways. This is just an example of the concept.

Sign in to comment.

More Answers (1)

Dhruv G
Dhruv G on 14 Jul 2021
The issue here is you aren't changing redChannel, blueChannel or greenChannel anywhere. I'm not sure what you are trying to do with the black variable. If you want to do something like make a pixel black if it's redChannel is higher than a threshold and the others are lower, you should do something like the following in your if statement (the code I've written is for RED):
highthresh = 180
lowthresh = 60
if color=='RED'
if redChannel(row,column) > highthresh & blueChannel(row,column) < lowthresh & greenChannel(row,column) < lowthresh
redChannel(row,column) = 0;
blueChannel(row,column) = 0;
greenChannel(row,column) = 0;
end
end
  3 Comments
Dhruv G
Dhruv G on 14 Jul 2021
Right, so you would classify a pixel as red if it's red channel is higher than some threshold and the other channels lower than a threshold. Then you would want to make that pixel black (setting all channels of that pixel to 0)

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!