IDL自定义滑动窗口函数

15 篇文章 9 订阅

前言

    许多地表参数反演算法中是以整景影像中的每个小窗口为单位进行计算。这时候就需要对整景影像划分为数个固定窗口大小影像。以下函数实现输入想要设定窗口的大小,影像列行数,返回一个分块影像的左上角和右下角坐标的查找表数组。有这样一个数组,无论是影像计算还是裁剪深度学习样本都可以适用。
    之后会写一个有重叠的分块影像函数即滑动窗口。(已更新:2020-5-22-23:22)

规则窗口(无重叠)

2020-5-22-23:21 更新 无需生成lut版本

;自定义分隔影像函数,规则分隔
;wz 为窗口大小
;clos 为 影像列数
;rows 为影像行数

function block2, cols, rows, wz
  compile_opt idl2
  param_number = n_params()
  if param_number eq 3 then begin
  
    wz = wz
    rows = rows
    cols = cols
    
    if wz gt rows or wz gt cols then begin
      print, 'WindowSize gt imageSize'
      return, 0
    endif
     
    if rows mod wz eq 0 then begin        ; 计算行列方向的窗口数量
      row_wz = rows / wz                  
    endif else begin
      row_wz = floor(rows/wz) + 1
    endelse
  
    if cols mod wz eq 0 then begin
      col_wz = cols / wz
    endif else begin
      col_wz = floor(cols/wz) + 1
    endelse
    
    block_data = intarr(4, row_wz * col_wz)
  
    num = 0
    for i = 0,(row_wz - 1) do begin
      for j = 0,(col_wz - 1) do begin
        block_data[0, num] = wz * j > 0           ; 左上列坐标
        block_data[1, num] = wz * i > 0
        block_data[2, num] = wz* (j + 1) - 1      ; 右下列坐标
        block_data[3, num] = wz* (i + 1) - 1
      
        max_col = wz* (j + 1) - 1
        max_row = wz* (i + 1) - 1
        
        if max_col ge cols and max_row lt rows then begin
          block_data[0, num] = cols - wz          ; 左上列坐标
          block_data[1, num] = wz * i > 0
          block_data[2, num] = cols - 1           ; 右下列坐标
          block_data[3, num] = wz * (i + 1) - 1
        endif
        if max_row ge rows and max_col lt cols then begin
          block_data[0, num] = wz * j > 0            ; 左上列坐标
          block_data[1, num] = rows - wz
          block_data[2, num] = wz * (j + 1) - 1      ; 右下列坐标
          block_data[3, num] = rows - 1
        endif
        if max_row ge rows and max_col ge cols then begin
          block_data[0, num] = cols - wz     ; 左上列坐标
          block_data[1, num] = rows - wz
          block_data[2, num] = cols - 1      ; 右下列坐标
          block_data[3, num] = rows - 1
        endif
        num = num + 1 
      endfor
    endfor
  
    return, block_data
    
  endif else begin
    print, 'Please check Function params'
    return, 0
  endelse
  
end

用来裁剪测试一下,窗口大小为100,没有问题。
在这里插入图片描述

滑动窗口(有重叠)

2020-5-22-23:22更新
沿着行或列方向进行步长为1行像元的滑动,列或行之间进行步长为窗口大小的无重叠滑动。

;自定义影像滑动窗口
;row 影像行数
;col 影像列数
;wz 滑动窗口的大小
;dim 滑动方向的维度 1代表沿列方向(上下) 2代表沿行方向(左右)

function image_slide, cols, rows, wz, dim = dim
  compile_opt idl2
  param_number = n_params()
  if param_number eq 3 and (dim eq 1 or dim eq 2) then begin
    
    rows = rows
    cols = cols
    wz = wz 
    step = 1
    
    if wz gt rows or wz gt cols then begin
      print, 'WindowSize ge imageSize'
      return, 0
    endif
    
    case 1 of 
      dim eq 1 : begin          
        row_num = floor((rows - wz) / step) + 1
        col_num = floor(cols / wz) + 1            ; 行列方向的窗口个数
        slide_data = intarr(4, row_num * col_num) ; 用于存放滑动窗口在影像的左上右下列行坐标
        counts = row_num * col_num                ; 记录窗口的数量
      
        num = 0                                   ; 计数器 逐行写入数组
        for i = 0, (col_num * wz - 1), wz do begin    ; 沿列方向进行滑动, 列之间的窗口无重叠  -1是为了防止i溢出列数
          for j = 0, (rows - wz), step do begin   
             slide_data[0, num] = i               ; 左上列坐标
             slide_data[1, num] = j 
             slide_data[2, num] = i + wz - 1      ; 右下列坐标
             slide_data[3, num] = j + wz - 1    
             
             max_col = i + wz - 1
             max_row = j + wz - 1    
             if max_col ge cols and max_row lt rows then begin      ; 对不满足一个窗口大小的列边缘像素进行反向取窗口
               slide_data[0, num] = cols - wz    ; 左上列坐标
               slide_data[1, num] = j 
               slide_data[2, num] = cols - 1     ; 右下列坐标
               slide_data[3, num] = j + wz - 1
             endif
             if max_row ge rows and max_col lt cols then begin
               slide_data[3, num] = rows - 1
               slide_data[1, num] = rows - wz 
             endif
             if max_col ge cols and max_row ge rows then begin      ; 对不满足一个窗口大小的列边缘像素进行反向取窗口
               slide_data[0, num] = cols - wz    ; 左上列坐标
               slide_data[1, num] = rows - wz 
               slide_data[2, num] = cols - 1     ; 右下列坐标
               slide_data[3, num] = rows - 1
             endif
             num = num + 1 
          endfor
        endfor
                   end
      dim eq 2 : begin    
        col_num = floor((cols - wz) / step) + 1
        row_num = floor(rows / wz) + 1             ; 行列方向的窗口个数
        slide_data = intarr(4, row_num * col_num)  ; 用于存放滑动窗口在影像的左上右下列行坐标
        counts = row_num * col_num                 ; 记录窗口的数量
    
        num = 0                                    ; 计数器 逐行写入数组
        for i = 0, (row_num * wz - 1), wz do begin 
          for j = 0, (cols - wz), step do begin
            slide_data[0, num] = j                 ; 左上列坐标
            slide_data[1, num] = i
            slide_data[2, num] = j + wz - 1        ; 右下列坐标
            slide_data[3, num] = i + wz - 1
            ;print,j
    
            max_col = j + wz - 1
            max_row = i + wz - 1
    
            if max_col ge cols and max_row lt rows then begin      ; 对不满足一个窗口大小的列边缘像素进行反向取窗口
              slide_data[0, num] = rows - wz      ; 左上列坐标
              slide_data[1, num] = i
              slide_data[2, num] = rows - 1       ; 右下列坐标
              slide_data[3, num] = i + wz - 1
            endif
            if max_row ge rows and max_col lt cols then begin
              slide_data[3, num] = rows - 1
              slide_data[1, num] = rows - wz
            endif
            if max_col ge cols and max_row gt rows then begin      ; 对不满足一个窗口大小的列边缘像素进行反向取窗口
              slide_data[0, num] = rows - wz      ; 左上列坐标
              slide_data[1, num] = cols - wz
              slide_data[2, num] = rows - 1       ; 右下列坐标
              slide_data[3, num] = cols - 1
            endif
            num = num + 1
          endfor
        endfor
                 end
    endcase
    return, slide_data
    
  endif else begin   
    print, 'Please check Function params'
    return, 0
  endelse   
  
end

测试一下,输出的坐标没问题。对于不够一个窗口大小的边缘列进行反向滑动。

ENVI> image_slide(110 , 41, 40, dim = 1)
       0       0      39      39
       0       1      39      40
      40       0      79      39
      40       1      79      40
      70       0     109      39
      70       1     109      40

窗口大小为200,裁剪测试一下。
在这里插入图片描述
动图感受下滑动的过程(在普通图像中原点坐标是在左下角,所以自下往上进行滑动)。

在这里插入图片描述

使用方法
(1)影像计算

这里测试了一个8192*8000的数组,使得每一块分块影像的值等于他的分块序号。

pro block_test
  compile_opt idl2
  e = envi()
 
  data = make_array(8192,8000, type=2)
  
  subs = block2(8192, 8000, 500) ; 调用block函数对影像分块
  dim = size(subs, /dimensions)
  count = dim[1] ; 获取分块图像的数量
  
  for i = 0,count-1 do begin
    sub = subs[*, i]  ; 获取第一个分块影像的 左上角 右上角 行 列 坐标   
    data[sub[0]:sub[2], sub[1]:sub[3]] = i
  endfor
  
  tempfn = e.GetTemporaryFilename()
  raster = e.CreateRaster(tempfn, data)
  raster.save
  view = e.GetView()
  layer = view.CreateLayer(raster)
  
end

运行结果如下,影像分块值按行依次递增,说明分块没有错误。
在这里插入图片描述

(2)影像裁剪
pro crop_image
  compile_opt idl2
  
  img = read_image('E:\Manual instructions\image\apple.jpg')
  ;img_vis = image(img)
  
  img = reform(img[1,*,*])
  
  dim = size(img, /dimensions)
  rows = dim[1]
  cols = dim[0]
  
  subs = image_slide(cols, rows, 251, dim=1)
  counts = n_elements(subs) / 4
 
  for i = 0, counts - 1 do begin
    sub = subs[*, i] 
    img_out = img[sub[0]:sub[2], sub[1]:sub[3]] 
    write_jpeg, 'E:\Manual instructions\image\out3\' + 'image_crop' + string(i) + '.jpg', img_out
  endfor
 
end
lut版本

lut文件在IDL目录下生成。(起初生成lut文件是为了方便调试代码,实际上根本不适用,假如影像够大或者窗口过小,生成的txt文件大小能到G的量级~)

function block, wz, cols, rows
  compile_opt idl2  
  cd, getenv('idl_tmpdir')
  wz = wz
  rows = rows
  cols = cols
  
  if rows mod wz eq 0 then begin
    row_wz = rows / wz
  endif else begin
    row_wz = round(rows/wz) + 1
  endelse
  
  if cols mod wz eq 0 then begin
    col_wz = cols / wz
  endif else begin
    col_wz = round(cols/wz) + 1
  endelse
    
  lut = 'lut.txt'
  openw, lun, lut, /get_lun
  for i = 0,row_wz-1 do begin
    for j = 0,col_wz-1 do begin
      max_col = wz*(j+1) - 1
      max_row = wz*(i+1) - 1
      if max_col gt cols then max_col = cols - 1
      if max_row gt rows then max_row = rows - 1
      printf, lun, wz*j>0, wz*i>0, max_col, max_row
    endfor
  endfor
  free_lun,lun

  nl = file_lines(lut)
  lutdata = intarr(4, nl)
  openr, lun, lut, /get_lun
  readf, lun, lutdata
  free_lun, lun

  return, lutdata
  
end
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值