使用 OpenCV 测量物体的表观长度(以像素为单位)

Posted

技术标签:

【中文标题】使用 OpenCV 测量物体的表观长度(以像素为单位)【英文标题】:Measuring apparent length of object (in pixels) using OpenCV 【发布时间】:2021-03-15 07:48:58 【问题描述】:

我使用blender 从不同的角度/姿势渲染我的 3D 对象的不同图像。对象有彩色边缘(如图所示)。

现在,我的目标是使用 OpenCV 以像素为单位测量橙色和蓝色边缘的长度(Lo 和 Lb)。如果边缘由单个像素组成(即由单个边缘组成的线),这将是一项容易的任务。但是,这里不是这样。

感谢任何帮助。

【问题讨论】:

使用 cv2.inRange() 的颜色阈值。然后得到轮廓。然后使用 cv2.minAreaRect() 获取旋转后的边界框。这将返回该区域的长度宽度和角度。对其他颜色执行相同操作。 要求用户选点?投影到屏幕后让搅拌机倾倒对象的角落? @ChristophRackwitz 我无法理解:/ 【参考方案1】:

这是 Python OpenCV 中的一种方式。

 - Read the input
 - Threshold on one of the colors
 - Apply morphology to close gap
 - Get the contour
 - Get the rotated rectangle
 - Get the length from the rotated rectangle
 - Compute the centerline length
 - Draw the rotated rectangle on the input
 - Draw the centerline on the input
 - Save the results

输入:

import cv2
import numpy as np
import math

# read image
img = cv2.imread("blender.png")

# get color bounds of brown
lower =(0,30,60) # lower bound for each channel
upper = (20,50,80) # upper bound for each channel

# create the mask and use it to change the colors
thresh = cv2.inRange(img, lower, upper)

# apply morphology
kernel = np.ones((3,3), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# get contour
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cntr = contours[0]

# get rotated rectangle from contour
rot_rect = cv2.minAreaRect(cntr)
box = cv2.boxPoints(rot_rect)
box = np.int0(box)

# draw rotated rectangle on copy of img
rot_bbox = img.copy()
cv2.drawContours(rot_bbox, [box], 0, (255,255,255), 1)

# get dimensions
(center), (width,height), angle = rot_rect

# print dimensions
print('length=', height)
print('thickness=', width)

# get center line from box
# note points are clockwise from bottom right
x1 = (box[0][0] + box[3][0]) // 2
y1 = (box[0][1] + box[3][1]) // 2
x2 = (box[1][0] + box[2][0]) // 2
y2 = (box[1][1] + box[2][1]) // 2

# draw centerline on image
center_line = img.copy()
cv2.line(center_line, (x1,y1), (x2,y2), (255,255,255), 1)

# compute center line length
cl_length = math.sqrt( (x1-x2)**2 + (y1-y2)**2 )
print('centerline_length',cl_length)

# write img with red rotated bounding box to disk
cv2.imwrite("blender_thresh.jpg", thresh)
cv2.imwrite("blender_morph.jpg", morph)
cv2.imwrite("blender_rot_rect.jpg", rot_bbox)
cv2.imwrite("blender_length.jpg", center_line)


# display it
cv2.imshow("THRESHOLD", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("BBOX", rot_bbox)
cv2.imshow("CENTLINE", center_line)
cv2.waitKey(0)

阈值图像:

形态图像:

输入时的旋转矩形:

输入中心线:

测量:

length= 488.6615295410156
thickness= 9.058079719543457
centerline_length 488.83637344207517

【讨论】:

这看起来很整洁。它可以应用于非结构化边缘(如其他 3 个边缘)吗? 是的,您可以通过颜色和形态对它们进行阈值化,以将其清理成一条线或四边形。如果你能做到这一点,你可以获得旋转的边界框。或者如果它们足够薄,只需计算非零像素。仔细观察你的原件,蓝色和绿色区域很好,但顶部的红色边缘不是干净、恒定的红色。它从红色混合到白色。 另一种方法是在大的主四边形区域设置阈值。然后获取轮廓,然后使用 approxPolyDP() 将顶点数减少到适当的 4 边四边形。然后从顶点计算 4 条边的长度。

以上是关于使用 OpenCV 测量物体的表观长度(以像素为单位)的主要内容,如果未能解决你的问题,请参考以下文章

如何测量图像中每个极点的长度(以像素为单位)

看点云图的技巧

halcon能测量物体长度吗

想法如何使用opencv for IOS测量检测到的物体与相机的距离?

热视觉2:使用Python和OpenCV从图像中测量温度

opencv如何计算图像中物体的像素值