0

I am processing video images and I would like to detect if the video contains any pixels of a certain range of red. Is this possible?

Here is the code I am adapting from a tutorial:

#ifdef __cplusplus
- (void)processImage:(Mat&)image;
{
    cv::Mat orig_image = image.clone();
    cv::medianBlur(image, image, 3);
    cv::Mat hsv_image;
    cv::cvtColor(image, hsv_image, cv::COLOR_BGR2HSV);
    cv::Mat lower_red_hue_range;
    cv::Mat upper_red_hue_range;
    cv::inRange(hsv_image, cv::Scalar(0, 100, 100), cv::Scalar(10, 255, 255), lower_red_hue_range);
    cv::inRange(hsv_image, cv::Scalar(160, 100, 100), cv::Scalar(179, 255, 255), upper_red_hue_range);
    // Interpret values here
}

Interpreting values

I would like to detect if the results from the inRange operations are nil or not. In other words I want to understand if there are any matching pixels in the original image with a colour inRange from the given lower and upper red scale. How can I interpret the results?

mm24
  • 9,280
  • 12
  • 75
  • 170
  • First you need to OR the lower and upper mask. Then you can `countNonZero` to see if there are non zero pixels (i.e. you found something). It could be better to first apply morphological erosion or opening to remove small (probably noisy) blobs, or find connected components (`findContours`, `connectedComponentsWithStats`) and prune / search for according to some criteria – Miki Mar 07 '16 at 14:44
  • Thanks. I know it is lame but would you please be able to add some sample code? It is my very first OpenCV test project and I am struggling getting familiar with all these functions and concepts in such a short time.. – mm24 Mar 07 '16 at 14:47
  • I posted an answer. This should get you started. If you have more precise requirements, please add them to your question and I'll try to make a more accurate answer. – Miki Mar 07 '16 at 15:01

1 Answers1

0

First you need to OR the lower and upper mask:

Mat mask = lower_red_hue_range | upper_red_hue_range;

Then you can countNonZero to see if there are non zero pixels (i.e. you found something).

int number_of_non_zero_pixels = countNonZero(mask);

It could be better to first apply morphological erosion or opening to remove small (probably noisy) blobs:

Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
morphologyEx(mask, mask, MORPH_OPEN, kernel); // or MORPH_ERODE

or find connected components (findContours, connectedComponentsWithStats) and prune / search for according to some criteria:

vector<vector<Point>> contours
findContours(mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

double threshold_on_area = 100.0;
for(int i=0; i<contours.size(); ++i)
{
    double area = countourArea(contours[i]);
    if(area < threshold_on_area)
    {
        // don't consider this contour
        continue;
    } 
    else
    {
        // do something (e.g. drawing a bounding box around the contour)
        Rect box = boundingRect(contours[i]);
        rectangle(hsv_image, box, Scalar(0, 255, 255));
    }
}
Miki
  • 40,887
  • 13
  • 123
  • 202