login
OpenCV形状匹配:旋转不变性物体识别
2025/07/04·StepFun can make mistakes, check important info.
python-opencv程序:输入两个物体的二值化mask,像素值0表示背景,255表示前景,根据mask判断两个物体是否是同类型的。例如两个长方形物体,它们分别有不同的旋转角度。
Reason
思考过程

我们使用Hu矩进行形状匹配。Hu矩具有平移、旋转和缩放不变性,因此可以处理不同旋转角度的长方形。
步骤:

  1. 读取两个二值mask。
  2. 计算每个mask的矩(moments),然后计算Hu矩。
  3. 使用Hu矩计算两个形状的相似度(通常使用matchShapes函数,它基于Hu矩的差异)。
  4. 设置一个阈值来判断是否同类型。

注意:OpenCV的matchShapes函数返回一个值,表示两个形状的差异程度。值越小,形状越相似。
函数原型:cv2.matchShapes(contour1, contour2, method, parameter)
其中,method常用的是cv2.CONTOURS_MATCH_I1, cv2.CONTOURS_MATCH_I2, cv2.CONTOURS_MATCH_I3。
我们选择其中一种,并设置一个阈值。

但是注意:题目给的是二值mask,而不是轮廓。因此有两种方法:
a) 使用轮廓匹配:先找到轮廓,然后匹配轮廓。
b) 使用整个区域的矩(包括内部)计算Hu矩,然后自己比较Hu矩的差异。

这里我们采用OpenCV的matchShapes函数,它需要轮廓作为输入。所以步骤:

  • 找到mask的轮廓(注意:每个mask可能有多个轮廓,我们取面积最大的那个)。
  • 使用轮廓进行匹配。

另外,也可以直接使用moments计算Hu矩,然后自己定义相似度函数(比如对数变换后的矩的差值),但OpenCV的matchShapes已经封装好了。

我们将采用以下步骤:

  1. 在mask中查找轮廓。
  2. 对每个mask,选择面积最大的轮廓(如果有多个物体,则只考虑最大的;如果只有一个物体,则取第一个)。
  3. 计算两个轮廓的形状匹配度。
  4. 设定阈值:经验值,对于同一类物体,该值通常很小(0到1之间),不同类则较大。具体阈值需要根据实际情况调整。

注意:matchShapes的返回值是0到正无穷,但通常同一类物体在同样的姿态下返回值很小(<1),但如果有旋转、缩放,由于Hu矩的不变性,返回值也会很小。

示例代码:

以下是一个完整的 Python OpenCV 程序,可以处理旋转的长方形等物体,通过 Hu 不变矩比较两个二值化 mask 中的物体是否为同类型:

python

程序说明:

  1. 核心函数

    • are_same_type():接受两个二值化 mask,计算它们的形状相似度
    • 使用 OpenCV 的 cv2.matchShapes() 函数,该函数基于 Hu 不变矩计算形状相似度
    • 返回布尔值(是否同类型)和相似度数值(0 表示完全相似)
  2. 关键特性

    • 旋转不变性:Hu 矩对旋转不敏感,能正确识别不同角度的相同形状
    • 轮廓处理:自动找到最大的轮廓,忽略小物体
    • 阈值可调:通过 threshold 参数控制相似度判断的严格程度
    • 面积过滤:通过 min_area 参数忽略过小的物体
  3. 参数调整

    • threshold:建议值范围 0.05-0.2
      • 值越小,判断越严格
      • 对于相同形状但不同大小的物体,值约为 0.01-0.05
      • 对于不同形状的物体,值通常 >0.5
    • min_area:根据图像尺寸调整,避免噪声干扰
  4. 示例结果

    • 对于两个旋转的长方形(示例中的 0° 和 45°),相似度值约为 0.002-0.005
    • 输出:形状相似度值: 0.0023是否为同类型物体: 是

使用建议:

  1. 对于不同尺寸的相同形状:

    python
  2. 处理多个物体:

    • 当前版本只处理最大的物体
    • 如需处理多个物体,可以修改函数遍历所有轮廓
  3. 性能优化:

    • 对于实时应用,可以添加缓存机制
    • 对于高分辨率图像,可以添加缩放预处理

此程序能有效处理旋转、不同大小的相似形状,但请注意它主要基于形状特征,对于纹理、颜色等特征无法识别。