探地雷达(GPR)检测地下钢筋,并可视化钢筋

先说一下,这篇博文是关于 地下钢筋串线 的,就是用 探地雷达(GPR)检测到地下的钢筋 ,成像是多张 Bscan图像,每张Bscan图像中都有许多钢筋的形状。将多张Bscan中属于同一条钢筋的串起来,并做一个可视化的效果。


前言

首先来看一下我们用探地雷达(GPR)采集到的地下病害数据。假设 多条钢筋在地下的朝向探地雷达行进的方向一致 ,那么在不同位置,雷达就会呈现出不同的Bscan图像。如下图就是多条钢筋,不同部位的图像。

(注意:这里,我们需要通过网络模型去检测到每张Bscan的钢筋,并且得到钢筋的框坐标,然后才能进行后续工作。目标检测的模型很多,比如Faster-rcnn,YOLO等,本文只讲如何串线)

在这里插入图片描述

我现在要做的就是将多张Bscan图像中属于同一条的钢筋串起来,并且可视化。


一、问题分析,钢筋串线

我们分析一下上面的三幅Bscan图像,可以得知,属于同一条钢筋的话,那么它在各自Bscan图像上的位置大致是一样的,至少差别不大。所以,我们可以通过位置信息来判断它属于哪一条钢筋。可以在X和Y方向上都设定一个阈值,只要位置(坐标)之差在阈值内则属于同一条钢筋,否则不属于同一条钢筋。

(先不考虑钢筋条斜着的情况)。

二、钢筋串线步骤

1.找到每张Bscan中钢筋的顶点

为什么要找到每张Bscan中钢筋的顶点?第一,因为能更加方便的串线,也比较简单。第二,实现也比较容易,可以通过传统的图像处理方式实现。找到顶点之后,记录它在整张Bscan图像上的图像坐标(像素坐标)

代码如下(示例):

def get_top(src, w_th=3, h_th=3):
	#src代表钢筋图像
    ret, thresh1 = cv2.threshold(src, 180, 255, cv2.THRESH_BINARY)
    height, weight = np.shape(thresh1)
    h = np.zeros(height, dtype=np.int)
    w = np.zeros(weight, dtype=np.int)
    for i in range(height):
        for j in range(weight):
            if src[i][j] == 255:
                h[i] += 1
                w[j] += 1
    max = 0
    y = 0
    for i in range(height):
        if h[i] > h_th:
            y = i
            break
    for j in range(weight):
        if w[j]>max:
            max = w[j]
    x1 = x2 = 0
    for j in range(weight):
        if w[j] < max-w_th and x2 == 0:
            x1 += 1
        elif w[j] >= max-w_th:
            x2 += 1
    return [y, int(x1+x2/2)]  #返回顶点坐标

结果如下图所示:
在这里插入图片描述

2.根据顶点坐标,通过X和Y方向的阈值判断是否属于统一条钢筋

这一步比较简单,就是 比较前后Bscan图相应位置上顶点的X和Y方向的差值 ,差值小于阈值则认为是同一条钢筋,否则不属于同一条钢筋。这里,我把所有的顶点按照钢筋进行了区分,并且把区分的结果存在一个字典中,型如:

testpipline={
“0”:[ #第0条钢筋有哪些顶点
{‘class’: ‘00’, ‘id’: 0, ‘pointy’: 85, ‘pointx’: 606, ‘d’: 1, ‘z’: 0}, # 'z’代表属于哪一张Bscan图
{‘class’: ‘00’, ‘id’: 0, ‘pointy’: 83, ‘pointx’: 605, ‘d’: 1, ‘z’: 1}
]}

代码如下(示例):

def getpipline(result_list_2d_all):
	# result_list_2d_all是一个字典,里面包含所有的顶点信息
    x_threhold = 10  #x方向阈值
    y_threhold = 20  #y方向阈值
    # 先把所有的PIP按照属于哪一张Bscan进行分类
    split_list_2d = splitlsit_2d(result_list_2d_all)
    list_len = len(split_list_2d)
    # 把第一个bscan的所有顶点赋给pipline,认为初始的钢筋条数等于第一张Bscan的Pip的总数
    init_pipline(split_list_2d)
    index = 1
    if list_len == 0:
        print("result_list_2d_all is empty!")
    if list_len == 1:
        return split_list_2d[0]
    else:
        while index < list_len:
            #从第二张Bscan开始,依次和前面所有PIP顶点进行匹配
            findpoints(split_list_2d[index], x_threhold, y_threhold)
            index += 1

    w = open('result_piplines2.txt', 'w')
    for kk in pipline:
        w.write('{}:\n'.format(kk))
        for jj in pipline[kk]:
            w.write('{},{},{}\n'.format(jj["pointx"],jj["pointy"],jj["z"]))
    w.close()

    return pipline

3.将像素坐标转化为实际地理坐标(重点)

这里说明一下,探地雷达(GPR)在行进的过程中,我们生成了一个txt文件,记录了采集时的实际地理位置(x,y,z=0),z=0是因为GPR始终在地表面。如下图,探地雷达向地下发射电磁波,它在地表面有真实的(x,y,z=0)坐标,生成的Bscan图的钢筋顶点有(pointx,pointy)像素坐标。
因此,我们可以根据钢筋顶点的 pointx,在 txt 文件的第 pointx 行找到该点真实坐标(x,y)。至于该点的深度,通过公式:deep= pointy / 450 * 1.5 ,这个公式是根据GPR设置的。
(这里其实不难,只要明白GPR采集数据的过程就能懂了。)

在这里插入图片描述
在这里插入图片描述

4.可视化串线结果

通过上面三步,我们已经能得到所有Bscan图中,每个钢筋顶点的实际坐标,并且将这些顶点按照是否属于一条钢筋进行了分类。

#获取转换为实际坐标后的顶点,返回的一个字典类型
res=changePipCor()

figure = plt.figure()
axes = Axes3D(figure)  #使用了Axes3D进行可视化
for k in res:
    x=[]
    y=[]
    z=[]
    print("{}:".format(k))
    for l in res[k]:
        print("l:",l)
        x.append(float(l["pip_factx"]))
        y.append(float(l["pip_facty"]))
        z.append(float(l["pip_factz"]))
    x=np.array(x)
    y = np.array(y)
    z = np.array(z)
    cc=randomcolor()
    axes.scatter(x, y, z, color=cc) #可视化

plt.show()

结果如下图所示:
在这里插入图片描述

三、总结

总的来说:
1.我先通过深度学习模型检测出每一张Bscan图像里面的钢筋,并且返回目标框的坐标。
2.通过检测的目标框,找到每个钢筋顶点的像素坐标。
3.通过像素坐标,设定X和Y方向阈值,判断哪些顶点属于同一条钢筋,进行分类。
4.将分好类的像素坐标转化为实际坐标,(这里要了解GPR采集数据的过程)
5.根据实际坐标可视化

(注意:当然,我这种方法还没能解决钢筋在地下斜放着的情况,这可能涉及到聚类,优化等方法,还需要考虑到更多信息,如果您有更好的方法,欢迎交流。希望本文对您有帮助!)


  • 8
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值