Python 如何从matchShapes函数中获得可靠的结果?

Python 如何从matchShapes函数中获得可靠的结果?,python,opencv,image-processing,Python,Opencv,Image Processing,很抱歉问了这么长的问题。。。我必须添加足够多的图像来解释我的观点,并演示不同的边缘情况 我正在尝试使用Python中的OpenCV检测减速带标志。这些标志如下所示: (这些只是我从互联网上下载的示例,以下分割轮廓不是这些图像的一部分) 我成功地提取了这些标志的内部轮廓,它们看起来如下: 一些不需要的三角形标志也会通过我的三角形探测器: 这些提取的轮廓看起来像: 因此,我的目标是将提取的轮廓与一些标准图像(我已经保存)进行比较。为此,我正在使用OpenCV中的matchContours函数。 我正

很抱歉问了这么长的问题。。。我必须添加足够多的图像来解释我的观点,并演示不同的边缘情况

我正在尝试使用Python中的OpenCV检测减速带标志。这些标志如下所示:

(这些只是我从互联网上下载的示例,以下分割轮廓不是这些图像的一部分)

我成功地提取了这些标志的内部轮廓,它们看起来如下:

一些不需要的三角形标志也会通过我的三角形探测器:

这些提取的轮廓看起来像:

因此,我的目标是将提取的轮廓与一些标准图像(我已经保存)进行比较。为此,我正在使用OpenCV中的
matchContours
函数。

我正在使用的标准图像,将与所有可能的图像进行比较(左侧有多个凸起,右侧有一个凸起):

我面临的问题是,
matchContours
的输出非常多变,我无法理解它。以下水平堆叠图像描绘了目标轮廓(左侧),与上述标准之一(右侧)相比,左下角的值描绘了以下代码的输出:

def比较_ROI(标准,图像):
cnt1,u=cv2.查找孔(标准,cv2.外部翻新,cv2.链约无)
cnt2,=cv2.查找对象(图像,cv2.外部检索,cv2.链约无)
biggest1=已排序(cnt1,key=cv2.contourArea,reverse=True)[0]
biggest2=已排序(cnt2,key=cv2.contourArea,reverse=True)[0]
返回cv2.matchShapes(biggest1、biggest2、cv2.CONTOURS_MATCH_I1,0.0)
比较\u ROI(单个\u凹凸\u模板\u反转,图像)
比较\u ROI(多个\u凹凸\u模板\u反转,图像)
#不显示堆叠和添加文本
以下是上述代码输出的一些示例:

从上面的图像中,我可以说,分类为“检测到减速带”的值(两次比较中的最小值)应该介于
0和1.6之间

但以下图像与这一观察结果相矛盾。有时,未检测到的斑点的值落在该范围内,而其他时候,实际的“真实”检测值落在该范围外,所有与凹凸非常不同的形状中更糟糕的形状也会进入该范围(以“箭头”或“e”为例):

为什么会这样?请注意,ROI图像都是不同的形状。。。有些很小,有些很大<代码>匹配形状
应该对对象的形状保持不变,并且应该能够检测形状

如前所述,所有7个Hu矩在平移(沿x或y方向移动)、缩放和旋转下都是不变的

所以我的问题是:如何确保从
matchShapes
获取的返回值在正确的范围内?我是否可以将任何转换应用于输入图像,以便更好地“帮助”
matchShapes
“看到”差异


这与我的类似,下面的两条注释似乎表明可能需要进行一些转换

:

matchShapes()使用Hu不变量;旋转/平移/缩放不变形状的描述。尽管你的结果看起来很奇怪,但事实是硬币的形状是非常椭圆的,比衬衫的形状更椭圆,这意味着如果你把它们都放大到相同的大小,硬币上的椭圆比衬衫离中心的“质量”(面积)要远得多。因此,对于
matchShapes()

:

解决了这个问题,只是做了一个函数,将轮廓拉伸成一个正方形的边界框,这样从一个角度观察硬币时,硬币看起来就像它们的正面一样。这可能适用于更复杂的形状

我不确定OP在这种情况下做了什么,以及他们做同样的事情对我的情况是否有帮助,所以我问了这个问题


我应该尝试使用其他两种实现的方法吗<代码>等高线匹配\u I2和
等高线匹配\u I3
?它们到底有什么不同?政府只能说这么多:


您可以从下载整个数据集。并在与解压缩的“dataset”文件夹相同的工作目录中运行以下代码:

导入操作系统
进口cv2
dataset=“dataset”
folders=os.listdir(数据集)
文件夹。删除(“标准”)
single=cv2.imread(os.path.join(数据集,“标准”,“single.jpg”),0)
multiple=cv2.imread(os.path.join(数据集,“标准”,“multiple.jpg”),0)
def比较_roi(roi,标准):
cnt1,u=cv2.查找孔(标准,cv2.外部翻新,cv2.链约无)
cnt2,cv2.找到的目标(投资回报率,cv2.外部回报率,cv2.链约无)
biggest1=已排序(cnt1,key=cv2.contourArea,reverse=True)[0]
biggest2=已排序(cnt2,key=cv2.contourArea,reverse=True)[0]
返回cv2.matchShapes(biggest1、biggest2、cv2.CONTOURS_MATCH_I1,0.0)
对于文件夹中的文件夹:
path\u to\u folder=os.path.join(数据集,文件夹)
roi=cv2.imread(os.path.join(路径到文件夹,“image.jpg”),0)
ret1=比较投资回报率(投资回报率,单个)
ret2=比较roi(roi,多个)
single_resized=cv2.resize(single,roi.shape[::-1],插值=cv2.INTER_NEAREST)
多重调整大小=cv2.resize(多重,roi.shape[::-1],插值=cv2.INTER\u最近)
stacked1=np.hstack((投资回报率,单次调整大小))
stacked2=np.hstack((投资回报率,多个调整大小))
h、 w=堆叠1.形状[:2]
putText(stacked1,“{:3f}”。格式(ret1),(10,h-h//w-10),0,0.5,(255,255,255),1)
h、 w=堆叠的2.形状[:2]
putText(stacked2,“{:3f}”。格式(ret2),(10,h-h//w-10),0,0.5,(255,255,255),1)
cv2.imshow(“roi”,roi)
cv2.imshow(“与单个相比”,堆叠1)
cv2.imshow(“与多个进行比较”),堆栈