OpenCV:如何创建任意角度的腐蚀核以提取特定方向直线
通用角度腐蚀核实现方案
问题背景
我有一张包含水平、垂直、对角线、交叉对角线等多种角度直线的图像,现有代码可通过预设核矩阵筛选固定方向的直线,但无法处理任意角度的直线。需要修改代码中的TO DO区域,创建一个可自定义角度的通用腐蚀核,简化不同方向直线的处理流程。
输入图像:
输出示例(以90度垂直直线为例):
修改后的完整代码
import cv2 import numpy as np %matplotlib inline from matplotlib import pyplot as plt # 定义Jupyter环境下的图像显示函数 def showimage(title,myimage): # 彩色图像转换OpenCV的BGR格式为RGB if (myimage.ndim>2): myimage = myimage[:,:,::-1] fig, ax = plt.subplots(figsize=(6,6)) ax.imshow(myimage, cmap = 'gray', interpolation = 'bicubic') plt.xticks([]), plt.yticks([]) # 隐藏坐标轴刻度 plt.title(title) plt.show() # 加载图像 imfile = 'multilines.jpg' image = cv2.imread(imfile) showimage('Original',image) # 转为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Canny边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) ### 原固定方向核(保留作为参考,可注释) kernel_h = np.array([[0, 0, 0], [1, 1, 1], [0, 0, 0]], dtype=np.uint8) kernel_v = np.array([[0, 1, 0], [0, 1, 0], [0, 1, 0]], dtype=np.uint8) kernel_d = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.uint8) kernel_crossd = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]], dtype=np.uint8) # 注释原固定核选择,改用通用角度核 # kernel = kernel_h; tag = 'Horizontal' # kernel = kernel_v; tag = 'Vertical' # kernel = kernel_d; tag = 'Diagonal' # kernel = kernel_crossd; tag = 'Cross-diagonal' # TO DO begins ---------------------- # 生成通用角度依赖的腐蚀核 theta_deg = 90 # 可修改为任意角度(单位:度),0度为水平向右,逆时针旋转为正 theta = np.deg2rad(theta_deg) # 定义3x3大小的核 kernel_size = 3 kernel_angle = np.zeros((kernel_size, kernel_size), dtype=np.uint8) center = (kernel_size // 2, kernel_size // 2) # 计算角度对应的方向向量,取整得到偏移量 dx = np.cos(theta) dy = np.sin(theta) offset_x = int(round(dx)) offset_y = int(round(dy)) # 填充核的三个点:中心 + 对称的两个端点 kernel_angle[center[0], center[1]] = 1 # 中心像素 if offset_x != 0 or offset_y != 0: # 第一个端点 x1 = center[0] + offset_y y1 = center[1] + offset_x # 第二个端点(与第一个端点关于中心对称) x2 = center[0] - offset_y y2 = center[1] - offset_x # 确保坐标在核范围内(避免越界) if 0 <= x1 < kernel_size and 0 <= y1 < kernel_size: kernel_angle[x1, y1] = 1 if 0 <= x2 < kernel_size and 0 <= y2 < kernel_size: kernel_angle[x2, y2] = 1 kernel = kernel_angle ; tag = f'Generic angle-based ({theta_deg} degrees)' # TO DO ends ------------------------ print(f'{tag} erosion applied.') # 腐蚀操作提取目标直线 erosion_lines = cv2.erode(edges, kernel, iterations=1) showimage('After erosion',erosion_lines) # 反转颜色得到白底黑线条的结果 result = cv2.bitwise_not(erosion_lines) # 显示最终结果 showimage('Final',result)
实现说明
- 角度定义:以水平向右为0度,逆时针旋转为正方向,直接修改
theta_deg即可设置任意角度(如30°、60°、135°等) - 核生成逻辑:以3x3核的中心为原点,根据角度计算方向向量,取整后确定直线上的另外两个对称端点,将这三个位置设为1,其余为0,形成对应角度的直线型腐蚀核
- 兼容性:生成的核与原固定方向核完全匹配(如0°对应水平核、90°对应垂直核、45°对应对角线核),同时支持任意角度的直线筛选
内容的提问来源于stack exchange,提问作者hbaromega
相关产品推荐
相关产品推荐

