【问题标题】:Find Color inside an shape C++ OpenCV在形状 C++ OpenCV 中查找颜色
【发布时间】:2015-09-14 20:56:42
【问题描述】:

我有一个代码可以找到视频的计数并跟踪我选择的形状。在这段代码中,我正在搜索查看 3 或 4 个轮廓的三角形和矩形。

我需要 2 个问题的帮助:

1- 使用这种方法,我如何检测圆圈?

2- 我如何搜索颜色(形状已完成,所以在我的“如果”中我也需要验证颜色,但是如何?例如,如果我想找到一个红色三角形)

非常感谢

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp""
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv\cv.h>
#include <math.h>

using namespace cv;
using namespace std;

int iLastX = -1;
int iLastY = -1;

IplImage* imgTracking = 0;

int lastX1 = -1;
int lastY1 = -1;

int lastX2 = -1;
int lastY2 = -1;

void trackObject(IplImage* imgThresh){
  CvSeq* contour;  //hold the pointer to a contour
  CvSeq* result;     //hold sequence of points of a contour
  CvMemStorage *storage = cvCreateMemStorage(0); //storage area for all         contours

  //finding all contours in the image
   cvFindContours(imgThresh, storage, &contour, sizeof(CvContour),      CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

//iterating through each contour
while (contour)
{
    //obtain a sequence of points of the countour, pointed by the variable 'countour'
    result = cvApproxPoly(contour, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);

    //if there are 3 vertices  in the contour and the area of the triangle is more than 100 pixels
    if (result->total == 3 && fabs(cvContourArea(result, CV_WHOLE_SEQ))>100)
    {
        //iterating through each point
        CvPoint *pt[3];
        for (int i = 0; i < 3; i++){
            pt[i] = (CvPoint*)cvGetSeqElem(result, i);
        }

        //drawing lines around the triangle
        cvLine(imgTracking, *pt[0], *pt[1], cvScalar(255, 0, 0), 4);
        cvLine(imgTracking, *pt[1], *pt[2], cvScalar(255, 0, 0), 4);
        cvLine(imgTracking, *pt[2], *pt[0], cvScalar(255, 0, 0), 4);


    } 
    else if (result->total == 4 && fabs(cvContourArea(result, CV_WHOLE_SEQ))>100)
    {
        //iterating through each point
        CvPoint *pt[4];
        for (int i = 0; i < 4; i++){
            pt[i] = (CvPoint*)cvGetSeqElem(result, i);
        }

        //drawing lines around the quadrilateral
        cvLine(imgTracking, *pt[0], *pt[1], cvScalar(0, 255, 0), 4);
        cvLine(imgTracking, *pt[1], *pt[2], cvScalar(0, 255, 0), 4);
        cvLine(imgTracking, *pt[2], *pt[3], cvScalar(0, 255, 0), 4);
        cvLine(imgTracking, *pt[3], *pt[0], cvScalar(0, 255, 0), 4);
    }
    else if (CIRCLE???)
    {



    }

    //obtain the next contour
    contour = contour->h_next;
}

cvReleaseMemStorage(&storage);
}


int main(){
//load the video file to the memory
CvCapture *capture = cvCaptureFromAVI("F:/TCC/b2.avi");


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

IplImage* frame = 0;
frame = cvQueryFrame(capture);
if (!frame) return -1;

//create a blank image and assigned to 'imgTracking' which has the same size of original video
imgTracking = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvZero(imgTracking); //covert the image, 'imgTracking' to black

cvNamedWindow("Video");

//iterate through each frames of the video     
while (true){
    cvSet(imgTracking, cvScalar(0, 0, 0));

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

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

    //converting the original image into grayscale
    IplImage* imgGrayScale = cvCreateImage(cvGetSize(frame), 8, 1);
    cvCvtColor(frame, imgGrayScale, CV_BGR2GRAY);

    //thresholding the grayscale image to get better results
    cvThreshold(imgGrayScale, imgGrayScale, 100, 255, CV_THRESH_BINARY_INV);

    //track the possition of the ball
    trackObject(imgGrayScale);

    // Add the tracking image and the frame
    cvAdd(frame, imgTracking, frame);

    cvShowImage("Video", frame);

    //Clean up used images
    cvReleaseImage(&imgGrayScale);
    cvReleaseImage(&frame);


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

cvDestroyAllWindows();
cvReleaseImage(&imgTracking);
cvReleaseCapture(&capture);

return 0;
}

【问题讨论】:

  • 只是一条建议:使用 C++ 语法,而不是过时的 C 语法..

标签: c++ opencv colors tracking shapes


【解决方案1】:

Afaik,这将是一个相对复杂的项目,无法用一个问题回答,但这是我的 2 美分。我会试着画出我现在想到的那幅大画,希望它能对你有所帮助。

基本上,流程可以解耦:

  1. 对图像进行阈值处理以获得有希望的像素。正如您所说,您需要指定颜色,因此您可以使用它来设置阈值,即:如果您正在寻找红色物体,您可以使用具有高 R 通道级别而其他低的阈值。

  2. 一旦你得到了有希望的数字,你就需要一个标签算法来分离所有的数字。您可以为此使用this OpenCV addon library。这样,您就可以将找到的所有数字分开。

  3. 现在是最难的部分恕我直言。您可以使用分类器对数字进行分类(有很多关于 OpenCV 分类器的文档,like this one)。当您为此任务使用分类器时,您是在将输入形状(在本例中为您之前标记的每个图形)与几个 class 形状(在您的情况下为三角形和圆形)进行比较,并决定哪个类更适合您的输入形状。比较是分类器为您做的事情。说了这么多,你需要两件事:

    1. 定义您将从形状中获得的属性以便能够比较它们。你可以使用Hu moments

    2. 从一组训练数据中提取的数据集,您已经知道这些数据属于哪个类。也就是说,你基本上会得到一堆众所周知的三角形、圆形、正方形和任何你想到的形状,并从中得到第 3.1 步的属性。

这样,为了检查一个图形适合什么类,您将向分类器提供经过训练的数据集,其中包含众所周知的类的属性,以及输入形状的属性(即:Hu 矩)(您从标记)。

请注意,在使用分类器时,如果您在训练数据集中检测到未提供数据的形状,分类器将尝试将其与您提供的类更好地匹配。例如,如果您为三角形和正方形制作了训练数据集,当您提供圆形时,分类器会告诉您它是正方形还是三角形。

很抱歉没有提供详细信息,但我相信您可以get info on the net 了解如何使用分类器,并查看 OpenCV 文档。也许以后还会有更具体的问题,但是 afaik,这是我能说的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 2022-08-12
    • 2012-02-05
    • 2019-05-11
    • 2016-01-13
    • 2016-04-05
    相关资源
    最近更新 更多