Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate 'single' average/mean value of pixels in a set ROI using cvAvg or mean?

Tags:

opencv

I have a thresholded image of size 320x320 pixels. I loop through the entire image in blocks of 20x20 pixels by setting ROI. I need to find the average value of each block. So I pass these blocks of images to the function 'cvAvg'. I am facing the below problems.

  1. The return type of 'cvAvg' is 'CvScalar' which has 4 doubles. I could not interpret CvScalar from the docs. I need only a single average value of the pixels maybe of the format 'float' or 'double' based on which I need to make other decisions. How do I extract a single value out of the function return value. I do not want to iterate through all the pixels and find average. I want to process in blocks of 20x20. For Eg: If 200 pixels are white and 200 pixels are black in a block of 20x20, I want to be able to extract a single value so that I can make a decision that the block has 50% white pixels and I thought mean/average would be a good way to know.

  2. I created a variable of type CvScalar to retrieve and print the values returned by the function 'cvAvg. But all the values of the thresholded image are same

0.000000 255.000000 0.000000 0.000000

0.000000 255.000000 0.000000 0.000000

0.000000 255.000000 0.000000 0.000000

0.000000 255.000000 0.000000 0.000000

and this goes on 256 times for looping through all the blocks of the image which could not be right because the thresholded image has different parts of white and black. Whats going on here? Code Below. imgGreenThresh is the "binary image" thresholded for green.

IplImage* imgDummy = cvCreateImage(cvGetSize(imgGreenThresh), 8, 1);    //Create a dummy image of the same size as thresholded image
cvCopy(imgGreenThresh, imgDummy);                                       //Copy the thresholded image for further operations
CvRect roi;                                                             //Rectangular ROI
CvSize size;
int r, c, N=20;
int count = 0;
float LaserState[16][16];                                               //Create 16x16 matrix to hold the laser state values.
CvScalar meanValue;                                                     // individual windows mean value

size = cvGetSize(imgDummy);                                             //returns image ROI, in other words, height and width of matrix
                                                                        //Iteratively send the different ROIs for processing.
for (r = 0; r < size.height; r += N)
    for (c = 0; c < size.width; c += N)
    {
        count++;
        roi.x = c;
        roi.y = r;
        roi.width = (c + N > size.width) ? (size.width - c) : N;
        roi.height = (r + N > size.height) ? (size.height - r) : N;
        cvSetImageROI(imgDummy, roi);
        meanValue = cvAvg(imgDummy);
        printf("%f\t%f\t%f\t%f\n", meanValue);
        cvResetImageROI(imgDummy);

    }
//cvResetImageROI(imgDummy);                                                //Do not forget to reset ROIs

Thanks!

sudhir.

like image 331
sudhir vyasaraja Avatar asked Jan 21 '26 16:01

sudhir vyasaraja


1 Answers

My solution for computing the average of a single channel can be found in the following link: Average values of a single channel

For your case, you have a ROI instead of a single channel. In OpenCV, an ROI is also a Mat object (if you are using OpenCV's C++ code) which you can pass to the cv::mean(...) function to get back a Scalar object. Only the first entry of that object will be set properly to the mean of your ROI and that is the value you want. See the link above for details.

like image 83
lightalchemist Avatar answered Jan 26 '26 03:01

lightalchemist



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!