圆形识别

概述

本教程以硬币圆形识别为例, 结合圆形识别的算法霍夫变换, 逐步讲解了圆形识别的各个阶段。

  • 图像求导 , 进而求得边缘图像
  • 二维平面中的边缘投影到霍夫空间
  • 统计检索明亮区域
  • 霍夫空间中的圆投影到二维空间

然后讲解了openmv中find_circles的API函数,及各参数的含义。

最后凡哥希望大家在学习openmv过程中,除了会调参外,还可以去了解一下api中所涉及的算法原理,这样才能更加深入的学习,另外对调参也是很有帮助的,要不然具体参数的含义都搞不懂。此教程涉及的概念较多,凡哥有些地方可能讲的不是很清楚, 欢迎大家来QQ群 564048763 跟凡哥交流, 共同完善《凡哥带你玩转OpenMV》系列教程。

算法解析-霍夫变换圆形识别

原图

我以硬币为例演示圆形识别的过程。

Step1 图像求导

我们来将一个什么是图像求导, 图像求导就是说像素的颜色取值在某一个方向的变化速度。 理所当然的是在边缘处,变化最大。

对于一个离散结构的矩阵来讲,求导呢? 我们以对x正方向求导为例来看一下实际的公式。

discrete gradient

然后在y方向求导, 以一个夹角 θ \theta 求导的方式。

image_gradient

下图展现了老虎照片对x轴求导跟对y轴求导的图像

tiger

接下来我们继续思考一下, 上述求导方式只考虑了一侧的因子。而实际上一个像素点,被周边一圈像素点包围着, 如何把他们都考虑进去。

然后我们就有了各种功能的算子。使用算子来对原图像进行卷积,得到对因的求导结果。 如果你还不知道什么是卷积, 可以参照我们对与卷积的介绍。机器视觉基础-卷积

下列是常见的算子

  • Sobel算子
  • Prewitt算子
  • Roberts算子

operators

我们着重讲一下Sobel算子

sobel operator

举例看一下Sobel算子的效果

sobel operator effect

Step2 获取图像边缘

那么我们求出来的这个图像导数,如何变成我们需要的边缘呢?

gradient to edge

  • 对求得的求导后的图像进行平滑处理,过滤掉噪声。
  • 设定一个阈值去寻找有效边缘区域。
  • 对有效区域的的图像进行细化(thin, 数学形态学操作),获取局部边缘像素。
  • 添加对边缘像素进行连接。

对硬币图像进行边缘求值得到下图。

edge-coin

Step3 霍夫变换

circle

左图是普通二维平面,空间中圆公式可以表示为

(xa)2+(yb)2=r2 (x-a)^2 + (y-b)^2 = r^2

(a,b) (a,b) 为圆心坐标,r r 为半径

右图为霍夫空间,三个轴坐标为 a,b,r a, b, r 分表代表圆心横坐标, 圆心纵坐标,半径。

在r指定的条件下,左图的一个点(绿色小点) 在右图的投影就是一个圆圈。

嘿嘿,怎么理解呢我们换个角度看一下圆的公式就可以了

(ax0)2+(by0)2=r2 (a - x_0)^2 + (b -y_0)^2 = r^2

(x0,y0) (x_0, y_0) 是已知量, a,b a, b 为未知量。

是不是很好理解了呢。 那如果在霍夫空间中, (x0,y0) (x_0, y_0) 的投影就是一个圆锥型(由若干个半径不同的圆组合而成)。

再一次我们拿出霍夫空间中的一个横向切片(即r=r0)的情况(r0是r轴上的任意一个取值)

我们如何在已知半径 r=r0 r = r_0 , 与一系列边缘点来求得圆心呢?

hough transform for circle

如果所示 我们把二维平面空间上的几个边缘点,映射到霍夫空间中,是若干个圆。 而若干个圆的交点区域即为二维空间上的圆在霍夫空间中的投影。该点坐标(a_0, b_0, r_0) 对应二维空间中的圆为

(xa0)2+(yb0)2=r02 ( x - a_0)^2 + ( y - b_0)^2 = r_0^2

没错,二维空间中的一个圆,对应到霍夫空间就是一个点。

如果我们想找到空间中所有尺寸的圆形, 就需要遍历r值,然后针对每个切面进行遍历与统计。

在指定 r=r0 r = r_0 假想我们建立了一个二维矩阵,对霍夫空间的横切面进行离散化表示,值都初始化为0 矩阵中的每一个元素都代表范围[a_min, a_max], [b_min, b_max]内的亮度. 遍历所有的边缘像素点,变换到霍夫空间, 转换成圆, 如果圆的边界落在此区域内,该区域加上一个 δ \delta 值 (这个值随意指定 例如 1).

最后我们我们把这个切面空间进行均一化处理,像素值统一放缩到[0-255], 以便可以转换为灰度图,让大家直观的看到圆在切面上的投影。

对硬币边缘图像投影到霍夫空间切面的图像

hough-coin

针对两种硬币对应的半径 r1, r2. 左右图是在霍夫空间中的两个半径对应的切面空间的图像。

可以看到左图中间的小点, 就是penny(美元,1分)的圆。

右图的高亮区域为quarter(美元, 25分)的圆。

Step4 统计 在霍夫空间中寻找亮点

上图是我们可以直观的看到明亮区域。在代码里我们需要去划分若干个空间(a, b , r), 统计值最大的区域, 确定出圆的大致位置 (xn,yn,rn) (x_n, y_n, r_n)

并且对于相似的圆,圆心相近,半径相近的圆,我们可以对其进行合并操作。

Step5 将霍夫空间中的点(目标圆)投影到二维空间

下图为硬币图上标注了识别出来的圆形区域,描白边。

mark-coin

效果演示

圆形识别的演示视频-云江自频道 OpenMV3圆形识别演示视频

源代码


# Find Circles Example
#
# This example shows off how to find circles in the image using the Hough
# Transform. https://en.wikipedia.org/wiki/Circle_Hough_Transform
#
# Note that the find_circles() method will only find circles which are completely
# inside of the image. Circles which go outside of the image/roi are ignored...

import sensor, image, time

sensor.reset()
sensor.set_pixformat(sensor.RGB565) # grayscale is faster
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()

while(True):
    clock.tick()
    # 消除畸变
    img = sensor.snapshot().lens_corr(1.8)
    # 识别圆 并且绘制
    for c in img.find_circles(threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10):
        img.draw_circle(c.x(), c.y(), c.r(), color = (255, 0, 0))
        print(c)

    print("FPS %f" % clock.fps())

源码解析

img = sensor.snapshot().lens_corr(1.8)

这里的lens_corr作用的是去除镜头导致的畸变效果。 因为鱼眼畸变会让方形的东西变圆,对圆形识别会有较大干扰。 默认值为1.8 逐渐调小,直至画面正常。

img.find_circles(threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10)

@Param threshold 识别圆大小的阈值. 根据不同图像,要识别圆的大小, 边缘模糊度的不同设定不同的阈值。你需要根据你要识别的对象调大/调小。

Note that the magnitude of a circle is the sum of all sobel filter magnitudes of pixels that make up that circle.

@Param x_margin 圆形相似合并,x值

@Param y_margin 圆形相似合并,y值

@Param r_margin 圆形相似合并,r值

如果两个圆在其霍夫空间中距离 小于margin算法就将其合并为同一个圆形

同时满足如下条件

x1x2<=xmargin |x_1 - x_2 | <= x_{margin}

y1y2<=ymargin |y_1 - y_2 | <= y_{margin}

r1r2<=rmargin |r_1 - r_2 | <= r_{margin}

总结

我们可以发现这是一个非常粗暴的算法, 因为要遍历所有的半径取值,与每个像素点, 所以再执行识别圆的例程的时候比较耗费资源, 帧率会比较低。

参考文献

Detecting Coins using Hough Tramsform - Vivek Kwatra

find_circles - OpenMV英文文档

Copyright 杭州云江科技有限公司 2017 all right reserved,powered by Gitbook该文件修订时间: 2018-04-02 09:53:12

results matching ""

    No results matching ""