使用OpenCVs matchShapes函数时的匹配问题
Matchingproblems when using OpenCVs matchShapes function
我正在尝试使用 findContour/matchShape 函数在更大的图片中找到对象(对象可能会有所不同,因此无法照顾颜色或类似的东西,像 SIFT 这样的特征检测器也不会不工作,因为对象可能是对称的)
我写了下面的代码:
Mat scene = imread...
Mat Template = imread...
Mat imagegray1, imagegray2, imageresult1, imageresult2;
int thresh=80;
double ans=0, result=0;
// Preprocess pictures
cvtColor(scene, imagegray1,CV_BGR2GRAY);
cvtColor(Template,imagegray2,CV_BGR2GRAY);
GaussianBlur(imagegray1,imagegray1, Size(5,5),2);
GaussianBlur(imagegray2,imagegray2, Size(5,5),2);
Canny(imagegray1, imageresult1,thresh, thresh*2);
Canny(imagegray2, imageresult2,thresh, thresh*2);
vector<vector <Point> > contours1;
vector<vector <Point> > contours2;
vector<Vec4i>hierarchy1, hierarchy2;
// Template
findContours(imageresult2,contours2,hierarchy2,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
// Szene
findContours(imageresult1,contours1,hierarchy1,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
imshow("template", Template);
double helper = INT_MAX;
int idx_i = 0, idx_j = 0;
// Match all contours with eachother
for(int i = 0; i < contours1.size(); i++)
{
for(int j = 0; j < contours2.size(); j++)
{
ans=matchShapes(contours1[i],contours2[j],CV_CONTOURS_MATCH_I1 ,0);
// find the best matching contour
if((ans < helper) )
{
idx_i = i;
helper = ans;
}
}
}
// draw the best contour
drawContours(scene, contours1, idx_i,
Scalar(255,255,0),3,8,hierarchy1,0,Point());
当我使用只有模板所在的场景时,我得到了一个很好的匹配结果:
但是当图片中有更多物体时,我无法检测到物体:
希望有人能告诉我我使用的代码有什么问题。谢谢
你在第二张图片中有大量的轮廓(几乎每个字母)。
由于 matchShape 检查尺度不变的 Hu 矩 (http://docs.opencv.org/3.1.0/d3/dc0/group__imgproc__shape.html#gab001db45c1f1af6cbdbe64df04c4e944),因此非常小的轮廓也可能符合您要查找的形状。
此外,在排除所有面积小于50的轮廓时,可以看到原始形状无法正确区分。
if(contourArea(contours1[i]) > 50)
drawContours(scene, contours1, i, Scalar(255, 255, 0), 1);
换句话说,你的代码没有问题。根本无法很好地检测到轮廓。我建议看看 approxCurve
和 convexHull
并尝试以这种方式关闭轮廓。或者以某种方式改进 Canny
的使用。
然后你可以使用先验知识来限制你正在寻找的轮廓的大小(可能还有旋转?)。
我正在尝试使用 findContour/matchShape 函数在更大的图片中找到对象(对象可能会有所不同,因此无法照顾颜色或类似的东西,像 SIFT 这样的特征检测器也不会不工作,因为对象可能是对称的)
我写了下面的代码:
Mat scene = imread...
Mat Template = imread...
Mat imagegray1, imagegray2, imageresult1, imageresult2;
int thresh=80;
double ans=0, result=0;
// Preprocess pictures
cvtColor(scene, imagegray1,CV_BGR2GRAY);
cvtColor(Template,imagegray2,CV_BGR2GRAY);
GaussianBlur(imagegray1,imagegray1, Size(5,5),2);
GaussianBlur(imagegray2,imagegray2, Size(5,5),2);
Canny(imagegray1, imageresult1,thresh, thresh*2);
Canny(imagegray2, imageresult2,thresh, thresh*2);
vector<vector <Point> > contours1;
vector<vector <Point> > contours2;
vector<Vec4i>hierarchy1, hierarchy2;
// Template
findContours(imageresult2,contours2,hierarchy2,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
// Szene
findContours(imageresult1,contours1,hierarchy1,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
imshow("template", Template);
double helper = INT_MAX;
int idx_i = 0, idx_j = 0;
// Match all contours with eachother
for(int i = 0; i < contours1.size(); i++)
{
for(int j = 0; j < contours2.size(); j++)
{
ans=matchShapes(contours1[i],contours2[j],CV_CONTOURS_MATCH_I1 ,0);
// find the best matching contour
if((ans < helper) )
{
idx_i = i;
helper = ans;
}
}
}
// draw the best contour
drawContours(scene, contours1, idx_i,
Scalar(255,255,0),3,8,hierarchy1,0,Point());
当我使用只有模板所在的场景时,我得到了一个很好的匹配结果:
但是当图片中有更多物体时,我无法检测到物体:
希望有人能告诉我我使用的代码有什么问题。谢谢
你在第二张图片中有大量的轮廓(几乎每个字母)。
由于 matchShape 检查尺度不变的 Hu 矩 (http://docs.opencv.org/3.1.0/d3/dc0/group__imgproc__shape.html#gab001db45c1f1af6cbdbe64df04c4e944),因此非常小的轮廓也可能符合您要查找的形状。
此外,在排除所有面积小于50的轮廓时,可以看到原始形状无法正确区分。
if(contourArea(contours1[i]) > 50)
drawContours(scene, contours1, i, Scalar(255, 255, 0), 1);
换句话说,你的代码没有问题。根本无法很好地检测到轮廓。我建议看看 approxCurve
和 convexHull
并尝试以这种方式关闭轮廓。或者以某种方式改进 Canny
的使用。
然后你可以使用先验知识来限制你正在寻找的轮廓的大小(可能还有旋转?)。