Skip to content

在IDL中使用查找表实现快速角点检测:如何利用查找表提升速度

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/fast-corner-detection-using-a-look-up-table-in-idl-how-to-use-a-look-up-table-in-idl-for-improved-speed

19998 为本文评分:

3.0

在IDL中使用查找表实现快速角点检测:如何利用查找表提升速度

匿名 2014年1月23日,星期四

在IDL中实现算法通常涉及处理大型数据数组。一种可以加速IDL中某些算法的技术是利用预计算的查找表。这本质上允许绕过计算步骤,代价是增加内存使用。本例实现了FAST角点检测器算法。与许多其他角点检测器算法相比,这是一个简单的算法。每个像素都与围绕该像素形成圆环的16个其他像素进行比较。16个周围像素中的每一个都会被评估为与参考像素相似或不同。最后,如果参考像素至少有N个连续的周围像素被标记为明显更大或明显更小,则该像素被标记为角点。

为了测试速度,我使用以下代码作为参考。

  IDL> im=read_image(filepath('ohare.jpg', subdir=['examples','data']))
  % Loaded DLM: JPEG.
  IDL> im = reform(im[0,*,*])
  IDL> tic & x=fast_corner_detector(im) & toc
  % Compiled module: FAST_CORNER_DETECTOR.
  % Compiled module: ARRAY_INDICES.
  % Time elapsed: 42.885000 seconds.
  IDL> tic & z=fastcornerfinder(im, threshold=50, n_cont=12) & y=array_indices(z,where(z)) & toc
  % Compiled module: FASTCORNERFINDER.
  % Time elapsed: 2.6559999 seconds.
  IDL> array_equal(x,y)
  1
  IDL> help, x, y
  X               LONG      = Array[2, 4078]
  Y               LONG      = Array[2, 4078]

在这种情况下,速度比参考代码提高了16倍。这旨在说明一种使IDL代码运行更快的技术。我不保证此实现适用于任何特定目的。代码如下:

;+
; 参考:
;  http://www.edwardrosten.com/work/fast.html
;-
function FastCornerFinder, im, threshold=threshold, n_cont=n_cont
  compile_opt idl2, logical_predicate
  common fast_common, lookup, x_shift, y_shift

  ; 要查找的连续匹配数
  n = n_elements(n_cont) eq 0 ? 9b : byte(n_cont)
  if n lt 1 || n gt 16 then message, 'n_cont must be between 1 and 16'
  if n_elements(threshold) eq 0 then threshold = 50
  if n_elements(lookup) eq 0 then begin
    ; 一次性公共初始化
    ; 对于 r = 3,偏移量为
    x_shift = [-1, 0, 1, 2, 3, 3, 3, 2, 1, 0,-1,-2,-3,-3,-3,-2]
    y_shift = [-3,-3,-3,-2,-1, 0, 1, 2, 3, 3, 3, 2, 1, 0,-1,-2]
    ; 查找表返回设置的连续位的最大数量,使用位移位(ishft)。
    lookup = bytarr(65536)
    for i=0, 2^16-1 do begin
      x = i or ishft(i, 16)
      y = x
      for j=0, 15 do begin
        if y eq 0 then break
        y = x and ishft(y, 1)
      endfor
      lookup[i] = j
    endfor
  endif

  ; 创建一个数组,其中每一位表示圆环上16个位置中的每一个
  ; 是否与中心显著不同。测试明显更小或更大。
  bitsmaller = uintarr(size(im, /dimensions))
  bitbigger = uintarr(size(im, /dimensions))
  ; 确保像素为有符号,以便减法可以为负
  fim = fix(im)
  ; 遍历圆环上的16个位置
  for i=0, 15 do begin
    bitsmaller or= ishft(1us, i) * ((fim - shift(fim, x_shift[i], y_shift[i])) gt fix(threshold))
    bitbigger or= ishft(1us, i) * ((fim - shift(fim, x_shift[i], y_shift[i])) lt -fix(threshold))
  endfor

  ; 使用查找表转换为连续位的数量
  return, (lookup[bitsmaller] ge n) or (lookup[bitbigger] ge n)
end

无人机系统与进入商业空域的新前沿 让它下雪,让它下雪...