You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Skimage Hough Line检测液滴接触面水平线的技术求助

问题描述

这是首个Python项目,需求是检测黑白液滴图像中液滴与接触面的水平交界线。已用cv2.Canny成功检测液滴轮廓,但将边缘图输入Skimage的Hough变换(hough_line)后,无法确定是否检测到线条,也无法将线条绘制到原图上(单独绘制线条功能正常)。环境为Anaconda下的Spyder,Python版本3.10。

当前代码

import numpy as np
import cv2
from skimage.transform import hough_line, probabilistic_hough_line

def fit_baseline(image):
    # Convert the image to grayscale
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv2.imshow('Graubild', gray_image)

    # Apply edge detection
    edges = cv2.Canny(gray_image, 80, 120, apertureSize=3)
    cv2.imshow('Ecken',edges)

    # Perform the Hough Transform
    h, theta, d = hough_line(edges)
    print('h:', h)
    print('theta: ', theta)
    print('d: ', d)

    # Find the most prominent line (baseline)
    angle, dist = np.unravel_index(np.argmax(h), h.shape)
    angle = np.rad2deg(theta[angle])
    dist = d[dist]

    # Convert from polar to slope-intercept form
    if angle != 0:
        slope = -1 / np.tan(np.deg2rad(angle))
        intercept = dist / np.sin(np.deg2rad(angle))
    else:
        slope = float('inf')
        intercept = dist

    return slope, intercept

# Load the image
image = cv2.imread('Bilder/drop_zoomed.png')


# Fit the baseline
slope, intercept = fit_baseline(image)

# Draw the baseline on the image
height, width, _ = image.shape
baseline_start_x = 0
baseline_start_y = int(intercept)
baseline_end_x = width - 1
baseline_end_y =  int(slope * baseline_end_x + intercept)
baseline_color = (0, 255, 0)  # Green color (BGR format)
baseline_thickness = 2
image_with_baseline = cv2.line(image, (baseline_start_x, baseline_start_y), (baseline_end_x, baseline_end_y),
                               baseline_color, baseline_thickness)

# Display the image with the baseline
cv2.imshow('Image with Baseline', image_with_baseline)
cv2.waitKey(0)
cv2.destroyAllWindows()

待检测图像

待检测液滴图像

预期效果

预期检测效果


调整建议与可行方案

一、修正Hough变换的坐标转换逻辑

skimage的hough_line中,theta是线条与x轴正方向的夹角,d是原点到线条的垂直距离,你当前的坐标转换公式有误,导致直线位置偏移。直接用极坐标参数生成端点即可,无需转换为斜截式:

# 替换原Hough变换后的坐标转换代码
theta_rad = theta[angle]
x0 = np.cos(theta_rad) * d[dist]
y0 = np.sin(theta_rad) * d[dist]

# 生成直线两端点(取垂直于theta的方向,避免斜率无穷大问题)
dx = np.cos(theta_rad + np.pi/2) * 1000
dy = np.sin(theta_rad + np.pi/2) * 1000
start_point = (int(x0 - dx), int(y0 - dy))
end_point = (int(x0 + dx), int(y0 + dy))

# 直接绘制直线
cv2.line(image, start_point, end_point, (0,255,0), 2)

二、改用概率霍夫变换简化检测

probabilistic_hough_line直接返回直线端点,且更擅长检测长直线,适合你的场景:

# 替换原Hough变换部分
edges = cv2.Canny(gray_image, 30, 100, apertureSize=3)
lines = probabilistic_hough_line(edges, threshold=10, line_length=50, line_gap=5)

# 筛选接近水平的直线(角度误差±5度)
horizontal_lines = []
for line in lines:
    (x1, y1), (x2, y2) = line
    angle = np.arctan2(y2 - y1, x2 - x1)
    if abs(np.rad2deg(angle)) < 5 or abs(np.rad2deg(angle) - 180) < 5:
        horizontal_lines.append(line)

# 取最下方的水平直线(液滴与接触面的交界线)
if horizontal_lines:
    # 按平均y坐标排序,取最大的(最靠下)
    horizontal_lines.sort(key=lambda l: (l[0][1] + l[1][1])/2, reverse=True)
    best_line = horizontal_lines[0]
    cv2.line(image, best_line[0], best_line[1], (0,255,0), 2)

三、优化边缘检测参数

当前Canny阈值可能过滤了交界线边缘,可降低下限阈值并增加高斯模糊降噪:

blur = cv2.GaussianBlur(gray_image, (3,3), 0)
edges = cv2.Canny(blur, 30, 100, apertureSize=3)

四、替代方案:行像素统计法

针对水平交界线,直接统计每行白色像素占比,找到突变行:

def find_baseline_by_row(gray_image):
    width = gray_image.shape[1]
    # 统计每行白色像素数量(背景为白色,液滴为黑色)
    row_counts = np.sum(gray_image == 255, axis=1)
    # 从下往上找白色像素骤增的行
    for y in range(gray_image.shape[0]-1, 0, -1):
        if row_counts[y] - row_counts[y-1] > width * 0.5:
            return y
    return gray_image.shape[0] // 2

# 使用示例
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
baseline_y = find_baseline_by_row(gray_image)
cv2.line(image, (0, baseline_y), (gray_image.shape[1]-1, baseline_y), (0,255,0), 2)

内容的提问来源于stack exchange,提问作者Leah Fernández

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 16:15:15