6
$\begingroup$

In practice, subtracting the mean image from a dataset significantly improves classification accuracies. I thought there would be a ImageMean[] function but can't find one, so what is an efficient way to implement this for a list of given images of the same dimensions?

I typically calculate the mean image pixel values in C like this:

  const int channels = sum_blob.channels();
  const int dim = sum_blob.height() * sum_blob.width();
  std::vector<float> mean_values(channels, 0.0);

  for (int c = 0; c < channels; ++c) {
    for (int i = 0; i < dim; ++i) {
      mean_values[c] += sum_blob.data(dim * c + i);
    }
    LOG(INFO) << "mean_value channel [" << c << "]:" << mean_values[c] / dim;
  }

I need this to work for more than just a few images. Given a set of a few thousand images on filesystem, is there anyway of doing this without loading all the images into memory at the same time (which kills the front end).

This is what I have so far:

ImageMean[imgs_List] := Image@Mean[ImageData[#, "Real"] & /@ imgs]
imgs = Table[RandomImage[1, {256, 256}, ColorSpace -> "RGB"], {i, 10^5}];
AbsoluteTiming[ImageMean @ imgs]

This isn't giving me the save results as my c-code and it's slower than I think it can be (I'm not sure if it's correct in all colorspaces either). Plus it won't work for a large set of images that don't fit into memory all at once, it would be great if there is a way to enlist out-of-core methods (ImageFileApply, ImageFileFilter, ImageFileScan, ...).

$\endgroup$
2
  • 4
    $\begingroup$ Why wouldn't ImageMultiply[Fold[ImageAdd[#2, #1] &, 0, imgs], 1/Length[imgs]] be suitable? $\endgroup$ Aug 20, 2015 at 19:31
  • $\begingroup$ You may post your doubt about "(I'm not sure if it's correct in all colorspaces either)" in stackexchange DSP $\endgroup$ Aug 20, 2015 at 21:00

1 Answer 1

5
$\begingroup$

ImageAdd does some scaling/truncating, so cant be used directly for this purpose.

Try this, note for testing I'm averaging three copies of the same image and expect to recover the same image.

i0 = ExampleData[{"TestImage", "Boat"}];
imgs = {i0, i0, i0};
Image[Fold[ImageData[#2] + #1 &, 0 ImageData[i0] , imgs]/Length[imgs]]

enter image description here

here is the resuly of using ImageAdd/ImageMultiply

enter image description here

Performing the multiply first seems to fix this:

Fold[ImageAdd[ImageMultiply[#2, 1/Length[imgs]], #1] &, 0, imgs]

(watch for precision issues with large numbers of images though )

$\endgroup$
1
  • $\begingroup$ Do you know which one is more generally used when normalizing a set of images for classifcation pipelines? $\endgroup$
    – M.R.
    Aug 20, 2015 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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