2016-01-16 140 views
2

我有一个包含一些形状的简单图像:一些矩形和一些椭圆形,总数为4或5个。形状可以旋转,缩放和重叠。有一个示例输入: Sample image 我的任务是检测所有这些数字,并准备一些有关它们的信息:大小,位置,旋转等。在我看来,核心问题是这样的事实,形状可以重叠彼此。我试图搜索关于这类问题的一些信息,并发现OpenCV库可能非常有用。重叠形状识别(OpenCV)

OpenCV能够检测轮廓,然后尝试使椭圆或矩形适合这些轮廓。问题是当形状被覆盖时,轮廓被混淆。

我想到下面的算法:检测所有的特征点:并把白点放在它们上面。我得到了类似这样的东西,每个图都分为不同的部分: enter image description here 然后我可以尝试使用一些信息来链接这些部分,例如复杂度值(我将曲线approxPolyDP拟合到轮廓并读取它的多少部分具有)。但它开始变得非常困难。另一个想法是尝试所有连接轮廓并试图使数字适合它们的排列组合。最佳编译将输出。

任何想法如何创建简单而优雅的解决方案?

+0

你如何找到结合点?我认为如下所示的模糊不是基于某种数学属性,而是基于它自己的尝试 - 如果你能找到交点,那么它就成为一个图形问题。每个传入段都会有可能的输出段,并基于曲率进行匹配。但你如何检测交点? – gpasch

+0

我尝试了很多方法来找到角落,并发现'goodFeaturesToTrack'在这种情况下效果最好。 Disadventage是它不仅检测路口,还检测矩形的核心。 在我看来,仅检测连接点的能力只是算法。 –

+0

如果它检测到矩形拐角就好 - 你必须将一个线段与一个线段配对 - 如果goodFeaturesToTrack找到所有突出显示的点,那么它就是你需要的 – gpasch

回答

0

模糊图像有助于找到交叉口的代码所示

#include "opencv2/imgproc.hpp" 
#include "opencv2/highgui.hpp" 

using namespace cv; 

int main(int argc, char** argv) 
{ 
    Mat src = imread(argv[1]); 
    Mat gray, blurred; 
    cvtColor(src, gray, COLOR_BGR2GRAY); 
    threshold(gray, gray, 127, 255, THRESH_BINARY); 
    GaussianBlur(gray, blurred, Size(), 9); 
    threshold(blurred, blurred, 200, 255, THRESH_BINARY_INV); 
    gray.setTo(255, blurred); 
    imshow("result",gray); 
    waitKey(); 

    return 0; 
} 

结果图像:enter image description here

第2步

简单地说,从generalContours_demo2.cpp

#include "opencv2/imgproc.hpp" 
#include "opencv2/highgui.hpp" 

using namespace cv; 
using namespace std; 

int main(int argc, char** argv) 
{ 
    Mat src = imread(argv[1]); 
    Mat gray, blurred; 
    cvtColor(src, gray, COLOR_BGR2GRAY); 
    threshold(gray, gray, 127, 255, THRESH_BINARY); 
    GaussianBlur(gray, blurred, Size(), 5); 
    threshold(blurred, blurred, 180, 255, THRESH_BINARY_INV); 
    gray.setTo(255, blurred); 
    imshow("result of step 1",gray); 

    vector<vector<Point> > contours; 

    /// Find contours 
    findContours(gray.clone(), contours, RETR_TREE, CHAIN_APPROX_SIMPLE); 

    /// Find the rotated rectangles and ellipses for each contour 
    vector<RotatedRect> minRect(contours.size()); 
    vector<RotatedRect> minEllipse(contours.size()); 

    for(size_t i = 0; i < contours.size(); i++) 
    { 
     minRect[i] = minAreaRect(Mat(contours[i])); 
     if(contours[i].size() > 5) 
     { 
      minEllipse[i] = fitEllipse(Mat(contours[i])); 
     } 
    } 

    /// Draw contours + rotated rects + ellipses 
    for(size_t i = 0; i< contours.size(); i++) 
    { 
     Mat drawing = src.clone(); 
     // contour 
     //drawContours(drawing, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point()); 
     // ellipse 
     ellipse(drawing, minEllipse[i], Scalar(0, 0, 255), 2); 
     // rotated rectangle 
     Point2f rect_points[4]; 
     minRect[i].points(rect_points); 
     for(int j = 0; j < 4; j++) 
      line(drawing, rect_points[j], rect_points[(j+1)%4], Scalar(0, 255, 0), 2); 
     /// Show in a window 
     imshow("results of step 2", drawing); 
     waitKey(); 
    } 

    return 0; 
} 

你借码可以得到以下结果图像等等。我希望你能解决最后一步。 enter image description here enter image description here enter image description here enter image description here

+0

谢谢你,我会试着分析你的解决方案,它似乎是非常简单直接的反对我的想法。 –

+1

我希望它能帮助你。你可以尝试改变'GaussianBlur'和'threshold'的参数(看看我如何改变第一和第二代码) – sturkmen