缝隙检测算法

参考链接

问题分析:

这个问题类似于边缘提取,我们想到经典的canny算子,然而canny算子不保证边缘连续,而且无法给出直线划分,但却给我们一个分析问题的方向。以下思路是在canny算子的基础上进行的。对于比较直,但长度粗细不定,有些地方非常微弱,断断续续的直线,可能是个好方向,此处记录一下。

1、计算各处的梯度向量

图像梯度即求导数,导数能反映出图像变化最大的地方,图像变化最大的地方也就是图像的边缘。

  • sobel算子与scharr算子

在sobel算子不能明显反映图像边缘时就换用scharr算子

sobel_x= \begin{bmatrix}-1&0&1\\-2&0&2\\-1&0&1\end{bmatrix}
sobel_y= \begin{bmatrix}-1&-2&-1\\0&0&0\\1&2&1\end{bmatrix}
scharr_x= \begin{bmatrix}-3&0&3\\-10&0&1 0\\-3&0&3\end{bmatrix}
scharr_y= \begin{bmatrix}-3& -10&-3\\0&0&0\\3&10&3\end{bmatrix}

import cv2 as cv

def sobel_image(img):
    grad_x = cv.Sobel(img, cv.CV_32F, 1, 0)#x方向一阶导数
    #图像  图像深度,支持src.depth()和ddepth的组合  x方向上差分阶数 y方向差分阶数
    grad_y = cv.Sobel(img, cv.CV_32F, 0, 1)#y方向一阶导数
    #print(grad_x)
    gradx = cv.convertScaleAbs(grad_x)#可通过print查看区别
    #线性输入数组转化为无符号(绝对值)8为整形
    #print(gradx)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", gradx)
    cv.imshow("y", grady)
    gradxy = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)#将两幅图像整合
    #第一个数组  第一个数组的权重  第二个数组 第二个数组的权重 gamma
    #dst = src1[I]*alpha+ src2[I]*beta + gamma;输出图像式子
    cv.imshow("x&&y", gradxy)

img = cv.imread("d://work//1.jpg")
sobel_image(img)
cv.waitKey(0)
cv.destroyAllWindows()

sobel到scharr改变求导方式即可

def scharr_image(image):
    grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)
    grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)
    gradx = cv.convertScaleAbs(grad_x)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", grad_x)
    cv.imshow("y", grad_y)
    gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
    cv.imshow("x&y_s", gradxy)

相比sobel算子把变化描述地更明显,再介绍一种lpls算子。lpls 算子有四领域和8领域的,内置函数默认是四领域

def lpls_image(image):
    dst = cv.Laplacian(image, cv.CV_32F)
    lpls = cv.convertScaleAbs(dst)
    cv.imshow("lpls", lpls)

def lpls_image(image):
    #dst = cv.Laplacian(image, cv.CV_32F)
    #lpls = cv.convertScaleAbs(dst)
    dst = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
    lpls = cv.filter2D(image, cv.CV_32F, dst)
    lpls = cv.convertScaleAbs(lpls)
    cv.imshow("lpls", lpls)
2、梯度方向上进行非最大值抑制

指寻找像素点局部最大值,将非极大值点所对应的灰度值置为0,这样可以剔除掉一大部分非边缘的点。要进行非极大值抑制,就首先要确定像素点C的灰度值在其8值邻域内是否为最大。图中蓝色的线条方向为C点的梯度方向,这样就可以确定其局部的最大值肯定分布在这条线上,也即出了C点外,梯度方向的交点dTmp1和dTmp2这两个点的值也可能会是局部最大值。因此,判断C点灰度与这两个点灰度大小即可判断C点是否为其邻域内的局部最大灰度点。如果经过判断,C点灰度值小于这两个点中的任一个,那就说明C点不是局部极大值,那么则可以排除C点为边缘。这就是非极大值抑制的工作原理。

image

在理解的过程中需要注意以下两点:

  1. 非最大抑制是回答这样一个问题:“当前的梯度值在梯度方向上是一个局部最大值吗?“ 所以,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较。
  2. 梯度方向垂直于边缘方向。但实际上,我们只能得到C点邻域的8个点的值,而dTmp1和dTmp2并不在其中,要得到这两个值就需要对该两个点两端的已知灰度进行线性插值,也即根据图1中的g1和g2对dTmp1进行插值,根据g3和g4对dTmp2进行插值,这要用到其梯度方向,这是Canny算法中要求解梯度方向矩阵\theta的原因。

完成非极大值抑制后,会得到一个二值图像,非边缘的点灰度值均为0,可能为边缘的局部灰度极大值点可设置其灰度为128。检测结果还是包含了很多由噪声及其他原因造成的假边缘。因此还需要进一步的处理。

3. 边缘追溯

我们对图像进行边缘追溯,canny算子除了给我们提供了边缘之外,其实还有丰富的局部梯度信息,而我们提取的缝隙都是直线,因而梯度信息是非常宝贵的。

For每个图像中的点:

        If 当前点 == 0:continue

        While 两端还活着:

                试图沿着梯度的垂直方向生长,找下一个点(如果没找到,生命值-1)

                找到后判别目标点的梯度向量是否与当前集合平均一致

                一致则合并,生命恢复,计算新的平均梯度,不一致则生命值-1

                生命减到1,停止生长

优势:考虑了梯度方向问题,可以很好的排除非自己所属的边缘

加入生命值的概念,可以在断的时候,继续沿着梯度垂直方向生长,得以延续。

4. 直线性判别

所有直线都生长结束后,对每个轮廓进行特征值分解,用较小的特征值进行线性度判定。

5. 线段配对

1)两个线段长度相似

2)两个线段质心接近

3)两个线段梯度向量相对立

总结:算法基于canny算子,在极大值抑制后,没有进行双阈值,而是保留梯度向量进行线段追溯,追溯过程中加入生命值概念,让直线延续性得以保证,而有梯度和生长方向概念,也不会混入其他点,得到纯净点后进行直线度检验,最后对所有提取出来的直线进行配对,得到结果。

附Imagepy github链接
https://github.com/yxdragon/imagepy.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343