如何用Python的OpenCV基于细水平线分割图像为指定区块?
问题描述
我需要根据图像中的细水平线(红色箭头所指)将图像分割为4个区块:
- 包含“Combiné”文本的页眉
- 两个分别对应单个投注的区块
- 包含投注赔率和预期收益的页脚
我尝试调整了代码中的各项参数,但仍无法检测到这些线条,以下是我的代码:
import cv2 import numpy as np # 加载图像 image = cv2.imread('polygone_resultant.png') # 转换为灰度图 gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用阈值检测浅灰色线条 _, binary_image = cv2.threshold(gray_image, 220, 255, cv2.THRESH_BINARY) # 调整阈值 # 检测轮廓 contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 初始化文本区块列表 text_blocks = [] # 遍历轮廓提取细水平线 for contour in contours: x, y, w, h = cv2.boundingRect(contour) # 判断是否为细水平线 if h < 3 and w > 50: # 根据需求调整高度(h)和宽度(w)的阈值 text_block = image[y:y+h, x:x+w] text_blocks.append(text_block) # 显示每个区块 for i, block in enumerate(text_blocks): cv2.imshow(f'Text Block {i+1}', block) cv2.waitKey(0) cv2.destroyAllWindows()

解决方案
用轮廓检测细水平线容易失效,这类线条的轮廓特征不明显,建议改用霍夫直线检测(Hough Line Transform),它更适合检测规则直线。以下是调整后的代码:
import cv2 import numpy as np # 加载图像 image = cv2.imread('polygone_resultant.png') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 边缘检测突出线条 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 霍夫直线检测:定向捕捉水平线 lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=20, minLineLength=100, maxLineGap=5) # 收集水平线的y坐标(取线段中点y值,避免重复) y_coords = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] # 过滤非水平线(y坐标差极小) if abs(y1 - y2) < 3: y_mid = (y1 + y2) // 2 y_coords.append(y_mid) # 去重并排序y坐标 y_coords = sorted(list(set(y_coords))) # 构建分割边界:顶部→第一条线→第二条线→第三条线→底部,确保4个区块 if len(y_coords) >= 3: split_ys = [0] + y_coords[:3] + [image.shape[0]] else: # 兜底:手动设置分割坐标(根据图像实际尺寸调整) split_ys = [0, 80, 200, 320, image.shape[0]] # 分割并显示区块 blocks = [] for i in range(len(split_ys)-1): y_start = split_ys[i] y_end = split_ys[i+1] block = image[y_start:y_end, :] blocks.append(block) cv2.imshow(f'区块 {i+1}', block) cv2.waitKey(0) cv2.destroyAllWindows()
关键调整说明:
- Canny边缘检测:先提取图像边缘,让细水平线更清晰,提升检测准确率。
- 霍夫直线检测参数:
minLineLength=100:过滤短线条,只保留贯穿画面的长水平线maxLineGap=5:合并同一条线上的断开线段threshold=20:控制检测灵敏度,可根据图像微调
- 坐标处理:去重排序y坐标,补充顶部和底部边界,确保分割出完整的4个区块。
- 兜底机制:若检测失败,可手动设置
split_ys的数值,适配你的图像实际布局。
额外优化:
如果图像有噪声,可在灰度转换后添加高斯模糊:
blur = cv2.GaussianBlur(gray, (3,3), 0) edges = cv2.Canny(blur, 50, 150, apertureSize=3)
内容的提问来源于stack exchange,提问作者Thomas Letellier
相关产品推荐
相关产品推荐

