✨ 长期致力于滑坡监测、垮塌检测、深度学习、残差网络、结构相似度、三维重建、双目视觉研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
如需沟通交流,点击《获取方式


(1)植被-岩土分离的深度卷积对抗网络:

提出Vegetation-Rock Adversarial Segmentation Net,VRASNet。网络采用生成对抗结构,生成器为改进的DeepLabV3+,以RGB图像输入,输出二值掩膜(植被为1,岩土为0)。判别器为五层卷积网络,判断分割结果与真实标注的一致性。为增强对阴影和光照变化的鲁棒性,在生成器输入端增加光照归一化模块,通过估计图像局部均值和标准差进行自适应变换。训练数据集由意大利Perarolo滑坡区连续12个月每月拍摄的200张图像构成,共2400张,人工标注植被区域。采用多尺度训练,输入尺寸512x512,批次大小4,生成器学习率0.0001,判别器0.0004,交替训练200个epoch。最终生成器分割精度达到平均交并比0.912,植被像素检测召回率99.3%,虚警率仅2.1%。相比无对抗的DeepLabV3+,植被边界处的平均误差从4.2像素降至2.1像素。该网络在测试视频序列上处理速度达到每秒15帧,满足监测需求。

(2)时序结构相似度与自适应阈值垮塌检测:

开发基于滑动窗口非相似性积累的垮塌事件检测算法,命名为Temporal SSIM Accumulator,TSSIMA。算法对每个监控点位,连续采集图像序列,帧率设为0.2Hz。首先应用VRASNet得到岩土图层,然后计算相邻两帧岩土图层的结构相似度SSIM图,SSIM图的每个像素表示局部窗口的亮度、对比度和结构相似性组合值。对SSIM图进行高斯滤波后,构造一个自适应阈值:以过去24小时的SSIM图均值为参考,加上2倍标准差作为动态阈值。当SSIM图中低于阈值的像素区域面积超过预设面积2000像素时,触发潜在垮塌事件。为避免相机微小振动导致的虚假触发,引入振动补偿模块:在图像四角设置四个固定控制点,通过仿射变换对齐连续帧。将连续三次触发(间隔5秒)才确认为真正垮塌。在Perarolo滑坡半年期的监测中,TSSIMA成功检测到7次局部垮塌事件,无漏报,虚报2次(由动物活动引起)。传统基于差异阈值的方法漏报3次,虚报5次。

(3)稀疏点云下垮塌体三维重建与体积计算:

提出双目视觉与深度补全网络融合的重建流程,Stereo-Depth Completion Network,SDCN。使用两个200万像素工业相机,基线长度1.2米,同步采集图像。首先通过半全局立体匹配SGBM生成初始视差图,视差范围设为0-80像素。然后训练一个深度补全网络,输入初始视差图和原始左图,输出密集视差图。网络采用编码-解码结构,编码器中加入空洞卷积金字塔以捕捉多尺度上下文。在垮塌发生前后各取一对立体图像,分别生成密集三维点云。将两期点云进行粗配准(基于点云法向量的快速点特征直方图)和精配准(迭代最近点ICP)。垮塌区域定义为两期点云间欧氏距离超过0.1米的点集。对垮塌点云,使用泊松表面重建生成三角网格,然后计算网格包围的闭合体积。通过人工预埋已知体积的标定块进行验证,体积计算误差在8%以内。在一次体积约12.5立方米的垮塌事件中,SDCN计算体积为11.9立方米,误差-4.8%,而仅用SGBM稀疏点云的方法误差为-21%。整个处理流程从图像采集体积输出耗时约90秒,适用于日常巡检。

import cv2
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F

class VRASGenerator(nn.Module):
    def __init__(self):
        super().__init__()
        self.backbone = torch.hub.load('pytorch/vision', 'resnet50', pretrained=True)
        self.aspp = nn.Sequential(
            nn.Conv2d(2048,256,1),
            nn.Conv2d(2048,256,3,padding=6,dilation=6),
            nn.Conv2d(2048,256,3,padding=12,dilation=12),
            nn.Conv2d(2048,256,3,padding=18,dilation=18)
        )
        self.decoder = nn.Sequential(
            nn.Conv2d(1024,256,3,padding=1), nn.ReLU(),
            nn.Conv2d(256, 64, 3, padding=1), nn.ReLU(),
            nn.Conv2d(64, 1, 1)
        )

    def forward(self, x):
        feat = self.backbone.conv1(x)
        feat = self.backbone.bn1(feat)
        feat = self.backbone.relu(feat)
        feat = self.backbone.maxpool(feat)
        feat = self.backbone.layer1(feat)
        feat = self.backbone.layer2(feat)
        feat = self.backbone.layer3(feat)
        feat = self.backbone.layer4(feat)
        aspp_out = []
        for layer in self.aspp:
            aspp_out.append(layer(feat))
        aspp_cat = torch.cat(aspp_out, dim=1)
        out = self.decoder(aspp_cat)
        return torch.sigmoid(out)

def ssim_map(img1, img2, window_size=11, sigma=1.5):
    from scipy.ndimage import gaussian_filter
    mu1 = gaussian_filter(img1, sigma)
    mu2 = gaussian_filter(img2, sigma)
    sigma1 = gaussian_filter(img1**2, sigma) - mu1**2
    sigma2 = gaussian_filter(img2**2, sigma) - mu2**2
    sigma12 = gaussian_filter(img1*img2, sigma) - mu1*mu2
    C1 = 0.01**2
    C2 = 0.03**2
    ssim = (2*mu1*mu2 + C1)*(2*sigma12 + C2) / ((mu1**2+mu2**2+C1)*(sigma1+sigma2+C2))
    return ssim

def adaptive_threshold_accumulator(ssim_seq, lookback=24):
    threshold_arr = []
    for i in range(lookback, len(ssim_seq)):
        window = np.array(ssim_seq[i-lookback:i])
        mean = np.mean(window)
        std = np.std(window)
        thr = mean - 2*std
        threshold_arr.append(thr)
    return np.array(threshold_arr)

def stereo_depth_completion(left_img, right_img, max_disp=80):
    stereo = cv2.StereoSGBM_create(minDisparity=0, numDisparities=max_disp, blockSize=11)
    disp = stereo.compute(left_img, right_img).astype(np.float32) / 16.0
    # 深度补全网络简化模拟:使用导向滤波填充空洞
    guide = cv2.cvtColor(left_img, cv2.COLOR_BGR2GRAY).astype(np.float32)/255.0
    disp_filled = cv2.ximgproc.guidedFilter(guide=guide, src=disp, radius=20, eps=1e-4)
    Q = np.float32([[1,0,0,-left_img.shape[1]/2],
                    [0,1,0,-left_img.shape[0]/2],
                    [0,0,0,1],
                    [0,0,1,0]])
    points = cv2.reprojectImageTo3D(disp_filled, Q)
    return points

def compute_volume(pcl, voxel_size=0.05):
    import open3d as o3d
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(pcl)
    pcd.estimate_normals()
    mesh, _ = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=9)
    return mesh.get_volume()

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐