0.教学资源
以下是本节课的微课,配合文档学习效果更佳喔。
形状识别与霍夫变换.pptx
1.课前导入
1.1形状识别有啥用?
分拣零件:工厂中的分拣机器人中涉及的关键技术是利用计算机机器视觉技术实现对圆形的识别和实时跟踪,引导机械臂完成拾取工作。
点击查看【bilibili】
视频1.工厂中的分拣零件机器人
总之,形状识别就是用摄影机和电脑对图像进行分析,提取出图像中的形状。在生活中它可以用于:识别车牌、标识、文字;工厂中识别零件等等。
2.形状识别的步骤
观看下面的视频,你能总结出形状识别的步骤吗?
视频2.形状识别的流程
2.1第一步:预处理
预处理可以将画面中的杂乱信息(比如画面抖动,背景杂乱)排除掉。同时预处理能提高识别准确率,加快识别速度。
图3.预处理效果
预处理方法-灰度化
灰度化,简单的说就是将彩色图像的颜色信息抹去,但是保留亮度信息(如下图左)。这个亮度信息也叫灰度值,它的范围在0~255。
当“灰度值”为255时,像素为白色,为0时像素为黑色。
图4.灰度化效果以及不同灰度值时像素的颜色
预处理方法-二值化
和灰度化不同,二值化是将彩色图像的颜色信息抹去,将大部分亮度信息也抹去。
通过设置一个阈值,当一个像素的“灰度值”大于这个值的时候,则将这个像素设为“255”(纯白)。如果小于阈值,则设置为“0”(纯黑)。
图5.二值化效果
2.2第二步:检测物体边缘
计算机是怎么识别出图像的边缘的?运用“霍夫变换” 可以解决这个问题。
图6.检测图像边缘效果
霍夫变换是什么?
霍夫变换是用于辨别物体特征的一个算法,可以用来辨别直线,椭圆,多边形等形状。
在这里,我用直线举例,让大家理解霍夫变换的过程。
假设我们的需要摄像头识别这样一张图片(不包含坐标系,图像为一条直线及四个蓝色干扰点)
图7
在计算机眼中,这张图片是有许多个像素点组成的,大致效果如下(将直线省略成6个点)
图8
计算机该怎样识别出这个图像中的直线呢?有一个方法是,求出任意两个像素点的直线方程,再带入第三个像素
点,如果方程成立则说明这三个点在同一条直线。
但显然这个方法非常麻烦,因为图像中有非常多像素点,运算量非常大。
所以这时就要用到“霍夫变换”。
霍夫变换就是将坐标系进行转换,原本的直角坐标系是y是因变量,x是自变量。但在霍夫变换之后,我们将y=kx+b中的b(直线的截距)作为因变量,将k(直线的斜率)作为自变量,得到b=-kx+y。这样转换之后,将图中的像素点代入b=-kx+y中得到:
图9
此时,图8中的黑色点变成了图9中的黑色直线,图8中的蓝色点变成图9中的蓝色直线。比如:(1,1)变成b=-k+1、(1,4)变成b=-k + 4
同时我们发现,图9中的黑线相交于点(1,0)。我们将点(1,0)代入b=-kx+y,发现其为y=x,正是图8中黑色点所在的直线方程。
所以我们知道,在进行了霍夫变换之后,图像中的像素点变成了一条条线,而它们的交点就是我们要找的图像中的物体边缘。
图10.霍夫变换中点和线的对应图
这样变换之后,找“图像中边缘”就变成了找“有最多线相交的点”。运算量大大减少。
相关代码
while(True):
img = sensor.snapshot() #显示画面
# r_min,r_max控制测试圆的半径。
# threshold = 3500比较合适。如果视野中检测到的圆过多,请增大阈值;
# 相反,如果视野中检测到的圆过少,请减少阈值。
for c in img.find_circles(threshold = 2500,r_min = 2, r_max = 100):
img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 255))
# draw_circle对象有三个值: x, y, r (半径)。
print(c)
3.完整代码
import sensor, image
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE) #进行预处理,将图像设置为灰度图
sensor.set_framesize(sensor.QQQVGA)
sensor.skip_frames(time = 2000) #跳过一些帧,使摄像头稳定
while(True):
img = sensor.snapshot() #显示画面
# r_min,r_max控制测试圆的半径。
# threshold = 3500比较合适。如果视野中检测到的圆过多,请增大阈值;
# 相反,如果视野中检测到的圆过少,请减少阈值。
for c in img.find_circles(threshold = 2500,r_min = 2, r_max = 100):
img.draw_circle(c.x(), c.y(), c.r(), color = (255, 255, 255))
# draw_circle对象有三个值: x, y, r (半径)。
print(c)