OpenMV教程:使用形状识别进行图像处理
矩形识别
Rect.py
# Find Rects Example
#
# 这个例子展示了如何使用april标签代码中的四元检测代码在图像中找到矩形。 四元检测算法以非常稳健的方式检测矩形,并且比基于Hough变换的方法好得多。 例如,即使镜头失真导致这些矩形看起来弯曲,它仍然可以检测到矩形。 圆角矩形是没有问题的!
# (但是,这个代码也会检测小半径的圆)...
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 灰度更快(160x120 max on OpenMV-M7)
sensor.set_framesize(sensor.QQVGA)#160 * 120
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
# 下面的`threshold`应设置为足够高的值,以滤除在图像中检测到的具有
# 低边缘幅度的噪声矩形。最适用与背景形成鲜明对比的矩形。
#find_rects只有两个参数roi(x,y,w,h) + threshold
#如果只想显示图像右下角位置,则roi=(80,60,80,60)
for r in img.find_rects(threshold = 20000):
#rect.rect()返回一个矩形元组(x, y, w, h),用于如矩形的边界框的image.draw_rectangle()等其他的 image 方法。
img.draw_rectangle(r.rect(), color = (255, 0, 0))
#image.draw_rectangle(x, y, w, h[, color[, thickness=1[, fill=False]]])在图像上绘制一个矩形。
# 您可以单独传递x,y,w,h或作为元组(x,y,w,h)传递。
#color 是用于灰度或RGB565图像的RGB888元组。默认为白色。但是,您也可以传递灰度图像的基础像素值(0-255)或RGB565图像的字节反转RGB565值。
#thickness 控制线的粗细像素。
#将 fill 设置为True以填充矩形。
#rect.corners()
#返回一个由矩形对象的四个角组成的四个元组(x,y)的列表。四个角通常是按照从左上角开始沿顺时针顺序返回的。
#嵌套循环!rect.corners()返回一个由矩形对象的四个角组成的四个元组(x,y)的列表。四个角通常是按照从左上角开始沿顺时针顺序返回的。
for p in r.corners(): img.draw_circle(p[0], p[1], 5, color = (0, 255, 0)) #在四个角上画圆
#image.draw_circle(x, y, radius[, color[, thickness=1[, fill=False]]])
#在图像上绘制一个圆形。与上方draw_rects()类似
print(r)
print("FPS %f" % clock.fps())
#rect.x()返回矩形的左上角的x位置。您也可以通过索引 [0] (如上方r[0])取得这个值。
#rect.y()返回矩形的左上角的y位置。您也可以通过索引 [1] (如上方r[1])取得这个值。
#rect.w()返回矩形的宽度。您也可以通过索引 [2] (如上方r[2])取得这个值。
#rect.h()返回矩形的高度。您也可以通过索引 [3] (如上方r3])取得这个值。
#rect.magnitude()返回矩形的模(magnitude)。您也可以通过索引 [4] (如上方r[4])取得这个值。
圆形识别
Circle.py
# 圆形检测例程
#
# 这个例子展示了如何用Hough变换在图像中找到圆。
# https://en.wikipedia.org/wiki/Circle_Hough_Transform
#
# 请注意,find_circles()方法将只能找到完全在图像内部的圆。圈子之外的
# 图像/ roi被忽略...
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 灰度更快
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
clock.tick()
#lens_corr(1.8)畸变矫正
img = sensor.snapshot().lens_corr(1.8) #如果采用的是无畸变镜头可以注释掉
# Circle对象有四个值: x, y, r (半径), 和 magnitude。
# magnitude是检测圆的强度。越高越好
# roi 是一个用以复制的矩形的感兴趣区域(x, y, w, h)。如果未指定,
# ROI 即图像矩形。操作范围仅限于roi区域内的像素。
# x_stride 是霍夫变换时需要跳过的x像素的数量(仅查找在x方向上大于x_srtide的圆)。若已知圆较大,可增加
# x_stride 。
# y_stride 是霍夫变换时需要跳过的y像素的数量(仅查找在y方向上大于y_srtide的圆)。若已知直线较大,可增加
# y_stride 。
# threshold 控制从霍夫变换中监测到的圆。只返回大于或等于阈值的圆。
# 应用程序的阈值正确值取决于图像。注意:一条圆的大小是组成圆所有
# 索贝尔滤波像素大小的总和。
# x_margin 控制所检测的圆的合并(如果这两个圆在x方向上的距离小于x_margin个像素点就合并)。 圆像素为 x_margin 、 y_margin 和
# r_margin的部分合并。
# y_margin 控制所检测的圆的合并(如果这两个圆在y方向上的距离小于y_margin个像素点就合并)。 圆像素为 x_margin 、 y_margin 和
# r_margin 的部分合并。
# r_margin 控制所检测的圆的合并(如果这两个圆在半径r方向上的距离小于r_margin个像素点就合并)。 圆像素为 x_margin 、 y_margin 和
# r_margin 的部分合并。
# r_min,r_max和r_step控制测试圆的半径。
# 缩小测试圆半径的数量可以大大提升性能。
# threshold = 3500比较合适。如果视野中检测到的圆过多(特别是有些杂乱的圆),请增大阈值;
# 相反,如果视野中检测到的圆过少,请减少阈值。
for c in img.find_circles(threshold = 5000, x_margin = 10, y_margin = 10, r_margin = 10,r_min = 2, r_max = 100, r_step = 2):
img.draw_circle(c.x(), c.y(), c.r(), color = (255, 0, 0))
print(c)
print("FPS %f" % clock.fps())
直线识别
line.py
# 线段检测例程
#
# 这个例子展示了如何在图像中查找线段。对于在图像中找到的每个线对象,
# 都会返回一个包含线条旋转的线对象。
# find_line_segments()找到有限长度的线(但是很慢)。
# Use find_line_segments()找到非无限的线(而且速度很快)。
enable_lens_corr = False # 关闭畸变矫正(进行畸变矫正会使图像帧率降低),追求准确度的话可以打开打开以获得更直的线条…
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 灰度更快
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()
# 所有线段都有 `x1()`, `y1()`, `x2()`, and `y2()` 方法来获得他们的终点
# 一个 `line()` 方法来获得所有上述的四个元组值,可用于 `draw_line()`.
while(True):
clock.tick()
img = sensor.snapshot()
if enable_lens_corr: img.lens_corr(1.8) # 如果打开了畸变矫正那么就进行畸变矫正
# `merge_distance`控制附近行的合并。 在0(默认),没有合并。
# 在1处,任何距离另一条线一个像素点的线都被合并...等等,
# 因为你增加了这个值。 您可能希望合并线段,因为线段检测会产生大量
# 的线段结果。
# `max_theta_diff` 控制要合并的任何两线段之间的最大旋转差异量。
# 默认设置允许15度。
for l in img.find_line_segments(merge_distance = 0 ,max_theta_diff = 5):
#merge_distance指两条线段之间可以被相互分开而不被合并的最大像素数,设置为0就默认不合并
#max_theta_diff指如果两条线段要合并的话(前提),如果角度差小于max_theta_diff,那么两条直线将被合并
img.draw_line(l.line(), color = (255, 0, 0))
# print(l)
print("FPS %f" % clock.fps())
#调用img.find_line_segments()返回的对象
#line.line()返回一个直线元组(x1, y1, x2, y2) ,用于如 image.draw_line 等其他的 image 方法。
#line.x1()返回直线的p1顶点 x坐标分量。您也可以通过索引 [0] 取得这个值。
#line.y1()返回直线的p1 y分量。您也可以通过索引 [1] 取得这个值。
#line.x2()返回直线的p2 x分量。您也可以通过索引 [2] 取得这个值。
#line.y2()返回直线的p2 y分量。您也可以通过索引 [3] 取得这个值。
#line.length()返回直线长度即 sqrt(((x2-x1)^2) + ((y2-y1)^2).您也可以通过索引 [4] 取得这个值。
#line.magnitude()返回霍夫变换后的直线的模(magnitude)。您也可以通过索引 [5] 取得这个值。
#line.theta()返回霍夫变换后的直线的角度(0-179度)。您也可以通过索引 [7] 取得这个值。
#可以用于判断图像是不是三角形!详细见例程
#line.rho()返回霍夫变换后的直线p值。您也可以通过索引 [8] 取得这个值。