Java 重叠形状识别(OpenCV)
我有一张包含一些形状的简单图像:一些矩形和一些椭圆,总数为4或5。形状可以旋转、缩放和重叠。有一个示例输入: 我的任务是检测所有这些图形,并准备一些关于它们的信息:大小、位置、旋转等。在我看来,核心问题是形状可以相互重叠。我试图搜索有关此类问题的一些信息,发现OpenCV库非常有用 OpenCV能够检测轮廓,然后尝试将椭圆或矩形拟合到这些轮廓。问题是当形状重叠时,轮廓会混淆 我考虑以下算法:检测所有特征点:并在其上放置白点。我得到了这样的东西,每个图形都被分成不同的部分: 然后,我可以尝试使用一些信息链接这些部分,例如复杂度值(我将曲线approxPolyDP拟合到轮廓,并读取它有多少部分)。但这开始变得非常困难。另一个想法是尝试所有的排列方式,将轮廓连接起来,并尝试将图形与之匹配。最好的编译将被输出Java 重叠形状识别(OpenCV),java,opencv,contour,shapes,image-recognition,Java,Opencv,Contour,Shapes,Image Recognition,我有一张包含一些形状的简单图像:一些矩形和一些椭圆,总数为4或5。形状可以旋转、缩放和重叠。有一个示例输入: 我的任务是检测所有这些图形,并准备一些关于它们的信息:大小、位置、旋转等。在我看来,核心问题是形状可以相互重叠。我试图搜索有关此类问题的一些信息,发现OpenCV库非常有用 OpenCV能够检测轮廓,然后尝试将椭圆或矩形拟合到这些轮廓。问题是当形状重叠时,轮廓会混淆 我考虑以下算法:检测所有特征点:并在其上放置白点。我得到了这样的东西,每个图形都被分成不同的部分: 然后,我可以尝试使用一
你知道如何创建简单而优雅的解决方案吗?模糊图像有助于找到代码中所示的交点
#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;
}
结果图像:
步骤2
简单地说,借用了
#包括“opencv2/imgproc.hpp”
#包括“opencv2/highgui.hpp”
使用名称空间cv;
使用名称空间std;
int main(int argc,字符**argv)
{
Mat src=imread(argv[1]);
席灰色,模糊;
CVT颜色(src、灰色、灰色);
阈值(灰色、灰色、127、255、阈值二元);
高斯模糊(灰色,模糊,大小(),5);
阈值(模糊,模糊,180,255,阈值二值化);
灰色。设置为(255,模糊);
imshow(“步骤1的结果”,灰色);
矢量等值线;
///寻找轮廓
findContours(gray.clone()、等高线、重建树、链近似简单);
///找到每个轮廓的旋转矩形和椭圆
向量minRect(contours.size());
向量minEllipse(contours.size());
对于(size_t i=0;i5)
{
minEllipse[i]=fitEllipse(Mat(等高线[i]);
}
}
///绘制轮廓+旋转矩形+椭圆
对于(size_t i=0;i
您可以在其他图像中获得以下结果图像。我希望你们能解决最后一步。
如何找到连接点?我认为下面建议的模糊并不是基于某种数学性质,它只是一种特别的尝试和观察——如果你能找到连接点,那么它就变成了一个图形问题;每个传入段都将有一个可能的输出段,并基于您可以匹配的曲率。但是如何检测交叉点呢?我尝试了许多用于查找角点的方法,发现“goodFeaturesToTrack”在这种情况下效果最好。缺点是它不仅检测交叉点,还检测矩形的核心点。在我看来,只检测交叉点的能力只会简化算法。如果它检测到矩形角点,它同样好——你必须将一个线段与一个线段配对——如果goodFeaturesToTrack准确地找到所有高亮显示的点,那么这就是你需要的。是的,没错,我正在考虑创建一个图形。当我有一个只有两条边的顶点时,我可以将它们作为矩形的一部分连接起来。更有趣的是,我有更多边的顶点,如4(简单连接)或3(两个矩形连接的特殊情况)。谢谢,我将尝试分析您的解决方案,与我的想法相反,它似乎非常简单和直接。我希望它会有所帮助。您可以尝试更改
GaussianBlur
和threshold
的参数(请参见我在第一个和第二个代码中如何更改)
#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;
}