Eilidh
Eilidh

Reputation: 1374

Is there an efficient way to determine what percentage of an image falls within a specified colour range? (In OpenCV for Android)

I've written an application which captures a video frame to RGBA format, converts it to HSV (for ease of thresholding) and then thresholds the image. (Essentially, where the camera "sees" the specified colour, it will turn those elements white, where it does not, it will turn those elements black.)

What I would like to do is determine what percentage of the image falls within the specified colour range. My initial idea is to scan through each individual element of the thresholded Mat, and count up the number of white elements to see where the colour is detected. I have two questions - firstly, is this an efficient solution to this problem? Or am I missing something obvious? Secondly, how would I go about accessing the elements of the Mat (if this is the most efficient solution)? I've looked at several questions along with the Mat documentation, however it's a little over my head.

This is the pseudocode I have right now for determining the number of white elements in an image.

// Loop through height
   // Loop through width 
       // If Mat element (height, width) is white, add 1 to the total 

// Compare total to the total number of elements in the image (height * width)

Edit: I've found how to access individual elements of a Mat (I was over-thinking it and confusing myself looking at some irrelevant information in a tutorial I'd found. I'm including how to do it below, however I would welcome any ideas about a more efficient way to do this, or the knowledge that I'm already doing this as efficiently as possible, if I am! Thanks!

for(int h=0; h<mHSVThreshed.height(); h++){
    for(int w=0; w<mHSVThreshed.width(); w++) {
        double element = mHSVThreshed.get(h, w)[0]; 
        }
}

To access a Mat with multiple channels, you would use mHSV.get(h, w)[1] mHSV.get(h, w)[2] etc.

Upvotes: 0

Views: 818

Answers (1)

dvhamme
dvhamme

Reputation: 1450

I would do it like this for speed.

unsigned int accumulator=0;
for(int i=0;i<yourMat.rows;i++){
    unsigned char *row=yourMat.ptr(i);
    for(int j=0;j<yourMat.cols;j++)
        accumulator+=row[j];
}
accumulator/=(yourMat.cols*yourMat.rows);

This assumes that you have thresholded to a value of 1 rather than 255 or something else. It should be much faster than the Mat::get() function because it only worries about the width step once per row.

Upvotes: 1

Related Questions