0

Is there a c++ function or an opencv library that can calculate the average log of the luminance of a given 8*8 block or total image? My aim is to calculate the average luminance and store it back in the block. Also, is there another way to calculate the overall luminance or average luminance in another scientific method that fits the human visual system? If someone can point me to a lib or function in c++ I would appreciate that.

awksp
  • 11,764
  • 4
  • 37
  • 44
  • RGB2GRAY converts from RGB to luminance. Then an 8x8 averaging filter. http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor, http://docs.opencv.org/modules/imgproc/doc/filtering.html#void%20filter2D%28InputArray%20src,%20OutputArray%20dst,%20int%20ddepth,%20InputArray%20kernel,%20Point%20anchor,%20double%20delta,%20int%20borderType%29. My experience is that OpenCv tends to be slower than coding it up by hand, however. – IdeaHat May 14 '14 at 14:43

1 Answers1

2

To calculate the average luminance of an 8x8 block, centred at each pixel in an input greyscale image, you could perform a 2D convolution of that image with an 8x8 kernel containing the value 1/64 i.e. 1/(8*8) in each cell.

This is referred to as a normalised box filter / box blur.

You can then sample the resulting image e.g. at (x,y) to yield the average luminance of the 8x8 block centred at (x,y).

There is code in the OpenCV manual for a normalised box filter, with user selectable size.

http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.html

Regarding the 'log' of this value, you can then use OpenCV function cvLog to take the log of the filtered image and obtain your result.

jcollomosse
  • 673
  • 3
  • 17
  • why would I use a filter box; I can simply take the summation of all of the 64 pixels and divide them by 64 and get the avg luminance and multiply that by the log value?? why should I do more calculations for each pixel's neighbors ? please tell me your opinion, regards. – user3601375 May 14 '14 at 16:13
  • 1
    It is more efficient to perform a convolution/filtering. Consider to calculate an average the way you suggest will require a nested loop over X*Y pixels (the 8*8 window) then, you need to that over all W*H pixels in the image, which is a nested loop inside a nested loop. This is a spatial implementation of an operation called a "convolution" and a slow one with O(n^2) complexity. Convolution can be performed more efficiently by transforming both the image and the 8x8 window into the frequency domain, multiplying together, and transforming back. This can be done in O(log(n)) time or better. – jcollomosse May 14 '14 at 16:18
  • what about the margins pixels should the weight of the window have zeros this will not agive the right result, sorry I am getting old and stupid .. – user3601375 May 14 '14 at 16:28
  • 1
    You're right, the results of the convolution are invalid at the image border (i.e. within <8 pixels of the border). But then I don't see how you could iterate over these regions of the image by visiting pixels in an 8x8 grid either. There are a lot of different strategies for what to do with convolution in these cases e.g. duplicate the image, pad with zeros or another value e.g. avg greyscale value. All of those could be applied to your method also as it also suffers the same uncertainty in these border regions. – jcollomosse May 14 '14 at 16:31
  • am so grateful I would use the classic summation the performance is not what am seeking also border will effect the quality of my block and this is the most important concern now,I was believing some how filtering can give us a precise average for each pixel according to its neihbours rather than jumping to a wrong value when you have a steep change in luminance within the same block because on or two values . thanks a lot God may bless you. – user3601375 May 14 '14 at 16:40
  • 1
    Fair enough, although I guess my point was that what you're referring to as the "classic" method is performing a convolution whether you call it that or not. You still need to deal with the edge cases i.e. at the image borders via some strategy. If you use the filtering functions in OpenCV I believe these invalid/out of range values will be treated as zeros. – jcollomosse May 14 '14 at 16:44
  • Thanks a lot, you are very kind person. I have found your help very valuable. – user3601375 May 14 '14 at 16:53