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

MATLAB摄像头风扇RPM计算:双图显示与角度计算疑问

风扇RPM计算:子图独立显示与角度计算问题解决

一、解决子图独立显示问题

你的代码中两个循环分别调用figure(1)和figure(2),但由于绘图焦点切换和窗口渲染时机问题,导致第一个窗口被后台隐藏。只需调整窗口创建逻辑,确保两个窗口提前创建并完成渲染:

修改后的代码片段

黄色风扇中心检测循环

% 提前创建第一个独立窗口,设置标题便于区分
figure(1,'Name','黄色风扇中心检测');
for i=1:10
    filename = sprintf('imagen_%d.jpg', i);
    img = imread(filename);
    img_hsv = rgb2hsv(img);
    
    % 黄色掩码与圆形检测代码(保持不变)
    h_min = 0.11; h_max = 0.18;
    s_min = 0.3; s_max = 1.0;
    v_min = 0.7; v_max = 1.0;
    h_mask = (img_hsv(:,:,1) >= h_min) & (img_hsv(:,:,1) <= h_max);
    s_mask = (img_hsv(:,:,2) >= s_min) & (img_hsv(:,:,2) <= s_max);
    v_mask = (img_hsv(:,:,3) >= v_min) & (img_hsv(:,:,3) <= v_max);
    yellow_mask = (h_mask & s_mask & v_mask);
    
    rangoRadio = [80 200];
    sensibilidad = 0.95;
    [centros,radios] = imfindcircles(yellow_mask,rangoRadio,'ObjectPolarity','bright','Sensitivity',sensibilidad);
    
    if ~isempty(centros)
        centro = round(centros(1,:));
        centros_circulos(i,:) = centro;
        radio = round(radios(1));
        img_rect = insertShape(img,'Rectangle',[centro(1)-radio centro(2)-radio radio*2 radio*2],'LineWidth',2,'Color','yellow');
        
        subplot(2,5,i); imshow(img_rect);
        title('黄色圆心已检测');
    else
        subplot(2,5,i); imshow(img);
        title('未检测到黄色圆心');
    end
    disp(centros_circulos);
end
% 强制刷新窗口,确保所有子图渲染完成
drawnow;

蓝色标识检测循环

% 提前创建第二个独立窗口
figure(2,'Name','蓝色标识检测');
for i=1:10
    filename = sprintf('imagen_%d.jpg', i);
    img = imread(filename);
    img_hsv = rgb2hsv(img);
    
    % 蓝色掩码检测代码(保持不变)
    h_min = 0.50; h_max = 0.61;
    s_min = 0.34; s_max = 1.0;
    v_min = 0.47; v_max = 1.0;
    h_mask = (img_hsv(:,:,1) >= h_min) & (img_hsv(:,:,1) <= h_max);
    s_mask = (img_hsv(:,:,2) >= s_min) & (img_hsv(:,:,2) <= s_max);
    v_mask = (img_hsv(:,:,3) >= v_min) & (img_hsv(:,:,3) <= v_max);
    blue_mask = (h_mask & s_mask & v_mask);
   
    subplot(2,5,i); imshow(blue_mask);
    title(sprintf('图像 %d', i));
    [height, width]=size(blue_mask);
    contador=0;
    xprom=0;
    yprom=0;
    for y=1:height
        for x=1:width
            if(blue_mask(y,x))
                contador=contador+1;    
                xprom=xprom+x;
                yprom=yprom+y;
            end
        end
    end   
    xprom=xprom/contador;
    yprom=yprom/contador;
    centros_azul(i,1)=xprom;
    centros_azul(i,2)=yprom;
    fprintf('图像 %d 中蓝色标识坐标: (%.2f, %.2f)\n', i, xprom, yprom);
end
drawnow;

修改说明:

  • 提前创建两个独立窗口,避免循环内重复调用figure()导致的焦点切换
  • 使用drawnow强制Matlab完成窗口渲染,确保子图全部显示
  • 为窗口添加标题,便于区分两个结果窗口

二、关于+2*pi的保留判断

不能直接保留+2*pi,需要结合角度差的正负动态调整,同时必须替换atan为atan2:

问题根源

  1. 当前使用的atan(y/x)只能返回[-π/2, π/2]范围内的角度,无法区分象限,会导致角度计算完全错误(比如x为负时,角度值会偏离实际位置)
  2. 直接添加+2*pi会导致角度差为正时,总旋转角度被多算2π,最终RPM结果偏大

正确的角度计算代码

% 计算平均旋转角度
for i=1:9
    x1=centro_x_prom-centros_azul(i,1);
    y1=centro_y_prom-centros_azul(i,2);
    x2=centro_x_prom-centros_azul(i+1,1);
    y2=centro_y_prom-centros_azul(i+1,2);
    
    % 使用atan2(y, x)获取正确的象限角度,返回范围[-π, π]
    a1=atan2(y1, x1);
    a2=atan2(y2, x2);
    
    delta = a2 - a1;
    % 当角度差为负时,说明风扇旋转了超过半圈,补充2π得到实际正角度差
    if delta < 0
        delta = delta + 2*pi;
    end
    tetha = tetha + delta;
end

逻辑说明

  • atan2(y, x)会根据x和y的正负自动判断象限,返回[-π, π]的真实角度
  • 风扇旋转是周期性的,当后一帧的角度a2小于前一帧的a1时,说明标识已经绕圆心转了一圈(比如从π转到-π,实际旋转了2π),此时需要给负的角度差补充2π,得到实际旋转的正角度
  • 只有当角度差为负时才添加2π,避免不必要的累加误差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:10:03