基于OpenCV的居中目标像素尺寸测量移动端实现问询
Got it, let's tackle this problem step by step. Since you already know the real height of your target and can ensure it's centered in the frame, this simplifies things a lot—here's a practical, mobile-friendly approach using OpenCV:
The entire distance calculation relies on the similar triangles formed by your camera's focal length, the target's real height, and its pixel height in the frame. The formula is straightforward:
Distance (D) = (Target Real Height (H) * Camera Focal Length (f)) / Target Pixel Height (h)
Since your target is centered, we can safely ignore most lens distortion effects (we'll cover a precision tweak for this later) which makes the math reliable on mobile.
First, you need to calculate your camera's focal length (in pixels) — this only needs to be done once per device (or camera lens, if your phone has multiple):
- Grab a flat object with a known real height (e.g., an A4 paper, which is 297mm tall)
- Place it dead-center in front of your camera, measure the exact physical distance between the camera lens and the object (let's call this
D0, e.g., 500mm) - Take a clear photo, then use OpenCV to measure the object's pixel height in the image (
h0) - Calculate focal length:
f = (h0 * D0) / H0(whereH0is the known real height of your calibration object)
For example, if your A4 paper is 297mm tall, sits 500mm away, and measures 600 pixels tall in the image:f = (600 * 500) / 297 ≈ 1010 pixels
Once you have your focal length, here's how to build the mobile workflow:
1. Capture & Preprocess the Frame
On mobile, use your camera API (e.g., CameraX on Android, AVFoundation on iOS) to get a frame, then convert it to an OpenCV Mat for processing. Since the target is centered, you can even crop the frame to a central region to speed up processing.
2. Measure the Target's Pixel Height
You'll need to detect your target in the central area. Depending on your use case:
- If it's a high-contrast object: Use
Imgproc.threshold()to binarize the image, thenImgproc.findContours()to extract the target's contour. Calculate the bounding box height of the contour as yourh. - If it's a specific shaped object: Use template matching (
Imgproc.matchTemplate()) to locate it, then get the template's height ash.
3. Calculate Distance
Plug the values into the formula from earlier. Here's a simplified Android/Kotlin example:
// Pre-calibrated focal length (pixels) private val focalLength = 1010.0 // Known real height of your target (e.g., 200mm) private val targetRealHeight = 200.0 fun calculateDistance(targetPixelHeight: Double): Double { if (targetPixelHeight <= 0) return -1.0 // Invalid measurement // Apply similar triangles formula return (targetRealHeight * focalLength) / targetPixelHeight }
- Distortion Correction (For Precision): Even with a centered target, wide-angle mobile lenses can have minor distortion. To fix this, run a full camera calibration using OpenCV's
calibrateCamera()function to get distortion coefficients, then useImgproc.undistort()on each frame before processing. - Stabilize Measurements: Mobile cameras shake—average the pixel height across 3-5 consecutive frames to reduce noise.
- Validate Target Position: Add a check to ensure the detected target's center is within a small threshold of the frame's center (e.g., ±5% of frame width/height) to enforce your constraint.
- If your distance readings are off: Double-check your calibration (make sure the calibration object was perfectly centered and the distance/height measurements were accurate).
- Slow performance on mobile: Crop frames to the central region before processing, use OpenCV's optimized native libraries for your platform, and avoid unnecessary contour processing.
内容的提问来源于stack exchange,提问作者Jim

