如何通过轮廓准确获取米粒的长度与宽度?已用OpenCV相关函数未果
解决米粒长度/宽度测量问题的实用方案
你当前用cv2.boundingRect()得到的是轴对齐的外接矩形,对倾斜的米粒来说会包含大量空白区域,自然测不准。换成最小外接矩形或者计算轮廓最远点距离,就能拿到更贴合米粒实际尺寸的数据,具体步骤如下:
核心改进思路
替换轴对齐矩形为旋转最小外接矩形
cv2.minAreaRect()会生成贴合物体轮廓的旋转矩形,返回值((x_center,y_center), (width,height), angle)里的width和height就是米粒的实际宽高(取较大值为长度,较小值为宽度)。先优化轮廓质量
Canny边缘检测容易出现断裂或噪声轮廓,建议先做这些预处理:
- 把图像转灰度后用OTSU阈值分割生成二值图,比Canny更易得到闭合轮廓
- 用形态学闭运算(
cv2.morphologyEx())填补轮廓小缺口,去除小噪声点
代码示例
import cv2 import numpy as np # 读取图像(假设已读入img) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # OTSU二值化 _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 形态学闭运算填补缺口 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # 查找轮廓 contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历有效轮廓(过滤小噪声) for cnt in contours: area = cv2.contourArea(cnt) if area < 100: # 根据实际米粒大小调整阈值 continue # 计算最小外接矩形 rect = cv2.minAreaRect(cnt) (center, (w, h), angle) = rect # 确定长度和宽度(取大的为长度) length = max(w, h) width = min(w, h) print(f"米粒长度:{length:.2f}px,宽度:{width:.2f}px") # 可选:画出旋转矩形(可视化验证) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(img, [box], 0, (0,255,0), 2) cv2.imshow("Result", img) cv2.waitKey(0)
额外补充
如果需要亚像素级精度,可以先对轮廓做cv2.approxPolyDP()近似,或者用cv2.cornerSubPix()优化轮廓点坐标后再计算尺寸。
内容的提问来源于stack exchange,提问作者lisamarigondondaw
相关产品推荐
相关产品推荐

