Object Measurement System from Images/Video

Measuring objects in production or in the field often requires contact with the surface, which is not always possible or safe. We develop computer vision systems that determine dimensions from photos or videos without touching the object. Our team delivers the project turnkey—from selecting the calibration method to implementation and ongoing support.

AI Development Areas

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1344
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1307
  • B2B Advance company logo design
    B2B Advance company logo design
    754
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1050
  • AIDER company logo development
    AIDER company logo development
    994
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1097

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 $18k–26k per year on quality control. For example, one client reduced inspection time by 80%, equivalent to savings of about $14k–20k 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.