Changing one color to another in a RGB image

7 ビュー (過去 30 日間)
Larry Muester
Larry Muester 2019 年 1 月 29 日
コメント済み: DGM 2022 年 3 月 22 日
I have a RGB image and I want to turn all of the white portions of it to red. What I have so far is
rgbImage = imread('rainbow.jpg');
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
whitePixels = redChannel == 255 & greenChannel == 255 & blueChannel == 255;
redChannel(whitePixels) = 255;
greenChannel(whitePixels) = 0;
blueChannel(whitePixels) = 0;
rgbImage1 = cat(3, redChannel, greenChannel, blueChannel);
image(rgbImage1)
However, the code simply returns the original image without any changes.
rgbImage is of type uint8 whereas whitePixels is of type logical. Would this have any affect on the outcome?
  5 件のコメント
Adam
Adam 2019 年 1 月 30 日
編集済み: Adam 2019 年 1 月 30 日
Look at
nnz( whitePixels )
in your code also to see if there are actually any white pixels picked up by your logic.
When I run your code on 'gantrycrane.png', which is the only Matlab-based image I could remember off the top of my head!, I get 8 white pixels and when I visualise the end result I can see they have turned red.
Walter Roberson
Walter Roberson 2019 年 1 月 30 日
And remember that .jpg blurs sharp lines so what looks like pure white might not be exactly pure white.

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

回答 (2 件)

DGM
DGM 2022 年 3 月 22 日
編集済み: DGM 2022 年 3 月 22 日
I kind of wish this weren't a dead question. Oh well.
You could certainly try to do a logical masking operation. Depending on your image and goals, that might be appropriate, or it might not. The given filename implies an image with smooth color transitions. That sounds like a bad case for using a logical masking approach.
Consider the following image:
As Walter says, your mask doesn't select anything except [255 255 255]. Even a more lenient mask specification will produce ugly results:
inpict = imread('rainbow.png');
th = 240;
whitePixels = repmat(all(inpict >= th,3),[1 1 3]);
outpict = inpict;
outpict(whitePixels) = repmat(permute([255 0 0],[1 3 2]),[nnz(whitePixels)/3 1]);
imshow(outpict)
Depending on the goals, this may be the desired outcome. If appearances are what's important, then maybe this isn't a very good approach.
You could take the image saturation and use that as a mask for multiplicative composition:
inpict = imread('rainbow.png');
s = size(inpict);
hsvpict = rgb2hsv(inpict);
colorpict = repmat(permute([255 0 0],[1 3 2]),s(1:2));
satmap = hsvpict(:,:,2); % a map of color saturation
% compose image
outpict = uint8(double(inpict).*satmap + colorpict.*(1-satmap));
imshow(outpict)
If desired, you could adjust the slope and extent of the mask with imadjust():
inpict = imread('rainbow.png');
s = size(inpict);
hsvpict = rgb2hsv(inpict);
colorpict = repmat(permute([255 0 0],[1 3 2]),s(1:2));
satmap0 = hsvpict(:,:,2);
% a simple gamma adjustment to reduce extent of color replacement
satmap = imadjust(satmap0,[0 1],[0 1],0.5);
outpict = uint8(double(inpict).*satmap + colorpict.*(1-satmap));
imshow(outpict)
% a simple gamma adjustment to increase extent of color replacement
satmap = imadjust(satmap0,[0 1],[0 1],2);
outpict = uint8(double(inpict).*satmap + colorpict.*(1-satmap));
imshow(outpict)
More to the general question as stated in the title, how can this be generally applied to any color? Consider the following example wherein green is replaced with purple. This is similar to the decomposition used by GIMP's "Color to Alpha" tool, though without the corrections.
inpict = imread('rainbow.png');
incolor = [0 1 0];
outcolor = [0.6 0 1];
% create a mask
inpict = im2double(inpict);
mask = zeros(size(inpict));
s = size(inpict);
for c = 1:3
if incolor(c) < 0.0001
mask(:,:,c) = inpict(:,:,c);
else
cdiff = abs(inpict(:,:,c)-incolor(c));
mA = inpict(:,:,c) > incolor(c);
mB = inpict(:,:,c) < incolor(c);
mask(:,:,c) = cdiff./(1-incolor(c)+eps) .* mA + cdiff./incolor(c) .* mB;
end
end
mask = max(mask,[],3);
% compose image
outcp = repmat(permute(outcolor,[1 3 2]),s(1:2));
outpict = im2uint8(inpict.*mask + outcp.*(1-mask));
imshow(outpict)
That works, though maybe the transitions aren't the best. Doing the operations in linear RGB might help, but this is already getting pretty complicated.
The aforementioned GIMP tool is replicated in MIMT's color2alpha(). Combining that with MIMT imblend(), we can get this with relatively simple syntax:
inpict = imread('rainbow.png');
incolor = [0 1 0];
outcolor = [0.6 0 1];
s = size(inpict);
outcp = colorpict(s,outcolor); % a solid color RGB image
tppict = color2alpha(inpict,incolor); % an RGBA image
outpict = imblend(tppict,outcp,1,'normal'); % compose
outpict = outpict(:,:,1:3); % strip alpha
imshow(outpict)
As mentioned, this composition can also be done in linear RGB without complication:
outpict = imblend(tppict,outcp,1,'normal','linear'); % compose
outpict = outpict(:,:,1:3); % strip alpha
imshow(outpict)
Depends what suits the situation.
  2 件のコメント
Image Analyst
Image Analyst 2022 年 3 月 22 日
It's not necessarily dead. We find that many, many times people reply to very old threads, so the threads are still being accessed and people are still learning from them even though they're old, so it's not a bad idea to add an answer, especially if there is not any answers yet.
By the way, I'm attaching my color change demos that I posted for other questions.
DGM
DGM 2022 年 3 月 22 日
While I justify it by observing the current traffic on old posts, I still feel a tiny bit bad when I stir things back to the top of the recent queue just because I'm bored and disinterested in the current questions that people actually want answered.
Then I remember that this isn't a job.

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


Image Analyst
Image Analyst 2022 年 3 月 22 日
See attached demos from my huge list of over 400 old demos I've posted before.
Adapt as needed.

カテゴリ

Help Center および File ExchangeImage Processing Toolbox についてさらに検索

製品


リリース

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by