项目思路记录

1 目标切割
假设:没有目标模板(不能运用模板匹配)
要求:精确切割出目标
思路:传统图像处理技术(因为神经网络或级联分类器不能精确切割)
处理思想:画出像素分布图,观察分布,确定特征


具体步骤:
(1)阈值处理
阈值处理的方法这里选择了取图像85%的分位数的值np.percentile(blur, 85) 这样选取的好处是自适应性比较好,相比于大津法也有更多的自由选择阈值的空间。
(2)计算每一行的像素均值,得到一个以图像高为长度的向量。理想情况是根据背景区域与目标区域的灰度差,可以比较容易地确定目标区域的y方向的位置。同样地,计算每一列的像素均值,从而得到目标区域的x方向的位置。
得到的y方向上的像素均值图像实际上是这样的:

难以确定一个自适应的阈值来确定边缘的位置。于是想到计算一阶导,但由于临近像素点之间的像素差不大,因此计算一阶导数
的效果很差。结合之前学习深度学习中,池化的概念,我想到了对每十个像素点计算一个均值或者最大值,来代替这十个像素点的值,从而减小这些细节的影响,提取出比较明显的像素变化趋势,得到图像如下。根据这个图形,我们再计算一阶导数,就可以得到比较好的结果。

一阶导数的结果:

如此,我们只需要确定前半部分的最大值,以及后半部分的最小值,就可以得到图像的左右边缘了。计算上下边缘同理。

总结:采用传统方法对目标区域进行切割,首先自适应是一个问题。采用图像数据的分位数是一个不错的选择。其次,画出图像直方图、像素分布等信息进行观察和尝试,寻找目标区域的特征,如颜色,灰度等。最后,多尝试,多思考。

2 角度修正
角度修正的方法我没有找到一个较好地方法,只能说根据网上的一些方法进行了尝试,不具有通用性。
(1)根据霍夫变换找直线
霍夫变换的原理比较简单。他将二维空间里的一条直线,映射成为用(theta,h)表示。其中theta是该直线的垂线与x轴的夹角,h是原点到该直线的垂直距离。空间里的每个点其实可以位于无数条直线上,因此一个点可以对应无数个(theta,h)。位于同一条直线上的这些点的{(theta,h)}集和存在一个交集,这个交集就是他们所在的同一条直线。从而霍夫变换通过确定空间里的这些点所对应的{(theta,h)},就可以确定空间里的直线。通过霍夫变换找到直线后,我们就可以通过直线的角度判断图像的倾角。
lines = cv.HoughLines(img_canny, 1, np.pi / 10, 10) if lines is None: arc = 0 else: # 提取为为二维 arc = lines[:, 0, :] arc = arc[0][1]
M = cv.getRotationMatrix2D((img.shape[0] / 2, img.shape[1] / 2), -arc, 1)

不过在实践中发现,霍夫变换的效果经常是比较差的。
(2)考虑到我们的图像中有两行字符,因此我们可以通过计算字符的倾角确定图像的倾角。
首先是确定出字符大概位置,通过计算字符的最小外接矩形得到字符的倾角。
coords = np.column_stack(np.where(img_to_calculate_angle > 0)) angle = cv.minAreaRect(coords)[-1] if angle < -45: angle = 90 + angle else: angle = -angle


3 寻找连通区域

确定连通区域有一个现成的函数:
label_img = measure.label(blurm)
props = measure.regionprops(label_img)
得到的props就是连通区域集和,我们可以计算每个联通区域的像素点个数,像素比例,周长,凸集面积等等。
prop.area:区域像素个数
prop.extent:区域与背景像素比

4 链接断开划痕
由于在阈值处理的过程中,一部分划痕被断开了。为了更精准地计算划痕的长度,需要将断开的划痕连接起来。这里查阅了一篇论文,‘’基于Prim最小生成树的路面裂缝连接算法‘’,采用了其中的算法实现断开划痕的链接。
算法思路:
(1)计算距离矩阵。计算每一条划痕的左右顶点与其他划痕左右顶点的距离。初始化空列表:linked,初始化列表:unlinked,储存所有的划痕。
(2)确定最长划痕,从unlinked中删除,添加进linked,在unlinked中寻找距离这个最长划痕最近的划痕,添加进linked
(3)在unlinked中寻找与linked中的划痕距离最近的划痕,添加进linked。循环该步骤,直至unlinked为空。
(4)判断某链接是否正确:(1)两划痕中心点的距离<=65,两划痕的角度差不超过30度(2)两划痕的连接点的横纵方向最大距离<=5或者两划痕连线的斜率与两划痕的斜率均值之差<30度,则计算两条划痕的长度和及连线的长度,代替原划痕的长度;

5 判断平行划痕
由于对方要求,当有多条临近的平行划痕,计算他们宽度的和作为平行划痕的宽度。因此需要判断平行划痕。
首先需要判断是否平行,即通过计算斜率来判断。第二需要判断是否这些划痕距离比较近,通过判断相邻的两条划痕的距离是否在一定范围内来判断。

6 判断字符识别是否受到划痕影响
分为贯穿和未贯穿但影响识别两种情况处理。

在查阅资料的过程中,发现了一个有用的函数,顺便记录一下(如果早能够发现,也许能省掉一些麻烦)。
顶帽变换和底帽变化:用于矫正不均匀光照的影响。
顶帽变换用于暗背景上的亮物体,而底帽变换则用于相反的情况。由于这一原因,当谈到这两个变换时,常常分别称为白顶帽变换和黑底帽变换。
下面,我们通过一个实例来说明此方法,对于图1(a),可以看到光照明显不均匀,左边光照更强,直接进行otsu法全局阈值得到图1(b),可以看到左边的硬币分割出错。
  由于原图是背景亮,前景暗,对原图进行底帽变换以解决光照不均匀的问题,这里先给出处理结果,如图1(c)和(d),可以看到底帽变换后的图像删除了大部分非均匀背景,最后阈值处理后,左边的硬币被分割出来,有少量残缺,但是影响不大,后续可以通过形态学的其他处理将残缺补齐。
下面是一个底帽变换的例子。

再来一个顶帽变换的例子
原图:

阈值处理:发现右下角效果不好
顶帽变换:
再进行阈值处理,发现效果变好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章