这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 企业专区» 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 跳转至

回复

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