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

如何用Python识别旋转圆盘角度以驱动步进电机

基于圆盘图像旋转角度控制步进电机的解决方案

问题描述

我拍摄了旋转圆盘的图像,希望根据圆盘的旋转角度来驱动步进电机旋转相同角度。圆盘示例图像如下:
旋转圆盘示例图像

我尝试通过旋转原始图像360度寻找均方误差(MSE)最小的角度,但该方法无效,相关代码如下:

MSE计算函数

def mse(img1, img2):
    img1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY)
    img2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
    h, w = img1.shape
    diff = cv.subtract(img1, img2)
    err = np.sum(diff**2)
    mse = err/(float(h*w))
    return mse

旋转匹配代码

for i in range(0,360,5):
    rotate = imutils.rotate(r,i)
    differ = mse(rotate,r)
    print(differ,i)

可行解决方案

1. 提取圆盘特征标记计算角度

圆盘上有明显的黑白扇形标记,直接利用这些标记计算角度:

  • 对图像做二值化处理,提取白色区域轮廓
  • 计算白色扇形的中心角度:通过轮廓的最小外接矩形/拟合椭圆得到角度范围,或计算白色区域重心,结合圆盘中心计算夹角
  • 对比初始参考图像的白色标记角度,得到旋转差值

2. 局部模板匹配优化检测

  • 截取圆盘上一个独特的局部标记(比如某块白色扇形的局部)作为模板
  • 在目标图像中结合旋转操作使用cv2.matchTemplate进行匹配,找到匹配度最高的角度,即为圆盘旋转角度
  • 相比全图MSE,局部模板匹配受背景干扰更小,精度更高

3. 霍夫圆检测+圆心角计算

  • 用霍夫圆检测定位圆盘的中心和半径
  • 提取圆盘边缘像素,结合二值化后的黑白区域,计算白色区域对应的圆心角
  • 对比初始状态的圆心角,得到旋转角度差

4. 改进原有MSE方法

你之前的MSE方法无效,大概率是因为旋转图像时出现黑边(imutils.rotate默认会保留或裁剪黑边),导致全图对比误差大:

  • 改用cv2.warpAffine进行旋转,保持图像尺寸并填充背景(比如用圆盘背景色填充)
  • 先通过霍夫圆检测提取圆盘掩码,只计算掩码内区域的MSE,排除背景干扰

代码示例(特征点角度计算)

import cv2
import numpy as np

def get_disk_angle(img_path):
    # 读取图像并预处理
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    
    # 检测圆盘中心(霍夫圆)
    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=100, maxRadius=200)
    if circles is not None:
        circles = np.uint16(np.around(circles))
        center_x, center_y = circles[0][0][0], circles[0][0][1]
        
        # 提取白色区域轮廓
        contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        for cnt in contours:
            # 计算轮廓重心
            M = cv2.moments(cnt)
            if M["m00"] != 0:
                cx = int(M["m10"] / M["m00"])
                cy = int(M["m01"] / M["m00"])
                # 计算重心与中心的夹角(以y轴正方向为0度,顺时针为正)
                angle = np.arctan2(cx - center_x, center_y - cy) * 180 / np.pi
                if angle < 0:
                    angle += 360
                return angle
    return 0

# 计算初始角度和当前角度
initial_angle = get_disk_angle("initial_disk.jpg")
current_angle = get_disk_angle("current_disk.jpg")
rotation_diff = (current_angle - initial_angle) % 360
print(f"圆盘旋转角度:{rotation_diff}度")

# 驱动步进电机(示例,根据电机参数调整)
# step_angle = 1.8  # 步进电机步距角
# steps_needed = int(rotation_diff / step_angle)
# 调用电机驱动代码发送steps_needed步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:53:33