【问题标题】:How to filter out small contours in OpenCV 2.4.10如何在 OpenCV 2.4.10 中过滤掉小轮廓
【发布时间】:2015-04-08 02:25:00
【问题描述】:

小知识:我对 OpenCV 非常陌生,但想通过它变得更好,但目前我对它真的很不好(显然没有经验或导师......)。我需要制作一个可以从四轴飞行器检测不同物体的程序,唯一的问题是我会出现大量随机的小形状。我从这里借用了代码:http://opencv-srf.blogspot.com/2011/09/object-detection-tracking-using-contours.html,并在从四轴飞行器拍摄的一些图像上进行了尝试。这是程序的结果:http://imgur.com/IqzNVVr。它应该只看到顶部附近的银色盒子,但它看到的所有小形状。我从逻辑上知道该怎么做;如果形状的面积低于某个像素量,则不要在形状周围画线......但我不知道该怎么做。我稍微更改了编码并将其包含在下面。我该怎么做呢? (如果你知道任何关于 OpenCV 的好的深入教程,那就太好了!)

代码:

#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"

using namespace cv;
using namespace std;

int main()
{

IplImage* img = cvLoadImage("C:/Users/wyndr_000/Documents/Visual Studio 2013/Projects/OpenCV2410Test2/OpenCV2410Test2/Testpic2.png");

//show the original image
cvNamedWindow("Raw");
cvShowImage("Raw", img);

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

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

CvSeq* contours;  //hold the pointer to a contour in the memory block
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(imgGrayScale, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));

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


        //if there are 3  vertices  in the contour(It should be a triangle)
        if (result->total == 3)
        {
            //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(img, *pt[0], *pt[1], cvScalar(255, 0, 0), 4);
            cvLine(img, *pt[1], *pt[2], cvScalar(255, 0, 0), 4);
            cvLine(img, *pt[2], *pt[0], cvScalar(255, 0, 0), 4);

        }

        //if there are 4 vertices in the contour(It should be a quadrilateral)
        else if (result->total == 4)
        {
            //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(img, *pt[0], *pt[1], cvScalar(0, 255, 0), 4);
            cvLine(img, *pt[1], *pt[2], cvScalar(0, 255, 0), 4);
            cvLine(img, *pt[2], *pt[3], cvScalar(0, 255, 0), 4);
            cvLine(img, *pt[3], *pt[0], cvScalar(0, 255, 0), 4);
        }

        //if there are 7  vertices  in the contour(It should be a heptagon)
        else if (result->total == 7)
        {
            //iterating through each point
            CvPoint *pt[7];
            for (int i = 0; i < 7; i++){
                pt[i] = (CvPoint*)cvGetSeqElem(result, i);
            }

            //drawing lines around the heptagon
            cvLine(img, *pt[0], *pt[1], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[1], *pt[2], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[2], *pt[3], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[3], *pt[4], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[4], *pt[5], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[5], *pt[6], cvScalar(0, 0, 255), 4);
            cvLine(img, *pt[6], *pt[0], cvScalar(0, 0, 255), 4);
        }

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


//show the image in which identified shapes are marked   
cvNamedWindow("Tracked");
cvShowImage("Tracked", img);

cvWaitKey(0); //wait for a key press

//cleaning up
cvDestroyAllWindows();
cvReleaseMemStorage(&storage);
cvReleaseImage(&img);
cvReleaseImage(&imgGrayScale);

return 0;
} 

【问题讨论】:

  • 您是否考虑过使用contourArea 查找每个轮廓的所有区域,对于任何低于一定数量的轮廓区域,使用黑色的drawContours 将它们归零?
  • 我知道有一个功能contourArea,但我不明白如何使用它。我查了一下,但我不明白如何在这里使用它。
  • contourArea 确定由闭合轮廓包围的总面积。它基本上是对轮廓包围的所有白色像素求和。您所要做的就是找到每个轮廓所包围的所有区域,并过滤掉那些小于规定最小值的区域。

标签: c++ opencv filter contour opencv-contour


【解决方案1】:

这里的问题是通过阈值后留下的噪音。技术described here 应该可以解决您的问题。 (特别是打开/关闭图像部分)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2020-09-22
    • 2012-07-27
    • 2015-12-13
    • 2016-09-25
    • 2014-07-12
    相关资源
    最近更新 更多