如何用OpenCV检测仪表图像中的全部水平线并获取其坐标
解决OpenCV仪表图像水平线检测不全的问题

问题分析
你的代码中水平结构元素尺寸固定为(40,1),只能匹配长度≥40的水平线,仪表里的短刻度线会被漏掉。另外cv.findContours的返回值处理不严谨,不同OpenCV版本返回值数量不同,直接遍历会导致报错。
改进后的代码
import cv2 as cv import numpy as np # 读取图像(替换为你的图像加载逻辑) # image = cv.imread("meter_image.png") result = image.copy() print("[INFO] Converting to Gray...\n") gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) print("[INFO] Converted to Gray.\n") print("[INFO] Applying Thresholding...\n") thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1] print("[INFO] Threshold Applied.\n") # 生成多尺寸水平结构元素,覆盖不同长度的水平线 horizontal_kernels = [ cv.getStructuringElement(cv.MORPH_RECT, (15, 1)), cv.getStructuringElement(cv.MORPH_RECT, (40, 1)), cv.getStructuringElement(cv.MORPH_RECT, (60, 1)) ] # 合并不同核的检测结果 detect_horizontal = np.zeros_like(thresh) for kernel in horizontal_kernels: temp = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=1) detect_horizontal = cv.bitwise_or(detect_horizontal, temp) # 适配不同OpenCV版本的轮廓返回值 cnts = cv.findContours(detect_horizontal, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] print("所有水平线坐标信息:") for c in cnts: # 通过边界框获取水平线的起止坐标与中心坐标 x, y, w, h = cv.boundingRect(c) start_point = (x, y) end_point = (x + w, y) center_point = (x + w // 2, y) print(f"起止点:{start_point} -> {end_point},中心坐标:{center_point}") cv.drawContours(result, [c], -1, (36,255,12), 2) cv.imshow('result', result) cv.waitKey(0) cv.destroyAllWindows()
关键改进点
- 多尺寸结构元素:使用15、40、60三种宽度的水平核,覆盖仪表中长短不一的水平线,通过位运算合并检测结果,避免遗漏短刻度线。
- 适配轮廓返回值:处理不同OpenCV版本
findContours的返回格式,避免报错。 - 完整坐标输出:通过
boundingRect提取每条水平线的起止坐标和中心坐标,满足你对x、y信息的需求。
内容的提问来源于stack exchange,提问作者Subramanya G
相关产品推荐
相关产品推荐

