如何通过图像处理仅保留图像中的垂直线?附已尝试滤波步骤
保留图像垂直线的优化方案
当然有更针对性的方法来实现你的需求!先聊聊你当前流程里可以优化的点:Scharr卷积结合Sobel X的组合有点冗余,而且可能引入不必要的噪声干扰,另外阈值参数也可以更灵活调整。下面给你几个更高效的方案,帮你精准保留垂直线:
方案1:定向形态学滤波(最直接)
形态学滤波可以通过自定义垂直结构元素,定向保留垂直线、过滤水平线。核心思路是用只对垂直结构生效的核,去除水平方向的干扰:
def process_image(self): image = cv2.cvtColor(self.img_diagonal, cv2.COLOR_BGR2GRAY) # 可选:先做高斯模糊去噪,减少后续检测的噪声干扰 blurred = cv2.GaussianBlur(image, (3, 3), 0) # 创建垂直结构元素:(1, N) 中N的值根据垂直线的粗细调整,线越粗N越大 vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5)) # 开运算:先腐蚀去除水平方向的小噪声,再膨胀修复垂直线的断裂 vertical_enhanced = cv2.morphologyEx(blurred, cv2.MORPH_OPEN, vertical_kernel) # 用Sobel X检测垂直边缘(强化线的对比度) sobelx = cv2.Sobel(vertical_enhanced, cv2.CV_64F, 1, 0, ksize=3) sobelx_abs = np.absolute(sobelx) # 归一化到0-255范围 sobelx_norm = cv2.normalize(sobelx_abs, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 二值化阈值,可根据实际图像调整阈值(这里用50,你可以改成更适合的数值) ret, thresh = cv2.threshold(sobelx_norm, 50, 255, cv2.THRESH_BINARY) cv2.imwrite("Temp/ritmo--%d.png" % self.count, thresh) return thresh
方案2:自定义垂直卷积核
直接用只响应垂直线的卷积核做滤波,强化垂直方向的像素变化,抑制水平方向:
def process_image(self): image = cv2.cvtColor(self.img_diagonal, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(image, (3, 3), 0) # 自定义垂直检测核:增强垂直方向的灰度差异 vertical_kernel = np.array([ [-1, 2, -1], [-1, 2, -1], [-1, 2, -1] ], dtype=np.float32) # 卷积操作 vertical_lines = cv2.filter2D(blurred, cv2.CV_64F, vertical_kernel) vertical_abs = np.absolute(vertical_lines) vertical_norm = cv2.normalize(vertical_abs, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 二值化+形态学微调 ret, thresh = cv2.threshold(vertical_norm, 40, 255, cv2.THRESH_BINARY) vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 3)) final = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, vertical_kernel) cv2.imwrite("Temp/ritmo--%d.png" % self.count, final) return final
方案3:优化你现有的Sobel流程
如果你想基于现有代码调整,可以去掉冗余的Scharr卷积,直接用Sobel X结合垂直形态学操作:
def process_image(self): image = cv2.cvtColor(self.img_diagonal, cv2.COLOR_BGR2GRAY) # 闭运算填充缝隙(保留你原有的步骤) kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) closing = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel) # 直接用Sobel X检测垂直边缘,无需Scharr卷积 sobelx = cv2.Sobel(closing, cv2.CV_64F, 1, 0, ksize=3) sobelx_abs = np.absolute(sobelx) sobelx_norm = cv2.normalize(sobelx_abs, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 用垂直核过滤水平线 vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5)) vertical_filtered = cv2.morphologyEx(sobelx_norm, cv2.MORPH_OPEN, vertical_kernel) ret, thresh2 = cv2.threshold(vertical_filtered, 127, 255, cv2.THRESH_BINARY) cv2.imwrite("Temp/ritmo--%d.png" % self.count, thresh2) return thresh2
关键提示
- 结构元素的大小:如果你的垂直线比较粗,把
(1,5)改成(1,7)或(1,9);如果线很细,用(1,3)。 - 阈值参数:根据你的原图亮度调整,比如把127改成50、80这类数值,找到最适合的保留效果。
- 去噪步骤:高斯模糊很重要,能减少噪声带来的伪边缘,让最终的垂直线更干净。
内容的提问来源于stack exchange,提问作者Paulo Oliveira
相关产品推荐
相关产品推荐

