You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测类瓶圆柱物体是否与相机光轴垂直?

Got it, let's figure out how to check if a bottle-shaped cylinder is perpendicular to the camera's optical axis—since you don't need high precision, we can keep this straightforward and avoid overcomplicating things!

核心思路

Your input has a huge advantage: a solid-color background paired with a single bottle-like cylinder. We can leverage the contour shape features of the object to make the call:

  • When the object is perpendicular to the optical axis, it’ll appear as either a perfectly circular end face or a neat rectangular side profile from the camera’s view.
  • When it’s not perpendicular (like in a slight top-down shot or tilted angle), the end face will stretch into an ellipse (with a big gap between major and minor axes), and the side profile will become a trapezoid or a rotated rectangle.
分步实现方案

1. Preprocessing: Separate Object from Background

The solid background makes this step trivial:

  • Convert the image to grayscale, then use binary thresholding (cv2.threshold()) to split the object from the background.
  • Use morphological opening (cv2.morphologyEx()) to wipe out tiny noise spots that might mess up contour detection.

2. Extract Contour Features & Make the Judgment

Grab the largest contour (that’s your target object), then pick a logic based on how the object is facing the camera:

Scenario 1: Object’s End Face is Facing the Camera

Fit a minimum enclosing ellipse to the contour, then calculate the ratio of its major axis to minor axis:

  • If perpendicular, the ellipse is nearly a circle, so the ratio is close to 1.
  • If not perpendicular, the ellipse gets stretched, and the ratio will be much larger than 1.

Scenario 2: Object’s Side Profile is Facing the Camera

Fit a minimum enclosing rectangle to the contour, then check its rotation angle:

  • If perpendicular, the rectangle is "straight" (rotation angle is close to 0° or 90°).
  • If not perpendicular, the rectangle will have a noticeable tilt, or the contour will approximate a trapezoid.
Code Example (Python + OpenCV)

Here’s a simple implementation that works for both scenarios:

import cv2
import numpy as np

def is_cylinder_perpendicular(img_path, ratio_threshold=0.15, angle_threshold=5):
    # Read the input image
    img = cv2.imread(img_path)
    if img is None:
        return False
    
    # Preprocess to isolate the object
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Adjust THRESH_BINARY/THRESH_BINARY_INV based on your object/background colors
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    # Remove small noise
    kernel = np.ones((3, 3), np.uint8)
    binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
    
    # Extract the main object contour
    contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    if not contours:
        return False
    main_contour = max(contours, key=cv2.contourArea)
    
    # Handle end face scenario (fit ellipse)
    if len(main_contour) >= 5:
        ellipse = cv2.fitEllipse(main_contour)
        major_axis, minor_axis = ellipse[1]
        # Ensure major axis is the longer one
        if major_axis < minor_axis:
            major_axis, minor_axis = minor_axis, major_axis
        axis_ratio = major_axis / minor_axis
        # Check if ratio is close to 1
        return abs(axis_ratio - 1) < ratio_threshold
    else:
        # Handle side profile scenario (fit rectangle)
        rect = cv2.minAreaRect(main_contour)
        _, _, angle = rect
        # Normalize angle to 0-45° range
        if angle > 45:
            angle = 90 - angle
        # Check if rectangle is "straight"
        return abs(angle) < angle_threshold
Quick Adjustment Tips
  • If you know your objects are mostly facing one way (end face/side profile), you can strip out the unused logic to simplify the code.
  • Tweak ratio_threshold and angle_threshold based on your samples: since you don’t need high precision, feel free to set them a bit loose (e.g., ratio_threshold = 0.2).
  • If your background isn’t grayscale, use cv2.inRange() with RGB color ranges for cleaner object segmentation.

内容的提问来源于stack exchange,提问作者chamoda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:40:37