【问题标题】:How can i prevent my object detection program from detecting multiple objects of different sizes?如何防止我的对象检测程序检测到多个不同大小的对象?
【发布时间】:2014-08-31 21:44:29
【问题描述】:

所以,这是我的情况。我创建了一个基于颜色对象检测的对象检测程序。我的程序检测到红色并且效果很好。但这是我面临的问题:-

当周围有多个红色物体时,我的程序会检测到它们,并且当时它无法真正跟踪一个物体(即它在背景中跟踪其他各种大小的红色物体。它向我显示错误“背景中有太多噪音”。正如您在附加的“阈值图像”中看到的,它检测到圆形物体(这是我的跟踪对象)和我的红色帽子。我希望我的程序只检测我的跟踪对象(“这是一个圆形的可乐盖”)。我怎样才能做到这一点?请帮帮我。几天后我有我的工程设计比赛,我必须在我的讲师面前演示我的程序。我的程序应该只是能够检测和跟踪我想要的对象。谢谢

我的对象检测程序代码有点长。因此,我在此解释代码如下-我从网络摄像头帧捕获了一个帧-将其转换为 HSV-使用 HSV Inrange 过滤器过滤掉其他颜色,但对过滤后的图像应用红色应用形态学操作。这一切都在我的主要功能中

我的网络摄像头框架使用 1280*720 的帧分辨率。这有点减慢我的程序,但这是我必须为执行手势控制操作而做的权衡。无论如何,这里是我的 drawobjectfunction 和 trackfilteredobjectfunction。

int H_MIN = 0;
int H_MAX = 256;
int S_MIN = 0;
int S_MAX = 256;
int V_MIN = 0;
int V_MAX = 256;
//default capture width and height
const int FRAME_WIDTH = 1280;
const int FRAME_HEIGHT = 720;
//max number of objects to be detected in frame
const int MAX_NUM_OBJECTS=50;
//minimum and maximum object area
const int MIN_OBJECT_AREA = 20*20;
const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5;


void drawObject(int x, int y,Mat &frame){

circle(frame,Point(x,y),20,Scalar(0,255,0),2);
    if(y-25>0)
    line(frame,Point(x,y),Point(x,y-25),Scalar(0,255,0),2);
    else line(frame,Point(x,y),Point(x,0),Scalar(0,255,0),2);
    if(y+25<FRAME_HEIGHT)
    line(frame,Point(x,y),Point(x,y+25),Scalar(0,255,0),2);
    else line(frame,Point(x,y),Point(x,FRAME_HEIGHT),Scalar(0,255,0),2);
    if(x-25>0)
    line(frame,Point(x,y),Point(x-25,y),Scalar(0,255,0),2);
    else line(frame,Point(x,y),Point(0,y),Scalar(0,255,0),2);
    if(x+25<FRAME_WIDTH)
    line(frame,Point(x,y),Point(x+25,y),Scalar(0,255,0),2);
    else line(frame,Point(x,y),Point(FRAME_WIDTH,y),Scalar(0,255,0),2);

    putText(frame,intToString(x)+","+intToString(y),Point(x,y+30),1,1,Scalar(0,255,0),2);

}



void trackFilteredObject(int &x, int &y, Mat threshold, Mat &cameraFeed){

    Mat temp;
    threshold.copyTo(temp);
    //these two vectors needed for output of findContours
    vector< vector<Point> > contours;
    vector<Vec4i> hierarchy;
    //find contours of filtered image using openCV findContours function
    findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );
    //use moments method to find our filtered object
    double refArea = 0;
    bool objectFound = false;
    if (hierarchy.size() > 0) {
        int numObjects = hierarchy.size();
        //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
        if(numObjects<MAX_NUM_OBJECTS){
            for (int index = 0; index >= 0; index = hierarchy[index][0]) {

                Moments moment = moments((cv::Mat)contours[index]);
                double area = moment.m00;

                //if the area is less than 20 px by 20px then it is probably just noise
                //if the area is the same as the 3/2 of the image size, probably just a bad filter
                //we only want the object with the largest area so we safe a reference area each
                //iteration and compare it to the area in the next iteration.
                if(area>MIN_OBJECT_AREA && area<MAX_OBJECT_AREA && area>refArea){
                    x = moment.m10/area;
                    y = moment.m01/area;
                    objectFound = true;
                    refArea = area;
                }else objectFound = false;


            }
            //let user know you found an object
            if(objectFound ==true){
                putText(cameraFeed,"Tracking Object",Point(0,50),2,1,Scalar(0,255,0),2);
                //draw object location on screen
                drawObject(x,y,cameraFeed);}

        }else putText(cameraFeed,"TOO MUCH NOISE! ADJUST FILTER",Point(0,50),1,2,Scalar(0,0,255),2);
    }
}

这是图片的链接;如您所见,它还检测到背景中的红色帽子以及可乐瓶的红色盖子。

我的观察:- 这是我的想法,以实现我不检测未知大小的红色物体的预期目标。我想我必须编辑我在上述程序中声明的最大对象区域的值(const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH/1.5;)。我想我必须改变这个值,这可能会消除对更大的连续红色图片的检测。但是,还有另一个问题,一些物体不是完全红色的,它们有红色和其他颜色的斑块。因此,如果检测到的区域在我的程序中指定的范围内,那么我的程序也会检测到这些红色补丁。我的意思是我穿着一件混合颜色的 T 恤,当我穿着那件 T 恤测试我的程序时,我的程序能够从其他颜色中检测出红色。现在,我该如何解决这个问题?

【问题讨论】:

  • 嗯...有点难以帮助。你的链接挂在我的 iPad 上,你没有提供任何代码或任何关于你正在使用的工具、平台和算法的指示。
  • @MarkSetchell:- 标记我不允许在 stackoverflow 中上传图片,因为我是新用户。所以,我不得不把它上传到 photobucket 中,并在这里链接。至于我的代码和规范,我现在要更新我的问题。谢谢
  • @MarkSetchell:- 用代码更新了我的问题
  • 如果您尝试跟踪moving 红色物体,您可以计算每个物体的速度并拒绝任何不移动的物体(如帽子),或者使用图像差分技术检测运动。
  • 查看我对您上一个问题的帖子:stackoverflow.com/questions/25576995/…

标签: opencv image-processing computer-vision


【解决方案1】:

我认为您可以尝试以下程序:

  • 获得一个圆形内核,其面积与您感兴趣的对象大致相同。你可以这样做:Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(d, d)); 其中 d 是圆盘的直径。
  • 使用此内核对过滤后的区域图像执行归一化互相关或卷积(我认为归一化互相关会更好。并在内核周围添加一个空边框)。
  • 结果图像的峰值应为您提供过滤后图像中圆形区域的位置(如果您使用归一化互相关,则必须添加偏移)。

为了加快速度,您可以降低分辨率来执行此操作。

【讨论】:

  • :- 感谢您的帮助。我将尝试实现它。但我需要使用大约 1280*720 的分辨率,并且我的程序会变慢一点。有什么办法可以解决吗?
  • 我不确定您是在具体询问以缩小比例还是整个处理进行互相关/卷积。
  • 对于相关/卷积:一旦你有分割的图像,缩小它,并相应地缩小内核,然后执行操作。您可以轻松地将峰值位置映射到原始图像。关于以缩小的规模进行整个处理:从细节来看,不清楚为什么在不影响准确性的情况下很难做到。
【解决方案2】:

您可以通过检测阈值图像中的圆圈来过滤掉非圆形。 OpenCV 提供了一种使用霍夫变换检测圆的内置方法,更多信息here。您可以利用此功能仅保留半径在给定范围内的圆。

另一种可能性是将connected component labeling (CCL) 实现到您的演示程序中。 我相信它在 OpenCV 的 2.x 版本中的某个时候被删除了,但是从 Wikipedia 页面可以直接看到两遍版本的基本实现。 CCL 将在阈值化后为每个对象分配一个唯一 ID。然后,您必须在帧 (T-1) 和帧 (T) 中的对象之间实现对象之间的匹配(例如基于一些最近距离标准)并可能实现轨迹过滤 或平滑,但这肯定会给你一些额外的分数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 2019-11-09
    • 2022-07-19
    相关资源
    最近更新 更多