相邻液体层轮廓检测:现有OpenCV代码效果不佳求优化
离心试管液体层轮廓识别解决方案
问题根源
原代码直接套用通用的灰度+Canny+轮廓检测流程,没有针对试管的垂直结构、液体层的灰度差异特性做针对性处理,导致检测出大量无关轮廓,无法精准定位目标层的边界。
改进方案
针对离心后试管(上层血浆、下层红细胞,分界清晰)的特性,按以下步骤处理:
- 裁剪试管感兴趣区域(ROI),排除背景干扰
- 利用Otsu自动阈值分割两层液体
- 形态学操作去除噪声、平滑轮廓
- 通过面积筛选出液体层的有效轮廓
- 精准绘制轮廓与两层交界线
改进代码
import cv2 import numpy as np # 读取图像 image = cv2.imread('input/blood.png') if image is None: print("无法读取图像,请检查文件路径") exit() # 1. 定位并裁剪试管区域 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY_INV) # 提取试管的上下左右边界 non_zero_y = np.where(thresh.sum(axis=1) > 0)[0] non_zero_x = np.where(thresh.sum(axis=0) > 0)[0] if len(non_zero_y) == 0 or len(non_zero_x) == 0: print("未检测到试管区域") exit() top, bottom = non_zero_y[0], non_zero_y[-1] left, right = non_zero_x[0], non_zero_x[-1] tube_roi = gray[top:bottom, left:right] roi_color = image[top:bottom, left:right].copy() # 2. Otsu自动阈值分割两层液体 _, thresh_tube = cv2.threshold(tube_roi, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) thresh_tube = cv2.bitwise_not(thresh_tube) # 根据图像灰度分布调整反转 # 3. 形态学操作去除噪声 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) cleaned = cv2.morphologyEx(thresh_tube, cv2.MORPH_CLOSE, kernel) cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_OPEN, kernel) # 4. 筛选有效轮廓(过滤小噪声) contours, _ = cv2.findContours(cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) valid_contours = [] roi_area = tube_roi.shape[0] * tube_roi.shape[1] for cnt in contours: if cv2.contourArea(cnt) > roi_area * 0.1: # 保留面积大于ROI 10%的轮廓 valid_contours.append(cnt) # 5. 转换坐标并绘制轮廓 for cnt in valid_contours: cnt[:, :, 0] += left cnt[:, :, 1] += top cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2) # 额外:绘制两层液体的交界线 row_mean = cleaned.mean(axis=1) border_y = np.where(np.diff(row_mean) != 0)[0] if len(border_y) > 0: border_y = border_y[0] + top cv2.line(image, (left, border_y), (right, border_y), (0, 0, 255), 2) # 展示结果 cv2.imshow('液体层轮廓', image) cv2.waitKey(0) cv2.destroyAllWindows()
核心优化点
- ROI裁剪:聚焦试管区域,直接排除背景干扰,减少无效轮廓的产生
- Otsu阈值:自动适配图像灰度分布,精准区分两层液体的灰度差异
- 轮廓筛选:通过面积阈值过滤噪声轮廓,只保留液体层的大轮廓
- 交界线定位:利用行均值突变精准找到两层分界,补充绘制交界线
内容的提问来源于stack exchange,提问作者by42
相关产品推荐
相关产品推荐

