# Speed up image coloring with ReplaceImageValue

I have about 200000 rgb-images of such format (2160*577 pixels):

I want to colorize in each image some parts in white color:

To do so I am using the following code (i1 is the source image, i2 the colored image):

i2 = ReplaceImageValue[i1, {All, 1 ;; 20} -> White];
i2 = ReplaceImageValue[i2, {All, 557 ;; 577} -> White];
i2 = ReplaceImageValue[i2, {1 ;; 20, All} -> White];
i2 = ReplaceImageValue[i2, {2141 ;; 2160, All} -> White];
i2 = ReplaceImageValue[i2, {701 ;; 740, All} -> White];
i2 = ReplaceImageValue[i2, {1421 ;; 1460, All} -> White]


which needs about 6 sec for a single image.

The result is:

So, if I want to do that for all the images I would need to wait for 1.2*10^6 sec which are more than 13 days.

Is there a way to make my code much faster?

• Are the replacements applied to all images, or are there different replacements for different images? – J. M. will be back soon Jun 16 '15 at 12:28
• The replacements are exactly the same for all images – mrz Jun 16 '15 at 12:32
• If you are just trying to break the image up in three separate equal-sized rectangles separated by white strips, take a look at ImagePartition – m_goldberg Jun 16 '15 at 12:43

## 2 Answers

Here is a version that should be superior to your attempt. I'm using ImagePartition (as already suggested by m_goldberg) to rip your original image apart at 1/3 of the image width. After that you use a negative ImagePad to remove 20 pixel and again a positive ImagePad to add a 20 pixel white border.

For processing a large number of images, it definitely help to do this in parallel. Remember to make everything in parallel: The importing, the splitting and the exporting.

splitImage[img_] := ImageAssemble[
ImagePad[ImagePad[#, -20], 20, 1] & /@
Flatten@ImagePartition[img, ImageDimensions[img]/{3, 1}]]

img = Import["http://i.stack.imgur.com/BCScO.png"];
splitImage[img]; // AbsoluteTiming
(* {0.016326, Null} *)


Without taking importing time of the images into account this needs about 55 minutes for all your 200.000 images.

• 200,000 images ... – mrz Jun 16 '15 at 13:35
• @kale Fixed. It was 200.000 images. – halirutan Jun 16 '15 at 13:36
• dear halirutan, the code is not coloring the left 20 pixels of each of the 3 sub images - compare e.g. the left output image in my case with your output. The two gaps around the center image should have 40 pixels white space ... – mrz Jun 16 '15 at 14:48
• @MilenkoRubin-Zuzic I just saw that you make a white border completely around each sub-image. I fixed the code and now it's even faster. I compared my output image with yours and it seems to be identical. – halirutan Jun 16 '15 at 15:03
• dear halirutan, perfect ... extremely fast (with read/saving) ... thanks – mrz Jun 16 '15 at 15:24

You can apply your transformation to a black image of the same dimension to create a mask. When you add this mask to one of your images the black areas of the mask will not affect them, and the white areas will make the color channel values in those areas of the images one or larger. However, those values will then be truncated back to 1, giving you the result you want. Thank you to halirutan for realizing that the performance is better if you specify "Bit" in Image.

mask = Image[ConstantArray[0, Reverse@ImageDimensions[img]], "Bit"];
mask = ReplaceImageValue[mask, {All, 1 ;; 20} -> White];
mask = ReplaceImageValue[mask, {All, 557 ;; 577} -> White];
mask = ReplaceImageValue[mask, {1 ;; 20, All} -> White];
mask = ReplaceImageValue[mask, {2141 ;; 2160, All} -> White];
mask = ReplaceImageValue[mask, {701 ;; 740, All} -> White];
mask = ReplaceImageValue[mask, {1421 ;; 1460, All} -> White]


img = Import["http://i.stack.imgur.com/BCScO.png"];
ImageAdd[img, mask]


Needs["GeneralUtilities"]
ImageAdd[img, mask] // AccurateTiming
(* Out: 0.0325975 on my computer; 0.0117959 on halirutan's computer *)


halirutan's solution on my computer:

splitImage[img]; // AccurateTiming
(* Out: 0.0151506 *)


If your computer supports Cuda you can parallelize ImageAdd on the GPU easily by using CUDAImageAdd.

• "halirutan's solution is faster though"... this is because you don't try hard enough! Check this out: Import["http://goo.gl/NaH6rM"]["http://i.stack.imgur.com/VuZoL.png"] +1 – halirutan Jun 16 '15 at 16:17
• @halirutan Thank you, it's slower on my computer than yours but it's still a big a improvement. I added it to the answer. – C. E. Jun 16 '15 at 17:04
• I wonder: how about using SparseArray[] to generate the height values and then converting it to an Image[]` for the mask? – J. M. will be back soon Jun 16 '15 at 23:13
• @Guesswhoitis. It doesn't improve the speed. – C. E. Jun 16 '15 at 23:32