Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Consider the following image:

Red ball in a non-red environment

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

share|improve this question
add comment

3 Answers

up vote 30 down vote accepted

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}]

enter image description here

share|improve this answer
1  
You could also add a polygon defined by other locators, to define the mask of impact... –  P. Fonseca Apr 27 '12 at 10:11
2  
Or use another locator as a brush –  Simon Woods Apr 27 '12 at 10:48
2  
...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
3  
@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
add comment

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 /. 
                        ComponentMeasurements[isolateSphere[x], {"Centroid","BoundingDiskRadius"}]), 
                        {PlotRange -> Thread[{1, #}], ImageSize -> #} &@ImageDimensions@x]
getAreaToChange[x_Image] := ImageMultiply[i, ColorNegate@makeMask[x]]
shiftColors[x_Image] := Image[ImageData[getAreaToChange[x]] /. 
                                                      p: {r_, g_, b_} /; r > .3 :> RotateLeft[p, 1]]
finishIt[x_Image] :=  ImageAdd[ImageMultiply[x, makeMask[x]], ColorConvert[shiftColors[x], "RGB"]]

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

Mathematica graphics

Comparing side to side:

Mathematica graphics

share|improve this answer
    
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? –  David Carraher Apr 26 '12 at 18:51
2  
@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]] –  belisarius Apr 26 '12 at 19:19
6  
@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[] :) –  belisarius Apr 26 '12 at 21:28
2  
Congrats on your (soon to be awarded) populist badge! :) –  rm -rf Apr 30 '12 at 2:30
show 8 more comments

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}]

enter image description here

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.