Consider an image (img) as

enter image description here

What is the best way to convert all the pixel values to say, 0.8?

Edit 1 Let me explain my objective. Firstly, I partition the image into 4 parts.

{width, height} = ImageDimensions[img];
Flatten@ImagePartition[img, {225/2, 225/2}];

Now I want to change the pixel values of the first image part to be 0.8 and then merge all the parts together. One thing to be noted here is that I don't have the information about the pixel values in the parts and all the pixels may not have the same value.

One issue in changing the pixel value in the part image is that it may create artifacts in the boundary while merging them together after changing pixel value. Therefore, I need a way such that there be a mapping between the first part and the corresponding portion in the original image so that I can make the changes directly on the image instead on the part.

Edit 2 I have applied image partitioning to treat individual parts as blocks so that I can compare the blocks with its neighbor to set the condition for changing the pixel value in a block.

  • $\begingroup$ Maybe img = Image[ConstantArray[0.8, ImageDimensions[img][[{-1, 1}]]]] $\endgroup$ – Coolwater Jan 23 '18 at 18:38
  • $\begingroup$ @Majis: Why do you want to "convert" pixel values rather than merely defining a new array having the desired pixel value? $\endgroup$ – David G. Stork Jan 23 '18 at 18:48
  • $\begingroup$ @DavidG.Stork see my edit. $\endgroup$ – Majis Jan 23 '18 at 19:12

MapAt can be used:

MapAt[ImageAdd[ImageMultiply[#, 0], 0.8] &,
   ImagePartition[img, {225/2, 225/2}], {1, 1}]

  • $\begingroup$ This is done on the partitioned image. I want it to be applied directly to the original image. $\endgroup$ – Majis Jan 23 '18 at 19:39

not sure why you want to do the partitioning. ReplacePixelValue can do it direct.

img = ImageResize[ExampleData[{"TestImage", "Mandrill"}], 100]
ReplacePixelValue[img, {1 ;; 50, 1 ;; 50} -> Hue[.3]]

enter image description here

actually partitioning proves to be considerably faster..

part = ImagePartition[img, {50, 50}];
 MapAt[Image[ConstantArray[Hue[.3], ImageDimensions[#]]] &, 
  part , {2, 1}]]
  • $\begingroup$ I know. Here you need to specify the range. By partition, I want to specify the block where the changing is to be done. $\endgroup$ – Majis Jan 23 '18 at 19:44
  • $\begingroup$ see edit. Partitioning turns out to be faster anyway. $\endgroup$ – george2079 Jan 23 '18 at 19:47

The two functions it sounds like you want to use are ImageApply and ImageApplyIndexed.

Let's make a random base image:

baseIm = RandomImage[];

Now, we want to turn the right half to 0.8-valued pixels.

ImageApply will get all of them. To choose, we build a mask image.

mask = ImageAssemble[{ConstantImage[0, {75, 150}], ConstantImage[1, {75, 150}]}];

Now, we can turn every pixel selected by the mask to 0.8 (or apply whatever function we want to it):

ImageApply[0.8 &, baseIm, Masking -> mask]

A random image with the right half all converted to take 0.8 value.

If we already know which pixels we want and don't want to go to the trouble of building a mask, we can use ImageApplyIndexed, which gives position as an argument to our function.

Let's make a random base image:

baseIm = RandomImage[];

Now we apply a function that makes the pixel value 0.8 if we are to the right or below the mid-lines:

ImageApplyIndexed[If[#2[[1]] > 75 && #2[[2]] > 75, 0.8, #1] &, baseIm]

A random image with pixels in quadrant 4 converted to 0.8 value.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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