Object Measurement System from Images/Video

Developing an Object Measurement System from Images or Video

AI Development Areas

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_logo-advance_0.webp
    B2B Advance company logo design
    696
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_logo-aider_0.webp
    AIDER company logo development
    919
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033

Developing an Object Measurement System from Images or Video

This is a task we solve using computer vision. On a production line, a part just came out of the machine — hot (80°C). Contact measurement with a caliper deforms the surface, introducing an error of up to 0.5 mm. Non-contact measurement via camera: a single shot in 50 ms, accuracy ±0.1 mm, data straight to SCADA. No risk of burns or conveyor stoppage.

Problems We Solve

Quality control on the production line. The part just came out of the machine — deviations from the drawing are detected instantly. The system measures length, width, diameter, angles, and contour area in 50 ms. Out-of-tolerance triggers an alarm or line stop.

Field measurements without access to the object. Need to know the width of a crack in a wall or the diameter of a pipe at height? Place an ArUco marker next to it, take a photo — in a second the dimensions are known. Ladders and rulers are unnecessary.

Logistics and warehouse. Box dimensions on a conveyor belt are measured in motion. The system automatically assigns length, width, and height to each unit — optimizing container loading.

How to Ensure Millimetre-Accurate Measurements

The key parameter is scale. We use three methods:

  1. Calibrated camera — photograph a calibration plate once from the working distance, compute pixels_per_mm. Accuracy ±0.1 mm. Ideal for static conveyors.

  2. ArUco marker in the frame — a marker of known size (e.g., 50 mm) is placed next to the object. The system detects the marker, computes the scale, then measures the object. Accuracy ±1–5 mm, suitable for field conditions.

  3. Stereo pair — two cameras spaced 10 cm apart produce a 3D point cloud. From this we extract overall dimensions, depth, volume. Accuracy ±0.5–2 mm on objects up to 1 m.

The choice of method depends on the task. For a conveyor with a fixed camera position — calibration. For a mobile tablet — ArUco. For large objects (furniture, pallets) — stereo or LiDAR+RGB.

How to Choose the Measurement Method?

  • If the object moves on a conveyor at constant speed and the camera is fixed — choose a calibrated camera. Maximum accuracy ±0.1 mm and measurement time 50 ms.

  • If you are in a warehouse or field — use an ArUco marker. Print a 5×5 cm marker, glue it onto a rigid base, and place it next to the object. The system will automatically determine the scale.

  • If you need to measure volume or depth — use a stereo pair. Two cameras with a 10 cm baseline build a 3D model and output dimensions in millimetres.

Step-by-Step: How the System Measures an Object

  1. Image capture. The camera takes a snapshot (or frame from video). Resolution and frame rate are configured.
  2. Scale determination. The system finds the calibration object or ArUco marker, computes pixels_per_mm.
  3. Object segmentation. We use thresholding (Otsu) or a neural network for complex contours.
  4. Dimension extraction. From the contour we compute bounding box, minimal rectangle, perimeter, area.
  5. Conversion to millimetres. Multiply pixel values by pixels_per_mm.
  6. Result output. Send data as JSON, to a database, or to the operator's screen.

What the Work Includes

  • Task analysis: Send us a photo/video of the object with shooting conditions (distance, lighting, motion). We choose the method and prepare an estimate in 1 day.
  • Prototype: In 3–5 days we build a demo version for your scenario. You test it on real data.
  • Development: We implement segmentation, calibration, and measurement algorithms. Stack: OpenCV, PyTorch (if a neural network for complex contours is needed), Docker, FastAPI.
  • Integration: Embed the module into your PLC/SCADA, add REST API, MQTT, Modbus.
  • Documentation and training: Deliver code, API description, operator instructions.
  • Support: 3 months free support, then by contract.

Timeframes (Approximate)

Task Duration
2D measurement on a conveyor 2–4 weeks
System with ArUco for field use 3–5 weeks
3D stereo system 6–10 weeks

Cost is calculated individually and depends on segmentation complexity, number of cameras, and need for neural networks. Write to us — we will give a preliminary estimate in 1 day.

Why Choose Us?

Over 10 years of experience in industrial CV. We have implemented 50+ projects for mechanical engineering, logistics, and medicine. Accuracy guarantee: we record metrological characteristics in the contract. We always provide a validation report. Development processes are standardized according to ISO 9001. Compared to Western Halcon/Matrox solutions, our solution is 2–3 times cheaper with comparable accuracy, and implementation time is 1.5 times shorter.

Our customers save up to 2 million rubles per year on quality control. For example, one client reduced inspection time by 80%, equivalent to savings of about 1.5 million rubles per year. Get a consultation from an engineer with 10+ years of CV experience — contact us.

Scaling Methods

Method 1: Calibrated Camera

Once we photograph an object of known size (calibration plate) from the working distance, compute the pixels_per_mm coefficient:

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: """Calibration using an object of known width""" # Assume object is already aligned and occupies ~80% of width 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: """Measure object's key parameters""" if self.camera_matrix is not None: # Correct lens distortion 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) # Minimal rotated rectangle rect = cv2.minAreaRect(c) (cx, cy), (rw, rh), angle = rect min_side = min(rw, rh) max_side = max(rw, rh) # Perimeter via arc length perimeter_px = cv2.arcLength(c, True) # Area 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)) } 

Method 2: Reference Object in Frame (ArUco Markers)

import cv2.aruco as aruco def measure_with_aruco(image: np.ndarray, marker_size_mm: float = 50.0) -> dict: """Measurement using ArUco marker as reference""" 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'} # Compute pixels_per_mm from the marker marker_corners = corners[0][0] marker_width_px = np.linalg.norm(marker_corners[0] - marker_corners[1]) ppm = marker_width_px / marker_size_mm # Then standard measurement measurer = CalibratedMeasurement(pixels_per_mm=ppm) return measurer.measure_contour(image) 

3D Measurement via Stereo Pair

class StereoCameraMeasurement: def __init__(self, stereo_calibration: dict): self.Q = stereo_calibration['Q'] # disparity-to-depth matrix 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 # Convert disparity to 3D point cloud points_3d = cv2.reprojectImageTo3D(disparity, self.Q) return self._extract_dimensions_3d(points_3d) 

Accuracy and Applications

Method Range Accuracy Application
2D with calibration (fixed distance) 1–500 mm ±0.1–0.5 mm Conveyor, QC
ArUco reference 10–2000 mm ±1–5 mm Field measurements
Stereo (10 cm baseline) 50–1000 mm ±0.5–2 mm 3D measurement
LiDAR + RGB 100–5000 mm ±1–3 mm Large objects

According to a NIST study, non-contact measurement reduces error by 40%. Ready to discuss your task. Write to us — we will evaluate your project in 1 day. Get a consultation from an engineer.