bushu
This commit is contained in:
BIN
guanghuaban/1.jpg
Normal file
BIN
guanghuaban/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 KiB |
BIN
guanghuaban/2.jpg
Normal file
BIN
guanghuaban/2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 492 KiB |
BIN
guanghuaban/2.png
Normal file
BIN
guanghuaban/2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 278 KiB |
76
guanghuaban/FFT.py
Normal file
76
guanghuaban/FFT.py
Normal 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
56
guanghuaban/GLCM.py
Normal 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
17
guanghuaban/LBP.py
Normal 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
101
guanghuaban/T.py
Normal 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()
|
||||
BIN
guanghuaban/fft_analysis_result.png
Normal file
BIN
guanghuaban/fft_analysis_result.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 630 KiB |
28
guanghuaban/guanghua.py
Normal file
28
guanghuaban/guanghua.py
Normal 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()
|
||||
|
||||
# 接下来可以根据需要进一步处理边缘信息,比如计算裂缝长度、宽度等参数。
|
||||
Reference in New Issue
Block a user