【问题标题】:Detecting a specific (qualitative) color in video with OpenCV使用 OpenCV 检测视频中的特定(定性)颜色
【发布时间】:2014-06-25 02:27:26
【问题描述】:

所以:我有这个 OpenCV 程序,它从摄像头捕获视频,并将其显示在两个窗口上。一种没有颜色检测;另一个突出显示某些特定颜色(例如红色)。

我需要一种方法来确定图像在特定时间是否包含该特定颜色。现在,第一个窗口只是一个普通的视频输出。第二个窗口全黑,直到看到与我指定颜色匹配的对象,这使得该对象在第二个窗口中显示为白色。

我想知道什么时候检测到,然后输出“检测到”或“未检测到”。

我该怎么做?我想我会遍历修改后图像的宽度和高度,然后检查,但我不知道该怎么做。任何帮助表示赞赏——我几天来一直试图找到这个问题的答案,但没有运气。我检查了 StackOverflow,但它没有为我提供我需要的东西。谢谢!

代码:

#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;
}

【问题讨论】:

  • 你能发布一些你输入的图片吗?

标签: c++ opencv image-processing video-processing cbir


【解决方案1】:

除了一些小的改动外,maggick 的代码可以正常工作...这将检测到红色。

#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;
}

【讨论】:

    【解决方案2】:

    您可以循环遍历图像的行和列,如果红色值大于某个阈值,您可以将另一帧中的相应像素设置为白色。另外我没有在下面的代码中编写它,但您也可以设置绿色和蓝色的阈值。因为如果您要查找的对象是红色的,那么它在绿色和蓝色记录中的位置就会很低。

    #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;
    }
    

    【讨论】:

      【解决方案3】:

      图像处理不是精确的科学,解决方案取决于输入数据...

      • 如果您使用数字创建的图像,您可以在过滤后的图像上使用cvCountNonZero 计算正像素
      • 如果您的图像是真实世界捕捉的,那么任何给定图像都有可能至少有一些像素与您的滤镜颜色相同。在局部滑动窗口中计算像素可能会更好,但这肯定不是唯一的方法。例如,抓取坐标 (0,0) 到 (100,100) 之间的区域,并计算非零的数量。如果超过一定的数字,假设你有一个积极的。否则,继续重叠窗口 (0,50) 到 (100, 150)...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-09
        • 1970-01-01
        • 2016-06-22
        • 2011-03-13
        • 1970-01-01
        • 1970-01-01
        • 2016-09-06
        相关资源
        最近更新 更多