This commit is contained in:
琉璃月光
2025-10-21 14:11:52 +08:00
parent 349449f2b7
commit df7c0730f5
363 changed files with 5386 additions and 578 deletions

BIN
guanghuaban/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

BIN
guanghuaban/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

BIN
guanghuaban/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

76
guanghuaban/FFT.py Normal file
View File

@ -0,0 +1,76 @@
import matplotlib
matplotlib.use('Agg') # 使用非 GUI 后端
import cv2
import numpy as np
import matplotlib.pyplot as plt
def analyze_surface_roughness(image_path):
# 读取图像
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if img is None:
raise FileNotFoundError(f"无法加载图像: {image_path}")
# 预处理
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
img = clahe.apply(img)
img = cv2.medianBlur(img, 5)
# FFT
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20 * np.log(np.abs(fshift) + 1e-9)
# 动态低频区域
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
radius = min(rows, cols) // 20
mask = np.ones((rows, cols), np.uint8)
cv2.circle(mask, (ccol, crow), radius, 0, thickness=-1)
# 计算能量占比
total_energy = np.sum(magnitude_spectrum)
high_freq_energy = np.sum(magnitude_spectrum * mask)
ratio = high_freq_energy / total_energy
# 可视化并保存
plt.figure(figsize=(12, 6))
plt.subplot(1, 3, 1)
plt.imshow(img, cmap='gray')
plt.title('预处理后图像')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('频谱图(中心为低频)')
plt.axis('off')
overlay = magnitude_spectrum.copy()
if len(overlay.shape) == 2:
overlay = np.stack([overlay]*3, axis=-1)
cv2.circle(overlay, (ccol, crow), radius, (1, 0, 0), 2)
plt.subplot(1, 3, 3)
plt.imshow(overlay)
plt.title(f'低频区域(红圈内)\n高频能量占比: {ratio:.3f}')
plt.axis('off')
plt.tight_layout()
plt.savefig("fft_analysis_result.png", dpi=150, bbox_inches='tight')
plt.close() # 释放内存
# 输出结果
print(f"✅ 图像尺寸: {cols}x{rows}")
print(f"📊 高频能量占比: {ratio:.3f}")
if ratio < 0.8:
print("🟢 评价: 表面较光滑")
elif ratio < 0.95:
print("🟡 评价: 表面中等粗糙")
else:
print("🔴 评价: 表面非常粗糙")
return ratio
# 运行
if __name__ == "__main__":
analyze_surface_roughness("1.jpg")

56
guanghuaban/GLCM.py Normal file
View File

@ -0,0 +1,56 @@
from skimage import feature
import cv2
import numpy as np
import os
# 图像路径
img_path = "2.jpg"
# ✅ 1. 检查文件是否存在
if not os.path.exists(img_path):
raise FileNotFoundError(f"图像文件不存在,请检查路径: {img_path}")
# ✅ 2. 以灰度模式读取图像
img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
if img is None:
raise ValueError(f"无法读取图像,可能是文件损坏或格式问题: {img_path}")
print(f"✅ 图像加载成功,原始尺寸: {img.shape}")
'''
height, width = img.shape
start_row = height // 3 * 2 # 从 2/3 处开始,到底部
bottom_region = img[start_row:, :] # 所有列,只取底部 1/3 行
print(f"✅ 裁剪出底部 1/3 区域,尺寸: {bottom_region.shape}")
'''
# ✅ 3. 提取最下方三分之一的区域
bottom_region = img
# ✅ 4. 计算 GLCM建议降低 levels 或使用压缩)
# 注意levels=256 对计算资源要求高,可考虑先归一化到 32 或 64 灰度级
# 这里我们先保持 256若报内存错误可改用降级方法
glcm = feature.graycomatrix(
bottom_region,
distances=[1],
angles=[0, np.pi/4, np.pi/2, 3*np.pi/4], # 多方向
levels=256,
symmetric=True,
normed=True
)
# ✅ 5. 提取平均纹理特征(在所有方向上取均值)
properties = ['contrast', 'dissimilarity', 'homogeneity', 'energy', 'correlation']
features = {}
for prop in properties:
values = feature.graycoprops(glcm, prop)[0]
features[prop] = np.mean(values) # 对多个角度取平均
# ✅ 6. 输出结果
print("\n📊 图像底部 1/3 区域的纹理特征:")
print(f"Contrast: {features['contrast']:.3f}") # 越大越粗糙230
print(f"Dissimilarity: {features['dissimilarity']:.3f}") # 越大差异越大7.265
print(f"Homogeneity: {features['homogeneity']:.3f}") # 越小越不均匀粗糙0.291
print(f"Energy: {features['energy']:.3f}") # 越小越复杂纹理丰富0.033
print(f"Correlation: {features['correlation']:.3f}") # 灰度线性相关性0.941

17
guanghuaban/LBP.py Normal file
View File

@ -0,0 +1,17 @@
from skimage import feature
import matplotlib.pyplot as plt
import cv2
import numpy as np
# 读取图像
img = cv2.imread("2.jpg", cv2.IMREAD_GRAYSCALE)
# 计算 LBP 图像
radius = 3
n_points = 8 * radius
lbp = feature.local_binary_pattern(img, n_points, radius, method='uniform')
# 统计 LBP 直方图
hist, _ = np.histogram(lbp, bins=256, range=(0, 256))
# 直方图熵(越高表示纹理越复杂)
entropy = -np.sum(hist * np.log(hist + 1e-9))
print(f"LBP Entropy: {entropy:.3f}")

101
guanghuaban/T.py Normal file
View File

@ -0,0 +1,101 @@
import cv2
import numpy as np
# 读取图像(以灰度模式加载)
# 作用:将 '1.jpg' 图像读入内存,转换为单通道灰度图,便于后续图像处理
# 注意如果路径错误或文件不存在image 将为 None导致后续报错
image = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
# 检查图像是否成功加载
if image is None:
raise FileNotFoundError("无法读取图像,请检查文件路径是否正确:'1.jpg'")
# 均值滤波滤波核大小为7x7
# 作用:对图像进行平滑处理,去除高频噪声(如随机噪点)
# 原理用每个像素周围7x7邻域的平均值替换该像素值使图像更“柔和”
blurred = cv2.blur(image, (7, 7))
# 使用局部自适应阈值进行图像分割
# 作用:将图像二值化,突出比局部背景更暗的区域(如划痕、凹坑等缺陷)
# 参数说明:
# - cv2.ADAPTIVE_THRESH_MEAN_C阈值基于局部邻域的平均值
# - 11邻域大小奇数决定局部范围
# - 2从均值中减去的常数用于微调灵敏度
# - cv2.THRESH_BINARY_INV反转结果缺陷区域为白色255背景为黑色0
thresholded = cv2.adaptiveThreshold(
blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
# 查找图像中的轮廓
# 作用:检测二值图像中所有连通的白色区域(即潜在缺陷)
# 返回值:
# - contours: 所有轮廓的坐标点列表
# - _ : 轮廓的层级关系(此处不需要)
# 方法选择:
# - cv2.RETR_LIST提取所有轮廓不建立层级
# - cv2.CHAIN_APPROX_SIMPLE压缩水平/垂直/对角线方向的轮廓点,节省内存
contours, _ = cv2.findContours(thresholded, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 创建一个彩色图像用于结果显示
# 作用将原始灰度图转换为BGR三通道图像以便用不同颜色绘制检测结果
output_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
# 对每个检测到的轮廓进行面积筛选
# 作用:过滤掉太小(可能是噪声)或太大(可能是背景干扰)的区域
# 设置面积阈值范围250 ~ 1000 像素
min_area, max_area = 250, 1000
for contour in contours:
area = cv2.contourArea(contour) # 计算轮廓包围的面积
if min_area < area < max_area:
# 绘制符合条件的轮廓
# 颜色:绿色 (0, 255, 0)线宽2
cv2.drawContours(output_image, [contour], -1, (0, 255, 0), 2)
# 形态学膨胀操作
# 作用:扩大二值图像中的白色区域,连接邻近的断裂缺陷(如断开的划痕)
# 结构元素椭圆形模拟圆形大小为7x7
# iterations=1执行一次膨胀
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
dilated = cv2.dilate(thresholded, kernel, iterations=1)
# 骨架化处理(细化为单像素宽的中心线)
# 作用:将膨胀后的缺陷区域“细线化”,便于分析划痕的路径和长度
# 注意OpenCV 无内置骨架化函数这里使用经典的Zhang-Suen细化算法简化版
def thinning(img):
skel = np.zeros(img.shape, np.uint8) # 存储骨架结果
size = np.size(img)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) # 3x3十字结构元
done = False
while not done:
# 重复执行:腐蚀 → 膨胀 → 差分 → 累加到骨架
eroded = cv2.erode(img, element) # 腐蚀:缩小区域
temp = cv2.dilate(eroded, element) # 膨胀回来
temp = cv2.subtract(img, temp) # 得到最外层轮廓(即“剥皮”一层)
skel = cv2.bitwise_or(skel, temp) # 累加到骨架图像
img = eroded.copy() # 更新图像为腐蚀后的结果
# 当图像完全变黑(无非零像素)时停止
zeros = size - cv2.countNonZero(img)
if zeros == size:
done = True
return skel
# 执行骨架化
skeleton = thinning(dilated)
# 显示所有中间结果和最终检测图
# 作用:可视化每一步的处理效果,便于调试和分析
cv2.imshow("Original Image", image) # 原始灰度图
cv2.imshow("Thresholded Image", thresholded) # 自适应阈值分割结果
cv2.imshow("Dilated Image", dilated) # 膨胀后结果
cv2.imshow("Skeletonized Image", skeleton) # 骨架化结果(细线)
cv2.imshow("Detected Regions", output_image) # 最终检测结果(绿色轮廓)
# 等待按键后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 KiB

28
guanghuaban/guanghua.py Normal file
View File

@ -0,0 +1,28 @@
import cv2
import numpy as np
# 加载图像
img = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
'''
height, width = img.shape
start_row = height // 7 * 4 # 从 2/3 处开始,到底部
img = img[start_row:, :] # 所有列,只取底部 1/3 行
print(f"✅ 裁剪出底部 1/3 区域,尺寸: {img.shape}")
'''
# ✅ 3. 提取最下方三分之一的区域
# 高斯模糊去除噪声
blurred = cv2.GaussianBlur(img, (5, 5), 0)
# 边缘检测
edges = cv2.Canny(blurred, 50, 150)
# 显示结果
cv2.imshow("Edges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 接下来可以根据需要进一步处理边缘信息,比如计算裂缝长度、宽度等参数。