这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » OpenVINO生态社区 » 【原创】OpenCV-Python系列之轮廓的高级功能(三十二)

共6条 1/1 1 跳转至

【原创】OpenCV-Python系列之轮廓的高级功能(三十二)

高工
2020-07-13 21:40:40     打赏

OpenCV-Python系列之轮廓的高级功能

截至到本次教程,我们已经基本掌握了OpenCV常用的一些功能,实际上已经可以处理很多问题了,故从本教程开始,示例代码将编写为一个固定函数,以便调用,另外将不再给出完整代码,比如导入库将不再另行贴出,一些基本的代码也不再贴出,只贴出核心部分,我会将核心部分整理为一个方便调用的函数。

我们在前面讨论了轮廓的特征以及属性,今天我们将综合之前学的内容讨论轮廓的高级功能。

凸缺陷

对象上的任何凹陷都被称为凸缺陷,OpenCV 中有一个函数cv.convexityDefect()可以帮助我们找到凸缺陷,函数调用如下:

hull = cv2.convexHull(cnt,returnPoints = False)

defects = cv2.convexityDefects(cnt,hull)

注意:如果要查找凸缺陷,在使用函数 cv2.convexHull 找凸包时,
参数 returnPoints 一定要是 False

它会返回一个数组,其中每一行包含的值是 [起点,终点,最远的点,到最远点的近似距离],们可以在一张图上显示它。我们将起点和终点用一条绿线 连接,在最远点画一个圆圈,要记住的是返回结果的前三个值是轮廓点的索引,我们仍然使用之前的多边形的图片:

image.png

来看代码核心部分:

def convexity(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(img_gray, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, 2, 1)
    cnt = contours[0]
    hull = cv2.convexHull(cnt, returnPoints=False)
    defects = cv2.convexityDefects(cnt, hull)
    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        start = tuple(cnt[s][0])
        end = tuple(cnt[e][0])
        far = tuple(cnt[f][0])
        cv2.line(img, start, end, [0, 255, 0], 2)
        cv2.circle(img, far, 5, [0, 0, 255], -1)
        cv2.imshow('img', img)

image.png

可以看到,凹陷处被检测出来。

点多边形测试

点多边形测试求解图像中的一个点到一个对象轮廓的最短距离。如果点在轮廓的外部,返回值为负。如果在轮廓上,返回值为0。如果在轮廓内部,返回值为正。

例如,我们可以如下检查点(50,50):

dist = cv.pointPolygonTestcnt,(50,50),True

在函数中,第三个参数是measureDist。如果为True,则找到带符号的距离。如果为False,它将查找该点是在轮廓内部还是外部或轮廓上(分别返回+ 1-10)。

这个按照我们的需要设置为False即可,当measureDist设置为false时,若返回值为+1,表示点在轮廓内部,返回值为-1,表示在轮廓外部,返回值为0,表示在轮廓上。

注意:如果不想查找距离,确保第三个参数为False,因为这是一个耗时的过程。因此,将其设置为False可使速度提高2-3倍。

我们来看代码,看看(50,50)位于哪儿:

def PointPolygon(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thresh = cv2.threshold(img_gray, 127, 255, 0)
    contours, hierarchy = cv2.findContours(thresh, 2, 1)
    cnt = contours[0]
    dist = cv2.pointPolygonTest(cnt,(50,50),False)
    print(dist)

结果:

image.png

-1代表该点位于轮廓内部。

匹配形状

函数 cv2.matchShape() 可以帮我们比较两个形状或轮廓的相似度。如果返回值越小,匹配越好。它是根据 Hu 矩来计算的。Hu 矩是归一化中心矩的线性组合,之所以这样做是为了能够获取代表图像的某个特征的矩函数,这些矩函数对某些变化如缩放,旋转,镜像映射具有不变形。

我们来看函数原型以及相应参数解释:

image.png

第一个参数是待匹配的物体1,第二个是待匹配的物体2

第三个参数method有三种输入:

CV_CONTOURS_MATCH_I1

CV_CONTOURS_MATCH_I2

CV_CONTOURS_MATCH_I3

即三种不同的判定物体相似的方法

image.png

注意:

前两个参数输入“灰度图像”时,并不是想当然的那样,其内容包含待匹配轮廓图案的灰度图;而是使用一行或一列双通道灰度图或者两列灰度图,该图中的每个像素不是什么图片,而是代表多边形轮廓上各节点的X,Y坐标。

输入轮廓时每个参数只能是一个轮廓

MatchShapesOpenCV提供的一个根据计算比较两张图像Hu不变距的函数,函数返回值代表相似度大小,完全相同的图像返回值是0,返回值最大是1。这可以用在在一堆照片中搜索出两张相同或相同程度最大的图像。

我们现在可以做个试验,类似于模板匹配。

待识别图像:

image.png

模板图像:

image.png

现在我们看看识别的步骤:

1. 将待识别图像 -> 灰度图像 -> 二值图像

2. 通过轮廓检索函数 cv.findContours 找到待识别图像所有轮廓

3. 模板图像 -> 灰度图像 -> 二值图像

4. 通过轮廓检索函数 cv.findContours 找到模板图像中字母 A 的外轮廓

5. 将第2步得到的轮廓逐一和第4步得到的轮廓 通过 cv.matchShapes 函数进行形状匹配。找到其中最小值,最小值对应的待识别图像中的轮廓即为匹配到的模板图像

6. 标出在待识别图像中找到的模板图像

来看核心代码:

def MatchShapes():
    # 载入原图
    img = cv2.imread('OCR.jpg', 0)
    # 在下面这张图像上作画
    image1 = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

    # 二值化图像
    _, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY|
                             cv2.THRESH_OTSU)
    # 搜索轮廓
    contours, hierarchy = cv2.findContours(thresh, 3, 2)
    hierarchy = np.squeeze(hierarchy)

    # 载入标准模板图
    img_a = cv2.imread('temp.jpg', 0)
    _, th = cv2.threshold(img_a, 0, 255, cv2.THRESH_BINARY|
                          cv2.THRESH_OTSU)
    contours1, hierarchy1 = cv2.findContours(th, 3, 2)
    # 字母A的轮廓
    template_a = contours1[0]

    # 记录最匹配的值的大小和位置
    min_pos = -1
    min_value = 2
    for i in range(len(contours)):
        # 参数3:匹配方法;参数4:opencv预留参数
        value = cv2.matchShapes(template_a, contours[i], 1, 0.0)
        if value < min_value:
            min_value = value
            min_pos = i

    # 参数3为0表示绘制本条轮廓contours[min_pos]
    cv2.drawContours(image1, [contours[min_pos]], 0, [255, 0, 0], 3)

    cv2.imshow('result', image1)

image.png

可以看到已经正确的匹配到了,实际上这就相当于是OCR文字识别的雏形。

当然,关于OpenCV中轮廓的讨论还没有结束,仍然有其他的功能,我们将在下次介绍。


对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区




关键词: OpenCV-Python     系列     系列     原创    

工程师
2020-07-14 18:52:46     打赏
2楼

感谢分享


工程师
2020-07-14 18:56:28     打赏
3楼

学习一下


工程师
2020-07-14 19:01:21     打赏
4楼

谢谢分享


助工
2020-07-15 15:01:03     打赏
5楼

感谢你的分享


工程师
2020-07-15 15:27:57     打赏
6楼

不错的分享


共6条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]