Matlab中如何获取旋转多边形对象的真实最大宽高(非边界框)
在Matlab中获取旋转polyshape对象的真实最大宽高
你现在的代码计算的是最小包围盒的宽高,但你要的是对象自身的「真实最大宽高」——也就是沿着某个方向上,对象上任意两点的最大跨度(类似椭圆的长轴/短轴长度),这和包围盒尺寸确实不是一回事。下面给你两种可行的实现方案:
方案一:遍历所有角度计算投影跨度(精度可控)
这个方法通过遍历不同角度,计算对象凸包在该角度下的投影跨度,找到最大的那个值,精度可以通过角度步长调整:
clc; clear all; Image = imread('E:/moon.gif'); BW = imbinarize(Image); BW = imfill(BW,'holes'); BW = bwareaopen(BW, 100); stat = regionprops(BW,'ConvexHull'); % 初始化最大宽高变量 max_width = 0; max_height = 0; best_angle_w = 0; best_angle_h = 0; % 遍历0-180度的角度(步长0.5度,步长越小精度越高) angles = 0:0.5:180; for ii=1:numel(stat) hull_points = stat(ii).ConvexHull; % 用凸包点计算,和原对象最大跨度一致,且计算更快 for phi = angles % 构建旋转矩阵,将点旋转到以phi为x轴的坐标系 rot_mat = [cosd(phi), sind(phi); -sind(phi), cosd(phi)]; rotated_points = hull_points * rot_mat; % 计算当前角度下的x方向跨度(宽度)和y方向跨度(高度) curr_w = max(rotated_points(:,1)) - min(rotated_points(:,1)); curr_h = max(rotated_points(:,2)) - min(rotated_points(:,2)); % 更新最大宽高记录 if curr_w > max_width max_width = curr_w; best_angle_w = phi; end if curr_h > max_height max_height = curr_h; best_angle_h = phi; end end end % 输出结果 fprintf('真实最大宽度: %.2f (对应角度: %.1f°)\n', max_width, best_angle_w); fprintf('真实最大高度: %.2f (对应角度: %.1f°)\n', max_height, best_angle_h);
关键说明:
- 用凸包点而不是原对象所有点:凸包包含了对象的所有极端点,计算凸包的跨度和原对象完全一致,但点的数量更少,能大幅提升计算速度。
- 角度遍历范围:只需要遍历0-180度,因为180度和0度的方向是完全重复的。
- 步长调整:如果需要更高精度,可以把步长改成0.1度,但计算时间会相应增加。
方案二:直接用Regionprops的Feret属性(简单快捷)
如果你的Matlab版本支持,regionprops的FeretProperties可以直接返回对象的最大Feret直径(也就是你要的真实最大跨度),以及对应的角度:
clc; clear all; Image = imread('E:/moon.gif'); BW = imbinarize(Image); BW = imfill(BW,'holes'); BW = bwareaopen(BW, 100); stat = regionprops(BW,'FeretProperties','ConvexHull'); % 最大Feret直径就是真实最大宽度/高度(取最大的那个) max_span = stat.FeretDiameter; max_span_angle = stat.FeretAngle; % 如果需要垂直于最大跨度方向的高度,直接计算90度方向的跨度 perp_phi = max_span_angle + 90; rot_mat = [cosd(perp_phi), sind(perp_phi); -sind(perp_phi), cosd(perp_phi)]; rotated_points = stat.ConvexHull * rot_mat; perp_span = max(rotated_points(:,1)) - min(rotated_points(:,1)); fprintf('真实最大跨度: %.2f (对应角度: %.1f°)\n', max_span, max_span_angle); fprintf('垂直方向最大跨度: %.2f (对应角度: %.1f°)\n', perp_span, perp_phi);
关键说明:
- Feret直径的定义就是对象上任意两点在某个方向上的投影距离的最大值,完全符合你说的「真实最大宽高」。
- 如果你需要的是一对垂直的宽高(类似长轴短轴),可以在得到最大跨度的角度后,直接计算其垂直方向的跨度即可。
内容的提问来源于stack exchange,提问作者hs100
相关产品推荐
相关产品推荐

