《我的眼睛–图灵识别》第五章:基础:形状识别
1、图形认识
三角形
三角形是由同一平面内不在同一直线上的三条线段‘首尾’顺次连接所组成的封闭图形。
三角形按边分有不等边三角形、等腰三角和等边三角形;按角分有直角三角形、锐角三角形、钝角三角形等,其中锐角三角形和钝角三角形统称斜三角形。
周长公式:周长 = a + b + c
面积公式:面积 = 底(任意边) * 高(h) / 2
不等边三角形、等腰三角形和等边三角形
锐角三角形、直角三角形和钝角三角形
矩形(四边形)
至少有三个内角都是直角的四边形是矩形,有一个内角是直角的平行四边形是矩形,对角线相等的平行四边形是矩形。矩形是一种特殊的平行四边形,正方形是特殊的矩形。矩形也叫长方形。
周长公式:周长 = 2 * (a + b)
面积公式:面积 = a * b
长方形、正方形和菱形
多边形
由三条或三条以上的线段‘首尾’顺次连接所组成的平面图形叫做多边形。多边形可以分为正多边形和非正多边形、凸多边形及凹多边形。
组成多边形的线段至少有3条,三角形是最简单的多边形。组成多边形的每一条线段叫做多边形的边;相邻的两条线段的公共端点叫做多边形的顶点;连接多边形的两个不相邻顶点的线段叫做多边形的对角线。
正凸多边形和非正凸多边形
正凹多边形和非正凹多边形
圆形(椭圆形)
在一个平面内,一动点以一定点为中心,以一定长度为距离旋转一周所形成的封闭曲线叫做圆,这个定点叫做圆的圆心。
圆是一种几何图形。圆是轴对称、中心对称图形。对称轴是直径所在的直线。同时,圆又是“正无限多边形”,而“无限”只是一个概念。当多边形的边数越多时,其形状、周长、面积就都越接近于圆。所以,世界上没有真正的圆,圆实际上只是概念性的图形。
椭圆形比圆形长,比圆形扁,椭圆形是由圆形变成的长圆形。椭圆是围绕两个焦点的平面中的曲线,使得对于曲线上的每个点,到两个焦点的距离之和是恒定的。因此,它是圆的概括,其是具有两个焦点在相同位置处的特殊类型的椭圆。
圆形周长公式:周长 = 2 * 3.14 * r
圆形面积公式:面积 = (3.14 * r ) ^ 2
椭圆形周长公式:周长 = (r / R) * (r + R)
椭圆形面积公式:面积 = 3.14 * a * b
圆形、椭圆形和同心圆
2、多边形识别
多边形识别(Find Shape)包含三角形、多边形、矩形和圆形的识别。主要识别的核心算法思路是统计形状的顶点数量和线段数量,根据筛选规则识别得到对应的形状图形。
数据统计筛选识别规则分别为三角形:有3个顶点和3条线段组成,多边形:有 4个顶点和至少3条线段以上组成,矩形:有4个顶点和4条线段组成,圆形:有4个顶点和0条线段组成。
(核心算法)多边形
人眼在识别形状的时候速度是非常快的,因为线条简单。但是电脑程序要实现形状识别就需要用到很多的数学几何公式。看似简单做起来却很难,要识别二维物体的形状需要以下的几个步骤:
识别步骤
第1步,获取像素
使用“来源_获取图片像素()”的函数命令(封装了微软提供的LoadImage和GetBitmapBits等API函数)根据图片文件的路径进行图像数据的像素获取。(详情查阅:04基础:图片识别->像素获取)
(预览)图像数据
第2步,滤镜处理
二值化
因为准备的示例图已经是黑白的图像,所以这里暂时不需要进行二值化等图像滤镜的处理。在之后章节的复杂图像识别上会有详细的介绍。(详情查阅:07预处理:图像滤镜->彩色图像滤镜->二值化)
第3步,定位区域
获取顶点
相邻的两条线段的公共端点叫做多边形的顶点。
首先对图形的显示区域进行定位,分别使用从上往下从左往右找出左边的边界、从左往右从下往上找出下边的边界、从下往上从右往左找出右边的边界和从右往左从上往下找出上边的边界,这样就得到的图形的显示区域和对应4个方向的边界值。
显示区域
然后再确定顶点的数量,规则为根据设定2个顶点之间的最小距离大于一定的阈值时则认为是2个顶点(注意看圆形的边界线比较长,这里设定的阈值为15像素距离)。因为图像通过二值化处理后,存在有锯齿或一小段线条的情况会影响顶点数量的计算,此过程主要是去除计算时的干扰。最终才能得到二维图形的有效顶点数量。
圆形的边界线比较长
有效顶点
获取线段
组成多边形的每一条边叫做线段。要确定是否为线段,道理很简单,只需要计算2个顶点之间直线上的白色点数达到一定的数量后(这里设定的阈值为15像素长度),则为判定为有效线段。
(绿色)有效线段
获取2个顶点之间直线上的所有像素点的坐标采用的是,直线的斜截式方程:y=kx+b,其中k是直线的斜率,b是直线在y轴上的截距。该方程叫做直线的斜截式方程,简称斜截式。此斜截式类似于一次函数的表达式。
直线方程式
第4步,进行识别
形状特征统计
接下来,只需要根据前面获得的顶点数量和线段数量,针对不同的形状进行不同的判定条件,即可完成图形的识别。
首先,判断线段数量小于2时则为圆形。
然后,判断顶点数量等于线段数量同时等3时则为三角形,同时等4时则为矩形。
最后,判断顶点数量大于线段数量且都大于4时则为多边形。
三角形
多边形
矩形
圆形
VB6核心代码:
'识别
Public Function 形状比对(图像数据() As Byte, 顶点距离 As Long, 线段长度 As Long) As String
Dim w As Long, h As Long, 宽 As Long, 高 As Long
Dim x As Long, y As Long, 顶点() As 坐标结构, i As Long, Point As Long, bo As Boolean
宽 = UBound(图像数据, 2)
高 = UBound(图像数据, 3)
i = 0
'按顺序 找出4个边界上的顶点,根据阈值筛选是否为2个点
'找出左边所有顶点
For w = 0 To 宽
Point = 0
bo = False
For h = 0 To 高
If 图像数据(2, w, h) = 255 Then
If bo = False Then '找到白色点
bo = True '记录开关
ReDim Preserve 顶点(i) As 坐标结构 '第1个点
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
Point = Point + 1 '记录白色点数
ElseIf 图像数据(2, w, h) = 0 And bo = True Then
If Point > 顶点距离 Then '筛选是否为第2个点
ReDim Preserve 顶点(i) As 坐标结构
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
Exit For
End If
Next
If bo = True Then Exit For
Next
If i = 0 Then 形状比对 = "": Exit Function
'找出下边所有顶点
For h = 高 To 0 Step -1
Point = 0
bo = False
For w = 0 To 宽
If 图像数据(2, w, h) = 255 Then
If bo = False Then '找到白色点
bo = True '记录开关
If 顶点(i - 1).x <> w And 顶点(i - 1).y <> h Then '排除重叠顶点
ReDim Preserve 顶点(i) As 坐标结构 '覆盖前面的点记录
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
End If
Point = Point + 1 '记录白色点数
ElseIf 图像数据(2, w, h) = 0 And bo = True Then
If Point > 顶点距离 Then '筛选是否为第2个点
ReDim Preserve 顶点(i) As 坐标结构
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
Exit For
End If
Next
If bo = True Then Exit For
Next
'找出右边所有顶点
For w = 宽 To 0 Step -1
Point = 0
bo = False
For h = 高 To 0 Step -1
If 图像数据(2, w, h) = 255 Then
If bo = False Then '找到白色点
bo = True '记录开关
If 顶点(i - 1).x <> w And 顶点(i - 1).y <> h Then '排除重叠顶点
ReDim Preserve 顶点(i) As 坐标结构 '覆盖前面的点记录
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
End If
Point = Point + 1 '记录白色点数
ElseIf 图像数据(2, w, h) = 0 And bo = True Then
If Point > 顶点距离 Then '筛选是否为第2个点
ReDim Preserve 顶点(i) As 坐标结构
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
Exit For
End If
Next
If bo = True Then Exit For
Next
'找出上边所有顶点
For h = 0 To 高
Point = 0
bo = False
For w = 宽 To 0 Step -1
If 图像数据(2, w, h) = 255 Then
If bo = False Then '找到白色点
bo = True '记录开关
If 顶点(i - 1).x <> w And 顶点(i - 1).y <> h Then '排除重叠顶点
ReDim Preserve 顶点(i) As 坐标结构 '覆盖前面的点记录
顶点(i).x = w
顶点(i).y = h
i = i + 1
End If
End If
Point = Point + 1 '记录白色点数
ElseIf 图像数据(2, w, h) = 0 And bo = True Then
'最后的点不为记录,因为返回到了起点
Exit For
End If
Next
If bo = True Then Exit For
Next
'按顺序 计算 当前点和下一个点的 直线上 的点数是否满足一定的阈值,为线段
Dim n As Long, m As Long, k As Long, 线段数量 As Long, 顶点数量 As Long
Dim xx() As Long, yy() As Long
n = UBound(顶点)
顶点数量 = n + 1
线段数量 = 0
For i = 0 To n
If i = n Then
Call 取直线上所有坐标(顶点(i).x, 顶点(i).y, 顶点(0).x, 顶点(0).y, xx, yy)
Else
Call 取直线上所有坐标(顶点(i).x, 顶点(i).y, 顶点(i + 1).x, 顶点(i + 1).y, xx, yy)
End If
m = UBound(xx)
Point = 0
For k = 0 To m
If 图像数据(2, xx(k), yy(k)) = 255 Then
Point = Point + 1
End If
Next
If Point > 线段长度 Then
线段数量 = 线段数量 + 1
End If
Next
'判断线段数量 和 顶点数量 最终得到 形状识别
If 线段数量 > 2 Then
If 顶点数量 > 线段数量 Then
形状比对 = "多边形"
Else
If 顶点数量 = 线段数量 Then
If 线段数量 = 3 Then
形状比对 = "三角形"
ElseIf 线段数量 = 4 Then
形状比对 = "矩形(四边形)"
Else
形状比对 = "多边形"
End If
End If
End If
Else
形状比对 = "圆形(椭圆形)"
End If
End Function