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.

I got a piece of artwork in dimension of 20x20 pixels. I attempted to divide it into a 5x5 array of elements each of a smaller size of 4x4 pixels, and would like to find the mean color of the elements. I got the job done in a double for-loop. Is there a better way to do it? I need a faster way to treat much larger pieces.

enter image description here

Clear[avg]
avg = ConstantArray[0, {5, 5}];
image = Import["http://i.stack.imgur.com/ZZWEu.jpg"] ;
idata = ImageData[image];
ddata = Partition[idata , {4, 4}, 4] ;
For[i = 1, i <= 5, i++,
 For[j = 1, j <= 5, j++,
  avg[[i, j]] = Mean@Flatten[ddata[[i, j]], 1 ];
  ]]
Image[avg]

This is what I got:

Mathematica graphics

share|improve this question

3 Answers 3

up vote 16 down vote accepted

Here is a way to achieve this:

img = Import["file.jpg"];
data = ImageData[img];

Then:

Image @ Developer`PartitionMap[Mean[Flatten[#, 1]] &, data, {4, 4}, 4]

Mathematica graphics

share|improve this answer
    
Nice, I did not know about PartitionMap. That's super useful. –  mfvonh Aug 24 at 4:17
    
@mfvonh, I know. It's a gem I use often :) –  RunnyKine Aug 24 at 4:19

What you describe is nearly a linear downsampling of the image as achieved with ImageResize:

img = Import["http://i.stack.imgur.com/ZZWEu.jpg"]

ImageResize[img, Scaled[1/4], Resampling -> "Linear"]

enter image description here

The values are not exact, presumably due to a different alignment of the resampling grid but I have not found a way to adjust that in this function.

share|improve this answer
    
I'm not sure, but my guess would be that the edge values surrounding a grid cell have some weight in the resampled mean value. There is, I believe, a theoretical reason for preferring this approach (at least for photographs) -- maybe one of our image experts will comment. Another strong reason is that ImageResize is quite a bit faster than the other current answers. (+1 of course.) –  Michael E2 Aug 24 at 16:42
    
@MichaelE2 Would you say that (42825) explains this issue, at least pragmatically? –  Mr.Wizard Aug 24 at 19:01
    
It seems to explain upsampling. Downsampling seems different. –  Michael E2 Aug 24 at 19:35
image = Import["http://i.stack.imgur.com/ZZWEu.jpg"]
ImagePartition[image, {4, 4}] /. i_Image :> MeanFilter[i, 4] // ImageAssemble

enter image description here

EDIT

For comparison:

image = Import["http://i.stack.imgur.com/ZZWEu.jpg"];
ImageData[image];
rk = Image@Developer`PartitionMap[Mean[Flatten[#, 1]] &, %, {4, 4}, 4]
mf = ImagePartition[image, {4, 4}] /. i_Image :> MeanFilter[i, 4] // ImageAssemble
mw = ImageResize[image, Scaled[1/4], Resampling -> "Linear"]
{rk, mf, mw} = Show[#, ImageSize -> 200] & /@ ImageResize[#, 200] & /@ {rk, mf, mw}
ColorNegate /@ ImageSubtract @@@ Subsets[%, {2}]
ImageAdjust /@ %;
Transpose[{%%, %}] // GraphicsGrid

Rows are: rk-mf, rk-mw, mf-mw

enter image description here

share|improve this answer
    
The values produced by this method are also not exact as MeanFilter does not take a complete average of the image. Also, the "pixels" are really 4x4 sections. –  Mr.Wizard Aug 24 at 6:37
    
Thanks for the feedback, I wouldn't have picked up on that. –  mfvonh Aug 24 at 16:33
    
Clearly your result is closer to the OP's original, apart from the 4x4 "pixel" thing. –  Mr.Wizard Aug 24 at 19:05
    
Closer-ish -- there appear to be problems on the boundaries as you alluded to. And it's slow :) –  mfvonh Aug 24 at 19:30

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.