# Changing color of an object in an image

Consider the following image:

How can I change all red colors in this image into (for example) blue.

-

Here's a version using Manipulate with a Locator to pick the colour to replace. There is also a tolerance control which determines how wide a range of hues to replace.

i=Import["http://i.stack.imgur.com/Qr7Tx.jpg"];

{h,s,b}=ColorSeparate[i,"HSB"];

colourchange[c_,from_,tol_,to_]:=Module[
{offset=Mod[c-from+0.5,1]-0.5},
If[Abs[offset]>tol,c,to]];

Manipulate[
ColorCombine[
{ImageApply[colourchange[#,ImageValue[h,pos],tol,ColorConvert[to,Hue][[1]]]&,h],s,b},
"HSB"],
{{to,Blue,"Change to"},Blue},
{{tol,-0.01,"Tolerance"},-0.01,0.5},
{{pos,{100,50}},Locator}]


-
You could also add a polygon defined by other locators, to define the mask of impact... – P. Fonseca Apr 27 '12 at 10:11
Or use another locator as a brush – Simon Woods Apr 27 '12 at 10:48
...and I see a full image-processing graphical suit a la Photoshop implemented in Mathematica coming up soon... – István Zachar Apr 27 '12 at 13:25
@Simon Woods: nice approach! I like that one but still: see the two people on the left hand side of the ball? The went blue too. How one avoid that? – John Apr 27 '12 at 18:44

I wanted to change only the color of the ball, leaving all other red objects untouched:

getReds[x_Image] := First@ColorSeparate[x, "Hue"]
isolateSphere[x_Image] := SelectComponents[Binarize[getReds[x], .9], Large]
makeMask[x_Image] := Image@Graphics[ Disk @@ (1 /.
{PlotRange -> Thread[{1, #}], ImageSize -> #} &@ImageDimensions@x]
shiftColors[x_Image] := Image[ImageData[getAreaToChange[x]] /.
p: {r_, g_, b_} /; r > .3 :> RotateLeft[p, 1]]

{#, getReds@#, isolateSphere@#, makeMask@#, getAreaToChange@#, shiftColors@#, finishIt@#} &
@Import["http://i.stack.imgur.com/Qr7Tx.jpg"]


Comparing side to side:

-
Nice. What should one change to change the from and to colors? Or it only works for red and blue? – Rojo Apr 26 '12 at 18:30
+1 Nice. What would you have done if there were other instances of red in the picture that you did not want to alter? – DavidC Apr 26 '12 at 18:51
@Rojo In fact Red is the most difficult case, since it is at the beginning and at the end of the Hue[] table. Try Graphics[Raster[Table[{h, s, 1}, {s, 0, 1, .01}, {h, 0, 1, .01}], ColorFunction -> Hue]] – Dr. belisarius Apr 26 '12 at 19:19
@DavidCarraher That happens usually in image processing. Things like "reddish" and "the big thingie in the middle" are not as easy to program as CylindricalDecomposition[] :) – Dr. belisarius Apr 26 '12 at 21:28
Congrats on your (soon to be awarded) populist badge! :) – R. M. Apr 30 '12 at 2:30

A one-liner:

i = Import["http://i.stack.imgur.com/Qr7Tx.jpg"];

Image[ImageData[i] /. {r_, g_, b_} /; r > g && r > b -> {b, g, r}]


-
ImageApply[RotateLeft, i] have a same effect. :) – yode Jun 28 at 8:59

# First Method

If you just want to get different color of your ball,but don't want to name the color.I will recommend you this solution,which makes your life easier.In the meantime,it will change other place's color,not just the ball,like CSP's answer

img = Import["http://i.stack.imgur.com/Qr7Tx.jpg"];
Select[ColorCombine /@ Tuples[ColorSeparate[img], {3}],
ImageMeasurements[ColorDistance[ColorConvert[#, "Grayscale"], #],
"Total"] > 8000 &]


You get 20 different color ball by a line code.

# Second Method

If you just want to change your ball's color with a specified color and want maintain other place,like Dr. belisarius' answer,I make a custom function for you to do this

ChangeColor[img_, color_] :=
Dilation[
DeleteSmallComponents[
ChanVeseBinarize[
KarhunenLoeveDecomposition[
ColorCombine /@ Permutations[ColorSeparate[img]]][[1, 2]]]],
ColorConvert[
ColorCombine[
Prepend[Rest[
First[ColorSeparate[
ImageMultiply[
ConstantImage[color, ImageDimensions[img],
ColorSpace -> "HSB"], mask]]]], "HSB"], "RGB"]]]


Usage:

ChangeColor[img, #] & /@ RandomColor[5]


-
It seems that the background change in the first solution, so I prefer the second one – Wjx Jun 28 at 9:07
@Wjx Thanks. :) – yode Jun 28 at 9:10
ChanVeseBinarize[] looks to be the key component here. – J. M. Jun 28 at 13:54