# How to get the mean color of an artwork?

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.

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:

-

Here is a way to achieve this:

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


Then:

Image @ DeveloperPartitionMap[Mean[Flatten[#, 1]] &, data, {4, 4}, 4]


-
Nice, I did not know about PartitionMap. That's super useful. – mfvonh Aug 24 '14 at 4:17
@mfvonh, I know. It's a gem I use often :) – RunnyKine Aug 24 '14 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"]


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.

-
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 '14 at 16:42
@MichaelE2 Would you say that (42825) explains this issue, at least pragmatically? – Mr.Wizard Aug 24 '14 at 19:01
It seems to explain upsampling. Downsampling seems different. – Michael E2 Aug 24 '14 at 19:35
image = Import["http://i.stack.imgur.com/ZZWEu.jpg"]
ImagePartition[image, {4, 4}] /. i_Image :> MeanFilter[i, 4] // ImageAssemble


EDIT

For comparison:

image = Import["http://i.stack.imgur.com/ZZWEu.jpg"];
ImageData[image];
rk = Image@DeveloperPartitionMap[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}]

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 '14 at 6:37