如何沿高度方向准确测量高温发光物体的垂直宽度
沿高度方向测量高温白炽发光体宽度的优化方案
核心思路
基于你提供的先验信息(纯黑背景、固定三物体结构、亮度梯度规律稳定、黑斑占比低),跳过容易放大噪声的直方图均衡化操作,直接通过灰度阈值分割+连通域提取+逐行统计的方式计算宽度,鲁棒性远高于直接做边缘检测或颜色过滤。
具体实现步骤
1. 直接做前景背景分割
import cv2 import numpy as np # 直接读取原始图像转灰度,不需要提前做均衡化(均衡化会放大暗区噪声) gray = cv2.cvtColor(raw_img, cv2.COLOR_BGR2GRAY) # 用OTSU大津法自动计算阈值,适配物体从亮到暗的梯度特性,自动区分纯黑背景和发光前景 _, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 做2次形态学开运算,去除零星噪声点和小面积黑斑的干扰 kernel = np.ones((3,3), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2)
2. 分离三个独立发光物体
# 提取外轮廓,过滤面积过小的噪声轮廓 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 按轮廓的x轴坐标从小到大排序,依次对应左、中、右三个物体 contours = sorted(contours, key=lambda x: cv2.boundingRect(x)[0]) # 生成每个物体的独立掩码 object_masks = [] for cnt in contours[:3]: single_obj_mask = np.zeros_like(mask) cv2.drawContours(single_obj_mask, [cnt], -1, 255, -1) object_masks.append(single_obj_mask)
3. 逐高度段计算宽度,过滤异常值
def calc_valid_width(obj_mask, segment_num=10): h = obj_mask.shape[0] # 逐行统计当前行物体的像素宽度 row_width = np.count_nonzero(obj_mask, axis=1) seg_height = h // segment_num seg_valid_width = [] for i in range(segment_num): start_row = i * seg_height end_row = start_row + seg_height if i != segment_num-1 else h # 提取当前段的所有行宽度,过滤黑斑导致的0值 current_seg = row_width[start_row:end_row] current_valid = current_seg[current_seg > 0] # 仅保留有效行占比超过70%的段,排除黑斑严重的分段 if len(current_valid) >= seg_height * 0.7: seg_valid_width.append(np.median(current_valid)) # 最终宽度取所有有效段的中位数,进一步降低噪声影响 return np.median(seg_valid_width) # 分别输出三个物体的宽度(像素单位,可结合相机标定参数转换为物理长度) left_width = calc_valid_width(object_masks[0]) mid_width = calc_valid_width(object_masks[1]) right_width = calc_valid_width(object_masks[2])
补充优化点
- 若需要亚像素级测量精度,可在获取每个物体的左右边缘点坐标后,基于边缘附近的灰度值一阶矩做亚像素拟合,精度可以提升到0.1像素级
- 不需要使用HSV颜色过滤,高温白炽发光体的亮度远高于背景,灰度阈值的鲁棒性远高于颜色阈值,不受发光色温波动影响
内容的提问来源于stack exchange,提问作者Alexandre Tavares
相关产品推荐
相关产品推荐

