Change specific color in an image to another one
367 views (last 30 days)
I am trying to change colors in an image into another color. I have generated some code myself but something seems to be wrong. What I am trying to achieve on the attached file is to change every purple data point into a green data point, or whatever color I would prefer. Currently, the code that I have written is able to change purple to green but the edges of the marked points are still in purple, I believe this has something to do with the intensity at the edges being different or something...
[I,m] = imread('iteration31.png');
%image = imshow(I,'Colormap',m);
rgbImage = ind2rgb(I,m);
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
purplePixels = redChannel == 1 & greenChannel == 0 & blueChannel == 1;
% MAKE THEM GREEN
redChannel(purplePixels) = 0;
greenChannel(purplePixels) = 1;
blueChannel(purplePixels) = 0;
rgbImage = cat(3, redChannel, greenChannel, blueChannel);
Matthew Eicholtz on 5 May 2017
This is a tough problem. Since you are using a raster image, objects that look purple are actually many small variations of purple. One thing you could try to do is compute which colors are purple-ish, and then modify those colors in the colormap.
Here is an example that may yield slightly better results than what you were experiencing, but still not perfect:
% Read image
[I,m] = imread('iteration31.png');
% Find purple-ish colors
mask1 = abs(m(:,3)-m(:,1))<0.8;
mask2 = abs(m(:,3)-m(:,2))>0.3;
mask3 = abs(m(:,2)-m(:,1))>0.3;
mask = mask1 & mask2 & mask3;
% Convert purple-ish colors to green-ish colors
m(mask,:) = 1-m(mask,:);
% Create and show newly colored image
rgb = ind2rgb(I,m);
More Answers (1)
DGM on 4 Sep 2022
Consider the following example using the OP's original image and task.
% Load image
[idxpict,ct] = imread('iteration31.png');
rgbpict = im2uint8(ind2rgb(idxpict,ct));
% Play around with the thresholds until you get what you want.
thresholds = [0.82 0.85]; % [Hmin Hmax]
hsvpict = rgb2hsv(rgbpict);
isPurple = hsvpict(:,:,1)>0.82 & hsvpict(:,:,1)<0.85;
% clean up the mask
isPurple = imerode(isPurple,ones(2));
% dilate it to hopefully include the extremes of the region extent
isPurple = imdilate(isPurple,ones(3));
imshow(isPurple(250:450,1200:1350,:)) % show a closeup of the mask
% expand to simplify addressing later
isPurpleArray = repmat(isPurple,1,1,3);
% Once you're happy with your thresholds above, adjust the image content.
hsvpict(:,:,1) = mod(hsvpict(:,:,1)-0.5,1); % rotate hue by 180d
adjpict = hsv2rgb(hsvpict);
% combine the adjusted image and the original using logical composition
% images must be the same class and scale
outpict = rgbpict;
outpict(isPurpleArray) = im2uint8(adjpict(isPurpleArray));
% Compare the original and new image.
This is a relatively simplified case since the colored dots are well separated by neutral colors. In this scenario, there's little harm in making the mask overselect the dots. If the background were not neutral, things would be different.
I've posted a number of answers to "change one color to another" problems. The above example uses no special tools, but some of the other examples use freely available third party tools.
Change the colors in a smoothly-graduated rainbow image (uses MIMT color2alpha())
Naive channel swap, hard masked filling/tweaking, lin masked colorization (color chips against table)
Color squares example (hue rotate, hue replace, solid fill; (mostly MIMT)
Pink strawberries (HSV segmentation & adjustment; no MIMT)
Change hair color (colorization of black objects and the challenges of realism)