如何让Scikit-Image的Hough变换检测到立方体的另一条边缘?
问题:Hough变换检测立方体边缘遗漏的解决方法
我尝试使用Scikit-Image库中的Hough变换检测下图中的立方体边缘:
更新
以下是我正在使用的代码:
smoothed_image = filters.frangi(gray_image) # Perform edge detection using the Canny edge detector low_threshold = 0.1 high_threshold = 3 low_threshold = low * smoothed_image.max() high_threshold = high * low_threshold edges = canny(smoothed_image, sigma, low_threshold=low_threshold, high_threshold=high_threshold) # Hough transform to detect the filament profile hspace, theta, dist = hough_line(edges) # Find the vertical lines vertical_peaks = hough_line_peaks(hspace, theta, dist, num_peaks=2) vertical_lines = [] for _, angle, dist in zip(*vertical_peaks): x = dist * np.cos(angle) y = dist * np.sin(angle) vertical_lines.append((x, y)) # Visualize the results fig, axes = plt.subplots(1, 3, figsize=(15, 5)) axes[0].imshow(smoothed_image) axes[0].set_title('Smoothed Image') #axes[0].axis('off') axes[1].imshow(edges, cmap='gray') axes[1].set_title('Canny Edge Detection') axes[1].axis('off') axes[2].imshow(edges, cmap='gray') for x, y in vertical_lines: axes[2].axvline(x=x, color='red') axes[2].set_xlim((0, image.shape[1])) axes[2].set_ylim((image.shape[0], 0)) axes[2].set_title('Detected Lines') axes[2].axis('off') plt.tight_layout() plt.show()
运行后得到如下输出结果:
请问如何调整才能让Hough变换检测到遗漏的那条边缘?
解决建议
1. 优化预处理步骤
Frangi滤波主打管状结构检测(如血管),对立方体这类规则边缘适配性差,改用高斯滤波能更高效地去噪并保留边缘:
# 替换Frangi滤波为高斯滤波 smoothed_image = filters.gaussian(gray_image, sigma=1.0)
2. 修正并调整Canny边缘检测参数
原代码存在变量名错误(low未定义),且高低阈值比例过高,导致弱边缘被过滤,调整后:
# 修正阈值计算并调整比例 low_threshold = 0.05 * smoothed_image.max() high_threshold = 2 * low_threshold # 降低高阈值与低阈值的比例 edges = feature.canny(smoothed_image, sigma=1.0, low_threshold=low_threshold, high_threshold=high_threshold)
- 降低
low_threshold比例,确保弱边缘能被保留 sigma建议在0.8-1.2之间测试,平衡噪声过滤与边缘清晰度
3. 改进Hough变换的峰值检测逻辑
- 增加峰值数量:将
num_peaks从2改为3,匹配立方体3条垂直边缘的需求 - 过滤垂直角度:只保留接近90°(
np.pi/2)的角度,排除无关方向干扰 - 降低峰值阈值:让较弱的峰值也能被检测到
修改后的Hough检测代码:
# Hough变换 hspace, theta, dist = transform.hough_line(edges) # 过滤垂直方向的角度(允许±0.1弧度的偏差) vertical_angle_mask = np.abs(theta - np.pi/2) < 0.1 filtered_hspace = hspace.copy() filtered_hspace[~vertical_angle_mask] = 0 # 非垂直方向的投票置0 # 检测3个峰值,降低阈值要求 vertical_peaks = transform.hough_line_peaks(filtered_hspace, theta, dist, num_peaks=3, threshold=0.3 * hspace.max())
4. 完整修改后的代码
import numpy as np import matplotlib.pyplot as plt from skimage import filters, feature, transform, io, color # 读取图像并转为灰度图 image = io.imread('cube_image.jpg') gray_image = color.rgb2gray(image) if len(image.shape) == 3 else image # 预处理:高斯滤波 smoothed_image = filters.gaussian(gray_image, sigma=1.0) # Canny边缘检测 low_threshold = 0.05 * smoothed_image.max() high_threshold = 2 * low_threshold edges = feature.canny(smoothed_image, sigma=1.0, low_threshold=low_threshold, high_threshold=high_threshold) # Hough变换与垂直边缘过滤 hspace, theta, dist = transform.hough_line(edges) vertical_angle_mask = np.abs(theta - np.pi/2) < 0.1 filtered_hspace = hspace.copy() filtered_hspace[~vertical_angle_mask] = 0 # 检测3个峰值 vertical_peaks = transform.hough_line_peaks(filtered_hspace, theta, dist, num_peaks=3, threshold=0.3 * hspace.max()) # 提取直线参数 vertical_lines = [] for _, angle, d in zip(*vertical_peaks): x0 = d * np.cos(angle) y0 = d * np.sin(angle) vertical_lines.append((x0, y0)) # 可视化结果 fig, axes = plt.subplots(1, 3, figsize=(15, 5)) axes[0].imshow(smoothed_image, cmap='gray') axes[0].set_title('平滑后图像') axes[1].imshow(edges, cmap='gray') axes[1].set_title('Canny边缘检测') axes[1].axis('off') axes[2].imshow(gray_image, cmap='gray') for x, y in vertical_lines: axes[2].axvline(x=x, color='red', linewidth=2) axes[2].set_xlim((0, image.shape[1])) axes[2].set_ylim((image.shape[0], 0)) axes[2].set_title('检测到的垂直边缘') axes[2].axis('off') plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

