基于Python OpenCV 4.8检测试管液位的技术求助
试管液位高度检测方案
这两张图虽有模糊,但完全可以通过针对性预处理和检测逻辑实现液位检测,无需直接放弃。以下是基于Python OpenCV 4.8的可行方案:
一、预处理:降噪与对比度增强
原始图的模糊和噪点会直接干扰边缘/轮廓检测,先做预处理优化:
- 转灰度图:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - 高斯模糊降噪:
blur = cv2.GaussianBlur(gray, (5,5), 0)用5×5核过滤高频噪点,保留液位的明暗分界 - 自适应阈值分割:
thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)自适应阈值能更好应对局部光照差异,突出液位线的对比度
二、两种液位线检测方法
方法1:霍夫直线检测(针对性找水平线)
液位是水平直线,用霍夫变换筛选水平方向的直线:
import cv2 import numpy as np # 读取图片(替换为你的图片路径) img = cv2.imread("test_tube.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # Canny边缘检测 edges = cv2.Canny(thresh, 50, 150) # 霍夫直线检测 lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=30, minLineLength=20, maxLineGap=5) # 筛选接近水平的直线(角度±5度以内) horizontal_lines = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi if abs(angle) < 5: horizontal_lines.append(line[0]) # 确定液位高度(取水平直线y坐标的中位数) if horizontal_lines: y_coords = [(y1 + y2) // 2 for x1, y1, x2, y2 in horizontal_lines] liquid_level_y = np.median(y_coords) print(f"液位高度对应的y坐标:{liquid_level_y}") # 可选:在图上画出液位线 cv2.line(img, (0, int(liquid_level_y)), (img.shape[1], int(liquid_level_y)), (0,0,255), 2) cv2.imshow("Result", img) cv2.waitKey(0)
方法2:轮廓筛选(找水平长条轮廓)
通过轮廓检测筛选宽高比大的水平轮廓,对应液位线:
import cv2 import numpy as np img = cv2.imread("test_tube.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0) thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 查找轮廓 contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) liquid_contours = [] # 筛选宽高比>5、宽度>20的水平轮廓 for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) if w / h > 5 and w > 20: liquid_contours.append((x, y, w, h)) # 确定液位高度(取符合条件轮廓的y坐标中间值) if liquid_contours: # 按y坐标排序,优先取试管中部的轮廓 liquid_contours.sort(key=lambda item: item[1]) target_contour = liquid_contours[0] liquid_level_y = target_contour[1] + target_contour[3] // 2 print(f"液位高度对应的y坐标:{liquid_level_y}") # 可选:画出轮廓和液位线 cv2.rectangle(img, (target_contour[0], target_contour[1]), (target_contour[0]+target_contour[2], target_contour[1]+target_contour[3]), (0,255,0), 2) cv2.line(img, (0, int(liquid_level_y)), (img.shape[1], int(liquid_level_y)), (0,0,255), 2) cv2.imshow("Result", img) cv2.waitKey(0)
三、参数调整建议
如果检测效果不佳,可针对性调整以下参数:
- 高斯模糊核大小:可尝试(3,3)或(7,7),适配不同模糊程度
- 自适应阈值的
blockSize:改为15、19等奇数,调整局部区域的计算范围 - 霍夫直线检测的
threshold、minLineLength:降低阈值或缩短最小线长,适配更短的液位线 - 轮廓筛选的宽高比阈值:根据实际图片调整,比如改为3或7
内容的提问来源于stack exchange,提问作者Bharata
相关产品推荐
相关产品推荐

