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:
问题根源
- 当前使用的
atan(y/x)只能返回[-π/2, π/2]范围内的角度,无法区分象限,会导致角度计算完全错误(比如x为负时,角度值会偏离实际位置) - 直接添加
+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
相关产品推荐
相关产品推荐

