最小面积边界框
原文链接:https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/minimum-area-bounding-box
16513 对此文章评分:
3.0
最小面积边界框
匿名 2016年8月18日,星期四
我发现自己经常在物体周围绘制边界框。我不知道为什么我这么做,但不管出于什么原因,我确实经常这样做,而且最近我想提升我的边界框绘制水平。过去,我通常只是简单地使用 x 和 y 方向上的全局最小值和最大值来获取坐标以形成边界框;然而,这并不总是最优雅的解决方案。例如,当我的数据呈现出一定的线性趋势时,我就会留下大量未被任何有价值信息填充的空白区域。
图 1:简单边界框
图 2:最小面积边界框
这让我思考,为什么不只在数据周围绘制边界框呢?听起来很棒,对吧?唯一的问题是我完全不知道如何做到这一点。幸运的是,有一种叫做互联网的东西,它拥有大量可以获取的信息和想法。我在 stackoverflow.com 上找到了一个由 Jesse Buesking 于 2015 年 11 月 9 日发布的非常优雅的解决方案。该解决方案是用 Python 编写的,我将其转换成了 IDL。我发布此内容的目标是展示一种绘制边界框的绝佳方法,同时也作为一个在 IDL 和 Python 之间进行转换的示例。
function bounding_box, pts = pts, plot_results = plot_results
compile_opt IDL2
;获取 x 和 y 坐标 xs = pts[0,*] ys = pts[1,*]
;寻找边界点 Triangulate, xs, ys, triangles, hull, CONNECTIVITY=CONNECTIVITY ;将 hull 点排序为一个 [2,n] 数组 hull_points = [[xs[hull]]##1,[ys[hull]]##1] ;计算边缘角度 edges = hull_points[*,1:-1] - hull_points[*,0:-2] angles = atan(edges[1,*], edges[0,*]) pi2 = !DPI/2.
angles = abs(angles - floor(angles / pi2) * pi2) angles = angles[sort(angles)] angles = angles[UNIQ(angles)] ;寻找旋转矩阵 rotations = transpose([[cos(angles)],[cos(angles-pi2)],[cos(angles+pi2)],[cos(angles)]]) rotations = REFORM(rotations, [2,2,n_elements****(angles)])
;将旋转应用于 hull rot_points = fltarr( n_elements(hull_points)/2, 2, n_elements(angles))****
size_rot = size(rotations) for group = 0 , size_rot[3]-1 do begin for row = 0 , size_rot[2]-1 do begin rot_points[*,row,group] = TRANSPOSE(rotations[*,row,group]) # hull_points endfor endfor ;寻找边界点 min_x = min(rot_points[*,0,*],DIMENSION=1, /NAN) max_x = max(rot_points[*,0,*],DIMENSION=1, /NAN) min_y = min(rot_points[*,1,*],DIMENSION=1, /NAN) max_y = max(rot_points[*,1,*],DIMENSION=1, /NAN) ;寻找具有最佳面积的框 areas = (max_x - min_x) * (max_y - min_y) min_val = min(areas, best_idx) ;返回最佳框 x1 = max_x[best_idx] x2 = min_x[best_idx] y1 = max_y[best_idx] y2 = min_y[best_idx] r = rotations[*,*,best_idx] rval = fltarr(2,4) rval[*,0] = TRANSPOSE(TRANSPOSE([x1, y2]) # transpose(r)) rval[*,1] = TRANSPOSE(TRANSPOSE([x2, y2]) # transpose(r)) rval[*,2] = TRANSPOSE(TRANSPOSE([x2, y1]) # transpose(r)) rval[*,3] = TRANSPOSE(TRANSPOSE([x1, y1]) # transpose(r))
;显示结果 if KEYWORD_SET(plot_results) then begin* p = *SCATTERPLOT(xs,ys, SYM_COLOR='Red', SYM_FILL_COLOR='Red', SYM_FILLED=1,$ XRANGE=[min(rval[0,*])-1,max(rval[0,*])+1], YRANGE=[min(rval[1,*])-1,max(rval[1,*])+1])* p = *POLYGON(rval, /FILL_BACKGROUND, $ FILL_COLOR="light steel blue", PATTERN_ORIENTATION=45, $ PATTERN_SPACING=4, /DATA) endif return, rval end