直方图投影法判断裂缝走势(裂缝类型)

裂缝类型

裂缝类型有很多种,这里我们仅仅判断线性裂缝与网状裂缝,线性裂缝按照其走势有可分为横向裂缝、纵向裂缝和斜向裂缝。

我觉得大家应当有这样的意识,面对网状裂缝,它的二维参数是否有意义?答案是没有!如果检测到网状裂缝,我想大家的第一反应是比较严重了,需要修补了。如果是一条线性裂缝呢?我是不是还有考虑一下它的受损程度是否达到需要修补的地步。

所以按照我的想法,可以求网状裂缝的面积,评估其受损程度,求线性裂缝的面积、长度和宽度,评估其受损程度。

直方图投影法

网状裂缝的直方图投影 

横向裂缝的直方图投影 

纵向裂缝的直方图投影 

斜向裂缝的直方图投影 

上面四张图是四种裂缝对应的直方图,结合上面的一些特点,我们可以依照自己的数据集进行类型分类。

 获取最小外接矩形信息

接下来,get_minAreaRect_information函数会从二值化掩膜图像中提取最小外接矩形的相关信息,包括中心点坐标、宽高和旋转角度。inference_minAreaRect函数用于计算最小外接矩形框的宽、高和角度信息,并将角度转换为相对于图像水平方向的夹角。

def inference_minAreaRect(minAreaRect):w, h = minAreaRect[1]if w > h:angle = int(minAreaRect[2])else:angle = -(90 - int(minAreaRect[2]))return w, h, angledef _get_minAreaRect_information(mask):mask = pz.BinaryImg(mask)contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)contour_merge = np.vstack(contours)minAreaRect = cv2.minAreaRect(contour_merge)return minAreaRect

pz.BinaryImg获取图像二值图,请确保读取时候为BGR的图片。 

初始化分类裂缝的参数

创建了一个ClassificationCrack类,并且对裂缝的分类参数进行初始化,有分类裂缝的阈值threshold,分类裂缝的高宽比阈值HWration,用于分类裂缝的直方图比例阈值Histration。

class CrackType():"""直方图投影法推断裂缝类型"""def __init__(self, threshold=3, HWratio=10, Histratio=0.5):"""初始化分类裂缝的参数:param threshold: 阈值,用于分类裂缝的阈值:param HWratio: 高宽比,用于分类裂缝的高宽比阈值:param Histratio: 直方图比例,用于分类裂缝的直方图比例阈值"""self.threshold = thresholdself.HWratio = HWratioself.Histratio = Histratioself.types = {0: 'Horizontal',1: 'Vertical',2: 'Oblique',3: 'Mesh'}

这里我们使用字典self.types,这样就可以通过键值对判断裂缝的类型了。

骨骼点投影直方图

在ClassificationCrack类下,我们再定义了一个hist_judge的方法,less_than_T统计直方图中大于 0 且小于等于阈值 self.threshold 的像素数量,more_than_T统计直方图中大于阈值 self.threshold 的像素数量。通过more_than_T / (less_than_T + 1e-5)来比较是否超过了直方图比例阈值。

    def hist_judge(self, hist_v):less_than_T = np.count_nonzero((hist_v > 0) & (hist_v <= self.threshold))more_than_T = np.count_nonzero(hist_v > self.threshold)return more_than_T / (less_than_T + 1e-5) > self.Histratio

裂缝分类

classify 方法是 ClassificationCrack 类中的另一个成员方法,它接收三个值,minAreaRect 是一个元组,表示最小外接矩形框的信息,包括中心点坐标、宽高和旋转角度;skeleton_pts是一个数组,表示骨骼点的坐标;HW是当前 patch 的高和宽。

    def classify(self, minAreaRect, skeleton_pts, HW):H, W = HWw, h, angle = inference_minAreaRect(minAreaRect)if w / h < self.HWratio or h / w < self.HWratio:pts_y, pts_x = skeleton_pts[:, 0], skeleton_pts[:, 1]hist_x = np.histogram(pts_x, W)hist_y = np.histogram(pts_y, H)if self.hist_judge(hist_x[0]) and self.hist_judge(hist_y[0]):return 3return self.angle2cls(angle)@staticmethoddef angle2cls(angle):angle = abs(angle)assert 0 <= angle <= 90, "ERROR: The angle value exceeds the limit and should be between 0 and 90 degrees!"if angle < 35:return 0elif 35 <= angle <= 55:return 2elif angle > 55:return 1else:return None

利用 inference_minAreaRect 函数从 minAreaRect 中获取旋转矩形框的宽度 w、高度 h 和角度 angle。接下来,通过判断 w / h 和 h / w 是否小于 self.HWratio 来判断旋转矩形框的长宽比是否满足分类条件。

如果长宽比满足条件,则将 skeleton_pts 按照 x 和 y 方向投影到直方图 hist_x 和 hist_y,然后通过 self.hist_judge 方法判断这两个直方图是否满足分类条件。

以上条件均满足,则会认为是网状裂缝,否则就使用angle2cls来进行角度分类。

根据角度的大小将裂缝分为以下三类:

  • 如果角度小于 35 度,则返回 0,表示水平裂缝。
  • 如果角度在 35 到 55 度之间,则返回 2,表示倾斜裂缝。
  • 如果角度大于 55 度,则返回 1,表示垂直裂缝。
  • 如果角度不在上述范围内,则返回 None 。

测试文件main

"""
裂缝分类如何判断
横向、纵向、网状、斜裂缝
"""
import os
import matplotlib.pyplot as pltimport numpy as np
import cv2
import pyzjr as pzfrom skimage.morphology import skeletonize
from skimage.filters import threshold_otsu
from skimage.color import rgb2grayclass CrackType():"""直方图投影法推断裂缝类型"""def __init__(self, threshold=3, HWratio=10, Histratio=0.5):"""初始化分类裂缝的参数:param threshold: 阈值,用于分类裂缝的阈值:param HWratio: 高宽比,用于分类裂缝的高宽比阈值:param Histratio: 直方图比例,用于分类裂缝的直方图比例阈值"""self.threshold = thresholdself.HWratio = HWratioself.Histratio = Histratioself.types = {0: 'Horizontal',1: 'Vertical',2: 'Oblique',3: 'Mesh'}def inference_minAreaRect(self, minAreaRect):"""旋转矩形框长边与x轴的夹角.旋转角度 angle 是相对于图像水平方向的夹角,范围是 -90 到 +90 度.然而,一般情况下,我们习惯将角度定义为相对于 x 轴正方向的夹角,范围是 -180 到 +180 度."""w, h = minAreaRect[1]if w > h:angle = int(minAreaRect[2])else:angle = -(90 - int(minAreaRect[2]))return w, h, angledef classify(self, minAreaRect, skeleton_pts, HW):"""针对当前crack instance,对其进行分类;主要利用了骨骼点双向投影直方图、旋转矩形框宽高比/角度;:param minAreaRect: 最小外接矩形框,[(cx, cy), (w, h), angle];:param skeleton_pts: 骨骼点坐标;:param HW: 当前patch的高、宽;"""H, W = HWw, h, angle = self.inference_minAreaRect(minAreaRect)if w / h < self.HWratio or h / w < self.HWratio:pts_y, pts_x = skeleton_pts[:, 0], skeleton_pts[:, 1]hist_x = np.histogram(pts_x, W)hist_y = np.histogram(pts_y, H)if self.hist_judge(hist_x[0]) and self.hist_judge(hist_y[0]):return 3return self.angle2cls(angle)def hist_judge(self, hist_v):less_than_T = np.count_nonzero((hist_v > 0) & (hist_v <= self.threshold))more_than_T = np.count_nonzero(hist_v > self.threshold)return more_than_T / (less_than_T + 1e-5) > self.Histratio@staticmethoddef angle2cls(angle):angle = abs(angle)assert 0 <= angle <= 90, "ERROR: The angle value exceeds the limit and should be between 0 and 90 degrees!"if angle < 35:return 0elif 35 <= angle <= 55:return 2elif angle > 55:return 1else:return Nonedef _get_minAreaRect_information(mask):"""从二值化掩膜图像中获取最小外接矩形的相关信息:param mask:二值化掩膜图像,包含目标区域的白色区域:return:最小外接矩形的信息,包括中心点坐标、宽高和旋转角度"""mask = pz.BinaryImg(mask)contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)contour_merge = np.vstack(contours)minAreaRect = cv2.minAreaRect(contour_merge)return minAreaRectdef SkeletonMap(target):"""获取骨架图的信息:param target: 目标图:return: 骨架图与一个数组,其中每一行表示一个非零元素的索引(y,x),包括行索引和列索引"""gray = rgb2gray(target)thresh = threshold_otsu(gray)binary = gray > threshskimage = skeletonize(binary)skepoints = np.argwhere(skimage)skimage = skimage.astype(np.uint8)return skimage, skepointsif __name__ == '__main__':plt.switch_backend('TkAgg')masks_dir = r"D:\PythonProject\RoadCrack\dimension2_data\num"  # 这里改为存放上面图片的路径results_save_dir = "A_results"os.makedirs(results_save_dir, exist_ok=True)classifier = CrackType()imgfile,_ = pz.getPhotopath(masks_dir, debug=False)for path in imgfile:mask = cv2.imread(path)H, W = mask.shape[:2]mask_copy = mask.copy()skeimage, skepoints = SkeletonMap(mask_copy)minAreaRect=_get_minAreaRect_information(mask)pts_y, pts_x = skepoints[:, 0], skepoints[:, 1]hist_x = np.histogram(pts_x, W)hist_y = np.histogram(pts_y, H)result = classifier.classify(minAreaRect, skepoints, HW=(H, W))crack_type = classifier.types[result]print(crack_type)T = classifier.thresholdplt.figure(figsize=(10, 5))plt.subplot(121)plt.plot(hist_x[1][:-1], [T] * len(hist_x[0]), 'r')plt.bar(hist_x[1][:-1], hist_x[0])plt.title("Histogram X")plt.subplot(122)plt.plot(hist_y[1][:-1], [T] * len(hist_y[0]), 'r')plt.bar(hist_y[1][:-1], hist_y[0])plt.title("Histogram Y")plt.tight_layout()  # 自动调整子图布局,防止重叠plt.show()

与我们实际图片进行对比,其检测效果均还不错,threshold,HWratio,Histratio这三个初始值均为经验所得,还是要依照自己的数据来设定。这里的SkeletionMap函数将会获得骨架图中的索引点,它并没有进行去消除毛刺的,实际并不影响,因为我们采用的这个方法,些许毛刺影响不了判断。

现在我们只需要写一个推动裂缝类型的函数,可以用于直接去判断我们设定的裂缝类型:

def infertype(mask):"""推导裂缝类型"""crack = CrackType()H, W = mask.shape[:2]mask_copy = mask.copy()skeimage, skepoints = SkeletonMap(mask_copy)minAreaRect = _get_minAreaRect_information(mask)result = crack.classify(minAreaRect, skepoints, HW=(H, W))crack_type = crack.types[result]return result, crack_type

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决 MyBatis-Plus 中增加修改时,对应时间的更新问题

问题&#xff1a;在添加修改时&#xff0c;对应的 create_time 与 insert_time 不会随着添加修改而自动的更新时间 第一步&#xff1a;首先在对应的属性上&#xff0c;加上以下注解 如果只添加以下注解&#xff0c;在增加或者修改时&#xff0c;可能对应的 LocalDateTime 会出…

Vue小笔记

官网中文手册 常用命令 vue标签大杂烩 v-if&#xff1a;条件渲染v-else: 如果为 false, 当前标签才会输出到页面v-show : 通过控制 display 样式来控制显示/隐藏v-for&#xff1a; 列表渲染v-on&#xff1a; 事件监听。 v-on&#xff1a; 。事件修饰符&#xff1a;鼠标事件&…

GB/T 14710-2009 医用电器环境要求及试验方法

举个例子&#xff1a; 应符合GB/T 14710-2009中气候环境试验II组&#xff0c;机械环境试验II组的要求。 气候环境试验II组&#xff0c;机械环境试验II组&#xff1f; 这是2个属性&#xff0c;先按特定的条件分组&#xff0c;分组后&#xff0c;应该满足该组的特定要求。这个标…

Linux面试题汇总1

MySQL数据库 1、MySQL和Oracle的区别 1.Oracle是大型数据库&#xff0c;而MySQL是中小型数据库。但是MySQL是开源的&#xff0c;但是Oracle是收费的&#xff0c;而且比较贵。 2. Oracle的内存占有量非常大&#xff0c;而mysql非常小 3. MySQL支持主键自增长&#xff0c;指定主…

Java初级到中级:技术提升的策略与方法

文章目录 1 问题背景2 前言3 方法 1 问题背景 截至2023年7月&#xff0c;笔者已经毕业2年了&#xff0c;每天都在搬砖打螺丝&#xff0c;自我感觉需要沉淀、思考、总结一下。思考和总结一下如何从Java初级提升到Java中级&#xff0c;需要掌握一些什么方法论&#xff0c;有效地去…

宝塔Node部署nuxt3

宝塔Node部署nuxt3 1、首先本地执行打包 yarn build2、然后把目录中的这个文件压缩成zip 3、在宝塔文件处添加一个网站的文件目录&#xff0c;并把文件解压到里面 4、点击左侧的网站&#xff0c;然后选择node项目&#xff0c;选择node版本安装 5、安装完后&#xff0c;点击新…

Minecraft 1.20.x Forge模组开发 06.建筑生成

我们本次尝试在主世界生成一个自定义的建筑。 效果展示 效果展示 效果展示 由于版本更新缘故,1.20的建筑生成将不涉及任何Java包的代码编写,只需要在数据包中对建筑生成进行自定义。 1.首先我们要使用游戏中的结构方块制作一个建筑,结构方块使用教程参考1.16.5自定义建筑生…

el-menu 导航栏学习(1)

最简单的导航栏学习跳转实例效果&#xff1a; &#xff08;1&#xff09;index.js路由配置&#xff1a; import Vue from vue import Router from vue-router import NavMenuDemo from /components/NavMenuDemo import test1 from /components/test1 import test2 from /c…

nodejs+vue 经典建筑网站elementui

第1章 项目概述 1 1.1 问题描述 1 1.2 项目目标 1 1.3 项目适用范围 2 1.4 项目应遵守的规范与标准 2 1.5 涉众 2 具有功能强大、支持跨平台、运行速度快、安全性高、成本低等优点。而对于后者我们使用 来完成它&#xff0c;使其网页功能完备&#xff0c;界面友好、易开发、易…

华为云云耀云服务器L实例评测|使用华为云耀云服务器L实例的CentOS部署Docker并运行Tomcat应用

目录 前言 步骤1&#xff1a;登录到华为云耀云服务器L实例 步骤2&#xff1a;安装Docker 并验证Docker安装 步骤3&#xff1a;拉取Tomcat镜像并运行Tomcat容器 步骤4&#xff1a;放行8080端口 步骤5&#xff1a;访问tomcat 步骤6&#xff1a;管理Tomcat容器 小结 前言 …

【c语言的malloc函数介绍】

malloc&#xff08;memory allocation的缩写&#xff09;是C语言中的一个函数&#xff0c;用于动态分配内存空间。这个函数允许你在程序运行时请求指定大小的内存块&#xff0c;以供后续使用。malloc函数属于标准库函数&#xff0c;需要包含头文件#include <stdlib.h> 才…

NLP 项目:维基百科文章爬虫和分类 - 语料库阅读器

塞巴斯蒂安 一、说明 自然语言处理是机器学习和人工智能的一个迷人领域。这篇博客文章启动了一个具体的 NLP 项目&#xff0c;涉及使用维基百科文章进行聚类、分类和知识提取。灵感和一般方法源自《Applied Text Analysis with Python》一书。 在接下来的文章中&#xff0c;我将…

本地项目远程Linux运行

文章目录 1 本地安装anconda&#xff08;如果不需要在本地运行&#xff0c;这步可以忽略&#xff09;2 进入本地conda环境&#xff08;如果不需要在本地运行&#xff0c;这步可以忽略&#xff09;2.1 查看已存在的环境2.2 创建新的conda环境2.3 激活新建的环境2.4 安装tensorfl…

大学生登记国家证书软件著作权提升就业资质

大学生登记国家证书软件著作权提升就业资质 随着信息技术的快速发展&#xff0c;软件行业成为了许多大学生就业的热门选择之一。然而&#xff0c;在竞争激烈的就业市场中&#xff0c;除了掌握专业知识和技能外&#xff0c;如何提升自己的就业资质也显得尤为重要。其中&#xff…

Vivado与Notepad++关联步骤

填写内容 先看"关联步骤"再看此处&#xff1a; 在“editor”栏中填写 Notepad的路径&#xff0c;并加上[file name] -n[line number]&#xff0c; 这里我的 Notepad 的路径为 C:/Program Files (x86)/Notepad/notepad.exe &#xff1b; 故这里我就填上以下内容即可…

[C#]vs2022安装后C#创建winform没有.net framework4.8

问题&#xff0c;我已经在visualstudio安装程序中安装了.net框架4.8的SDK和运行时。 然而&#xff0c;我在visual studio 2022中找不到已安装的框架。 我已经检查了我的VS 2019&#xff0c;它可以很好地定位网络框架4.8&#xff0c;它可以构建我的项目。但VS 2022不能。 我已经…

idea集成tomcat(Smart Tomcate插件安装)

当我们在 tomcat 上部署好一个 webapp 后&#xff0c;如果我们要修改代码&#xff0c;就需要重新进行打包和部署&#xff0c;但往往在工作中是需要频繁修改代码&#xff0c;然后再查看成果的&#xff0c;就需要反复的进行打包和部署的过程&#xff0c;这是很麻烦的 通过 Smart …

C# 继承

C# 继承 继承的类型实现继承虚方法隐藏方法调用函数的基类版本抽象类和抽象函数密封类和密封方法派生类的构造函数修饰符访问修饰符其他修饰符 接口 继承的类型 实现继承 表示一个类型派生于一个基类型&#xff0c;拥有该基类型的所有成员字段和函数。在实现继承中&#xff0c…

Seata入门系列【1】安装seata 1.7.1+nacos 2.1.1

1 介绍 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Github: https://github.com/seata/seata 官方文档&#xff1a;h…

苹果曾考虑基于定位控制AirPods Pro自适应音频

在一次最近的采访中&#xff0c;苹果公司的高管Ron Huang和Eric Treski透露&#xff0c;他们在开发AirPods Pro自适应音频功能时&#xff0c;曾考虑使用GPS信号来控制音频级别。这个有趣的细节打破了我们对AirPods Pro的固有认知&#xff0c;让我们对苹果的创新思维有了更深的…