I have an image, and I want to change the color of its background. For example, I want to change the color of the sky from blue to green (or just to pure-white, for simplicity). I have already get the edge of the house, i.e. imgEdges2 (my method of getting the imgEdges2 is very ad-hoc, and any advice for improvement is also welcome), how can I change the color of the sky?

Many thanks!

img = ExampleData[{"TestImage", "House"}]
imgEdges = EdgeDetect[img, 6.7, 0.11];
edgeData = ImageData@imgEdges;
edgeData[[246 ;; 256, All]] = 0;
edgeData[[80 ;; 120, 100 ;; 256]] = 0;
edgeData[[60 ;; 79, 90 ;; 154]] = 0;
edgeData[[50 ;; 59, 90 ;; 110]] = 0;
edgeData[[57 ;; 59, 111 ;; 115]] = 0;
imgEdges2 =Image@edgeData

enter image description here

enter image description here

  • 2
    $\begingroup$ As a first suggestion, you might try something like: Manipulate[ColorReplace[#,First@DominantColors@#->rep,d]&@img,{d,0,.1}] This will more or less work if your background is a solid color and is dominant in the image. You can replace the First with a manual index after DominantColors if it's not dominant. The Manipulate lets you figure out the right thresholding. This doesn't do anything with edge detection or morphological binarization, though—there's certainly more to be done! This gets me this. $\endgroup$ – Ben Kalziqi Jul 27 '18 at 18:57
img = ExampleData[{"TestImage", "House"}];

edge = ImageMultiply[EdgeDetect[ImageSubtract[#3, #] & @@ ColorSeparate[img], 4, 0.04],
    Image[SparseArray[{{i_, j_} /; Min[i, j] <= 100 -> 1}, ImageDimensions[img]]]]

binary = Binarize[ImageMultiply[ImageSubtract[#3, #] & @@ ColorSeparate[img],
    Image[SparseArray[{{i_, j_} /; Min[i, j] <= 100 -> 1}, ImageDimensions[img]]]], 0.12]

sky = Nest[ImageAdd[ImageFilter[Min, ImageFilter[Max, #, 1], 1], edge] &,
           ImageFilter[Min, ImageAdd[binary, edge], 1], 2]

   ImageMultiply[ImageApply[{#[[2]], #[[3]], #[[1]]} &, img], #],
   ImageMultiply[img, ColorNegate[#]]] & /@ {sky, sky - edge}



There are built in functions for this. Remove background


enter image description here

Replace the background with a different color:

RemoveAlphaChannel[RemoveBackground[img], Green]

enter image description here

That works because removal of background is done with help of setting the alpha channel with mask:


enter image description here


Here is how I would do it:

Get the Image:

img = ExampleData[{"TestImage", "House"}];

Use RegionBinarize to get a mask, and then close up the holes:

backgroundMask = ColorNegate[FillingTransform[Closing[RegionBinarize[img, ColorNegate @ Binarize @ img, 0.25], 5]]];

Choose the color to be targetted based on what occurs in the mask:

backgroundColor = RGBColor[Median[DeleteCases[Flatten[ImageData[backgroundMask img], 1], {0., 0., 0.}]]];

Make the replacement through the whole image:

colorReplacedImg = ColorReplace[img, backgroundColor -> Red];

Arithmetic so the replacement is only kept inside the mask:

resultImg = colorReplacedImg backgroundMask + ColorNegate[backgroundMask] img

Very dramatic and maybe unsettling sunset created with ColorReplace


Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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