You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV气泡轮廓极值点处理:多同X轴点时实现Y轴对齐选取

解决方案:OpenCV气泡轮廓极值点Y轴对齐问题

问题说明

用OpenCV提取充气气泡(白色区域)轮廓的极值点时,先对图像二值化、阈值处理后提取轮廓,再通过numpy的argmin()/argmax()获取最左、最右点。但当最右点所在竖直线上存在多个像素时,argmax()仅返回第一个实例,导致最左、最右点Y轴坐标不对齐,弦长计算出现误差。

需求:

  • 若某X轴上存在多个点,最左和最右点需Y轴对齐
  • 若无多点,仍按原逻辑选取第一个实例

修改后的代码实现

核心思路是先筛选出最左/最右X值对应的所有点,再通过匹配Y坐标(优先取中位数或最接近值)实现两点对齐:

# 导入必要库(若未导入)
import numpy as np
from scipy.spatial import distance as dist
import cv2
import imutils
from imutils import contours

# (原阈值处理代码省略)

cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
(cnts, _) = contours.sort_contours(cnts)

# 选择气泡轮廓(索引根据实际情况调整)
c = cnts[1]

# 将轮廓坐标转换为二维数组(原形状为(N,1,2))
points = c.reshape(-1, 2)
x_coords = points[:, 0]
y_coords = points[:, 1]

# 获取最小、最大X值
min_x = x_coords.min()
max_x = x_coords.max()

# 筛选最左X、最右X对应的所有点
left_points = points[x_coords == min_x]
right_points = points[x_coords == max_x]

# 计算目标Y值(优先用左点的中位数,保证对齐)
if len(left_points) == 1:
    target_y = left_points[0][1]
else:
    target_y = np.median(left_points[:, 1])

# 确定最左点:若左点有多个,选最接近目标Y的点
if len(left_points) > 1:
    left_idx = np.argmin(np.abs(left_points[:, 1] - target_y))
    extLeft = tuple(left_points[left_idx])
else:
    extLeft = tuple(left_points[0])

# 确定最右点:在右点中选最接近目标Y的点
if len(right_points) > 1:
    right_idx = np.argmin(np.abs(right_points[:, 1] - target_y))
    extRight = tuple(right_points[right_idx])
else:
    extRight = tuple(right_points[0])

# 原有的顶部、底部极值点计算逻辑不变
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])

# 后续绘图、计算、保存代码不变
cv2.drawContours(image, [c], -1, (0, 255, 255), 2)
cv2.circle(image, extLeft, 4, (0, 0, 255), -1)
cv2.circle(image, extRight, 4, (0, 255, 0), -1)
cv2.circle(image, extTop, 1, (255, 0, 0), -1)
cv2.circle(image, extBot, 1, (255, 100, 0), -1)

chord = (dist.euclidean(extLeft, extRight))/pixelsPerMetric
height = int(extTop[1]-extBot[1])/pixelsPerMetric
print(chord)
print(height)

cv2.putText(image, "{:.1f}mm".format(chord), extLeft, cv2.FONT_HERSHEY_SIMPLEX, 0.65, (255, 255, 255), 2)
cv2.imshow("Image", image)
fname="extreme.jpg"

print(extLeft)
print(extBot)
print(extRight)

cv2.imwrite(fname, image)
cv2.waitKey(0)
cv2.destroyAllWindows()

代码说明

  1. 轮廓坐标转换:将OpenCV返回的三维轮廓数组c转换为二维数组,方便后续筛选操作
  2. 筛选极值X对应的点:提取所有X等于最小/最大值的点,覆盖同竖直线上的所有像素
  3. Y坐标对齐逻辑:
    • 若最左X只有一个点,直接以其Y为目标值;若有多个点,取Y坐标的中位数作为基准
    • 在最右X的点集中,选取Y坐标最接近目标值的点,确保两点Y轴对齐
    • 若最左X有多个点,同样选取最接近目标Y的点,保证逻辑一致性

内容的提问来源于stack exchange,提问作者chipmunk008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:55:16