System Development измерения объектов по изображению/видео
Измерение размеров через компьютерное зрение заменяет штангенциркули, рулетки и ручные измерения. Система работает в двух режимах: с калиброванной камерой (известный масштаб, точность до десятых миллиметра) и с референсным объектом в кадре (для полевых измерений).
Методы масштабирования
Метод 1: Калиброванная камера
Один раз фотографируем объект известного размера (калибровочная пластина) с рабочего расстояния, вычисляем коэффициент pixels_per_mm:
import cv2
import numpy as np
class CalibratedMeasurement:
def __init__(self, pixels_per_mm: float,
camera_matrix: np.ndarray = None,
dist_coefficients: np.ndarray = None):
self.ppm = pixels_per_mm
self.camera_matrix = camera_matrix
self.dist_coefficients = dist_coefficients
def calibrate_from_reference(self, image: np.ndarray,
known_width_mm: float) -> float:
"""Калибровка по объекту известной ширины"""
# Предполагаем что объект уже выровнен и занимает ~80% ширины
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
main = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(main)
self.ppm = w / known_width_mm
return self.ppm
def measure_contour(self, image: np.ndarray) -> dict:
"""Измерение основных параметров объекта"""
if self.camera_matrix is not None:
# Исправление дисторсии линзы
image = cv2.undistort(image, self.camera_matrix,
self.dist_coefficients)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
if not contours:
return {'measured': False}
c = max(contours, key=cv2.contourArea)
# Bounding rectangle
x, y, w, h = cv2.boundingRect(c)
# Минимальный описывающий прямоугольник (с вращением)
rect = cv2.minAreaRect(c)
(cx, cy), (rw, rh), angle = rect
min_side = min(rw, rh)
max_side = max(rw, rh)
# Периметр через arc length
perimeter_px = cv2.arcLength(c, True)
# Площадь
area_px = cv2.contourArea(c)
return {
'width_mm': round(w / self.ppm, 3),
'height_mm': round(h / self.ppm, 3),
'length_mm': round(max_side / self.ppm, 3),
'width_min_mm': round(min_side / self.ppm, 3),
'angle_deg': round(angle, 2),
'perimeter_mm': round(perimeter_px / self.ppm, 3),
'area_mm2': round(area_px / self.ppm**2, 3),
'center': (round(cx / self.ppm, 2), round(cy / self.ppm, 2))
}
Метод 2: Референсный объект в кадре (ArUco маркеры)
import cv2.aruco as aruco
def measure_with_aruco(image: np.ndarray,
marker_size_mm: float = 50.0) -> dict:
"""Измерение с ArUco маркером как референсом"""
aruco_dict = aruco.getPredefinedDictionary(aruco.DICT_4X4_250)
detector = aruco.ArucoDetector(aruco_dict)
corners, ids, _ = detector.detectMarkers(image)
if ids is None:
return {'error': 'no_aruco_marker_found'}
# Вычисляем pixels_per_mm из маркера
marker_corners = corners[0][0]
marker_width_px = np.linalg.norm(marker_corners[0] - marker_corners[1])
ppm = marker_width_px / marker_size_mm
# Дальше стандартное измерение
measurer = CalibratedMeasurement(pixels_per_mm=ppm)
return measurer.measure_contour(image)
Измерение в 3D через стереопару
class StereoCameraMeasurement:
def __init__(self, stereo_calibration: dict):
self.Q = stereo_calibration['Q'] # disparity-to-depth матрица
self.baseline_mm = stereo_calibration['baseline_mm']
self.focal_length_px = stereo_calibration['focal_length_px']
def measure_3d(self, left_img: np.ndarray,
right_img: np.ndarray) -> dict:
# Stereo matching
stereo = cv2.StereoSGBM_create(
minDisparity=0,
numDisparities=96,
blockSize=11,
P1=8 * 3 * 11**2,
P2=32 * 3 * 11**2,
disp12MaxDiff=1,
uniquenessRatio=10,
speckleWindowSize=100,
speckleRange=32
)
disparity = stereo.compute(
cv2.cvtColor(left_img, cv2.COLOR_BGR2GRAY),
cv2.cvtColor(right_img, cv2.COLOR_BGR2GRAY)
).astype(np.float32) / 16.0
# Конвертация диспаретности в 3D облако точек
points_3d = cv2.reprojectImageTo3D(disparity, self.Q)
return self._extract_dimensions_3d(points_3d)
Точность и применения
| Метод | Диапазон | Точность | Применение |
|---|---|---|---|
| 2D с калибровкой (фиксированное расстояние) | 1–500 мм | ±0.1–0.5 мм | Конвейер, QC |
| ArUco референс | 10–2000 мм | ±1–5 мм | Полевые измерения |
| Стерео (10 cm базис) | 50–1000 мм | ±0.5–2 мм | 3D измерение |
| LiDAR + RGB | 100–5000 мм | ±1–3 мм | Крупные объекты |
| Задача | Срок |
|---|---|
| 2D измерение на конвейере | 2–4 недели |
| Система с ArUco для полевого применения | 3–5 недель |
| 3D стерео система | 6–10 недель |







