1

So: I have this OpenCV program, which captures video from the camera, and displays it on two windows. One has no color detection; the other highlights certain specific colors (such as red).

What I need is a way to figure out if the image, at a specific time, contains that specific color. Right now, the first window is just a regular video output. The second window is all black, until an object matching the color I specified is seen, which makes the object show up as white in the second window.

I want to know when it is detected and then output either 'detected' or 'not detected'.

How do I do this? I figured I would iterate over the width and height of the modified image and then check, but i have no idea how to do that. Any help appreciated – I’ve been trying to find an answer for this question for days now with no luck. I checked StackOverflow, but it didn't provide me with what I need. Thanks!

CODE:

#include <opencv/cv.h>
#include <opencv/highgui.h>

//This function threshold the HSV image and create a binary image
IplImage* GetThresholdedImage(IplImage* imgHSV){       
   IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   IplImage* imgThresh2=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   IplImage* imgThresh3=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   cvInRangeS(imgHSV, cvScalar(170,160,60), cvScalar(180,256,256), imgThresh2);
   cvInRangeS(imgHSV, cvScalar(0,160,60), cvScalar(22,256,256), imgThresh3);
   cvOr(imgThresh2, imgThresh3, imgThresh);
   cvInRangeS(imgHSV, cvScalar(75,160,60), cvScalar(130,256,256), imgThresh3);
   cvOr(imgThresh, imgThresh3, imgThresh);
   return imgThresh;
} 

int main(){
  CvCapture* capture =0;       

  capture = cvCaptureFromCAM(0);
  if(!capture){
printf("Capture failure\n");
return -1;
  }

  IplImage * frame = 0;

  cvNamedWindow("Video"); 
  cvNamedWindow("Ball");


  //iterate through each frames of the video     
  while(true){

        frame = cvQueryFrame(capture);           
        if(!frame) break;

        frame=cvCloneImage(frame); 
        cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel

        IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
        cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV

        IplImage* imgThresh = GetThresholdedImage(imgHSV);

        cvSmooth(imgThresh, imgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel

        cvShowImage("Ball", imgThresh);           
        cvShowImage("Video", frame);
        int sum = 0;
        for (int i = 0; i < imgThresh->width; i++) {
            for (int j = 0; j < imgThresh->height; j++) {
                // WHAT DO I NEED HERE TO CALCULATE CERTAIN COLOR
            }
        }
                    if (sum > 1) { cout >> "Detected"; }
                    else { cout >> "Not Detected"; }

        //Clean up used images
        cvReleaseImage(&imgHSV);
        cvReleaseImage(&imgThresh);            
        cvReleaseImage(&frame);

        //Wait 50mS
        int c = cvWaitKey(10);
        //If 'ESC' is pressed, break the loop
        if((char)c==27 ) break;      
  }

  cvDestroyAllWindows() ;
  cvReleaseCapture(&capture);     

  return 0;
}
fish2000
  • 4,289
  • 2
  • 37
  • 76
user2976493
  • 57
  • 1
  • 6

3 Answers3

0

Image processing is no exact science and the solution depends on the input data...

  • If you use digitally created images, you could count the positive pixels using cvCountNonZero on the filtered image
  • If your images are real-world captures, then there is a chance that any given image has at least some pixels in the colours of your filter. Counting pixels in a localised sliding window might work better, but this is certainly not the only approach. For example, grab an area between the coordinates (0,0) to (100,100), and count the number of non-zero's. If that goes above a certain number, assume you've got a positive. Otherwise, continue for an overlapping window (0,50) to (100, 150)...
tofi9
  • 5,775
  • 4
  • 29
  • 50
0

You can loop over the rows and cols of the image, and if the red value is greater than some threshold you can set the corresponding pixels in the other frame to be white. Also I didn't write it in the following code but you can also set thresholds for green and blue. Because if the object your looking for is red, it will be low in the green and blue records.

#include <opencv/cv.h>
#include <opencv/highgui.h>
//#include <opencv/imgproc.h>
#include <iostream>

using namespace std;

//This function threshold the HSV image and create a binary image
IplImage* GetThresholdedImage(IplImage* imgHSV){       
   IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   IplImage* imgThresh2=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   IplImage* imgThresh3=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
   cvInRangeS(imgHSV, cvScalar(170,160,60), cvScalar(180,256,256), imgThresh2);
   cvInRangeS(imgHSV, cvScalar(0,160,60), cvScalar(22,256,256), imgThresh3);
   cvOr(imgThresh2, imgThresh3, imgThresh);
   cvInRangeS(imgHSV, cvScalar(75,160,60), cvScalar(130,256,256), imgThresh3);
   cvOr(imgThresh, imgThresh3, imgThresh);
   return imgThresh;
} 

int main(){
  CvCapture* capture =0;       

  capture = cvCaptureFromCAM(0);
  if(!capture){
printf("Capture failure\n");
return -1;
  }

  IplImage * frame = 0;

  cvNamedWindow("Video"); 
  cvNamedWindow("Ball");


  //iterate through each frames of the video     
  while(true){

        frame = cvQueryFrame(capture);           
        if(!frame) break;

        frame=cvCloneImage(frame); 
        //cvSmooth(frame, frame, CV_GAUSSIAN,3,3); //smooth the original image using Gaussian kernel

        //IplImage* imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
        //cvCvtColor(frame, imgHSV, CV_BGR2HSV); //Change the color format from BGR to HSV
        //IplImage* imgThresh = GetThresholdedImage(imgHSV);
        //IplImage* imgThresh=cvCreateImage(cvGetSize(imgHSV),IPL_DEPTH_8U, 1);
        //cvCvtColor(imgHSV, imgThresh, CV_HSV2BGR);
        //cvSmooth(imgThresh, imgThresh, CV_GAUSSIAN,3,3); //smooth the binary image using Gaussian kernel

        //cvShowImage("Ball", imgThresh);           

        int sum = 150;

        for(int i=0; i< frame->height; i++){
          for(int j=0; j< frame->width; j++){
              int blue = frame->imageData[frame->widthStep*i + frame->nChannels* j + 0];
              int green = frame->imageData[frame->widthStep*i + frame->nChannels* j + 1];
              int red = frame->imageData[frame->widthStep*i + frame->nChannels* j + 2];
              //cout << red << " " << green << " " << blue << endl;
              if ( red + 128 >= sum)
              {
                if (blue < 30)
                {
                  if (green < 30)
                  {
                frame->imageData[frame->widthStep*i + frame->nChannels* j + 0] = 255;
                frame->imageData[frame->widthStep*i + frame->nChannels* j + 1] = 255;
                frame->imageData[frame->widthStep*i + frame->nChannels* j + 2] = 255;
              } 
            }

              }

            }
          } 
          cvShowImage("Video", frame);


                    if (sum > 1) { cout << "Detected"; }
                    else { cout << "Not Detected"; }

        //Clean up used images
        //cvReleaseImage(&imgHSV);
        //cvReleaseImage(&imgThresh);            
        cvReleaseImage(&frame);

        //Wait 50mS
        int c = cvWaitKey(10);
        //If 'ESC' is pressed, break the loop
        if((char)c==27 ) break;      
  }

  cvDestroyAllWindows() ;
  cvReleaseCapture(&capture);     

  return 0;
}
Maggick
  • 763
  • 2
  • 10
  • 26
0

well maggick's code works except some minor changes... This will detect red colors.

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>

using namespace std;

int main(){
  CvCapture* capture =0;       

  capture = cvCaptureFromCAM(0);
  if(!capture){
   printf("Capture failure\n");
   return -1;
  }

  IplImage * frame = 0;

  cvNamedWindow("Video"); 

  //iterate through each frames of the video     
  while(true){

        frame = cvQueryFrame(capture);           
        if(!frame) break;

        frame=cvCloneImage(frame);         

        int sum = 0;

        for(int i=0; i< frame->height; i++){
          for(int j=0; j< frame->width; j++){
              int blue = frame->imageData[frame->widthStep*i + frame->nChannels* j + 0];
              int green = frame->imageData[frame->widthStep*i + frame->nChannels* j + 1];
              int red = frame->imageData[frame->widthStep*i + frame->nChannels* j + 2];
              //cout << red << " " << green << " " << blue << endl;
              if ( red + 128 >= 250)
              {
                if (blue < 50)
                {
                  if (green < 50)
                  {
                  frame->imageData[frame->widthStep*i + frame->nChannels* j + 0] = 255;
                  frame->imageData[frame->widthStep*i + frame->nChannels* j + 1] = 255;
                  frame->imageData[frame->widthStep*i + frame->nChannels* j + 2] = 255;
                  sum = 1
                  } 
                }
              }
            }
          } 
        cvShowImage("Video", frame);

        if (sum > 0) { cout << "Detected"; }
        else { cout << "Not Detected"; }

        cvReleaseImage(&frame);

        //Wait 50mS
        int c = cvWaitKey(10);
        //If 'ESC' is pressed, break the loop
        if((char)c==27 ) break;      
  }

  cvDestroyAllWindows() ;
  cvReleaseCapture(&capture);     

  return 0;
}
feruz
  • 53
  • 10