跳转至

使用 ENVI ROI 进行基础特征提取

原文链接: https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/basic-feature-extraction-with-envi-rois

18220 为本文评分:

4.0

使用 ENVI ROI 进行基础特征提取

匿名 2016年8月9日,星期二

ENVI 特征提取模块允许用户从图像中提取特定特征。第一步是将图像分割成若干区域。完成后,你就可以利用这些区域的空间和光谱特性来提取目标。

在这个例子中,让我们在这张来自维基百科"交通信号灯"页面的图片中找出交通信号灯。 https://en.wikipedia.org/wiki/Traffic_light

第一步是使用 ENVI 的 FXSegmention 任务进行分割。我设置了 85 的合并值和 95 的分段值,这是我在 ENVI 中通过手动检查为此数据集确定的好值。

这些分段创建后,可以转换为 ENVI ROI(感兴趣区域)。在本例中,我使用了 ImageThresholdToROI 任务。

接下来,我们可以查看每个区域的特性,并创建一个评分算法来评估每个 ROI 是我们寻找的目标的可能性。我觉得寻找红色并不可行,因为当信号灯颜色变化时,该算法就会失效。所以,相反,由于我们想要找到的目标区域是圆形的,让我们据此来寻找。

我们知道关于圆形可以检查两点:它们是对称的,并且随着圆半径的增加,其面积和周长之间存在特定关系。首先,我为每个 ROI 设置了像素坐标,使得原点成为该区域的平均 x/y 位置。我还计算了每个像素到原点的距离。

x_avg = total(addr[0,*])/n_pix

y_avg = total(addr[1,*])/n_pix

x_coords = reform(addr[0,*] - x_avg)

y_coords = reform(addr[1,*] - y_avg)

power = (x_coords^2 +y_coords^2)

为了测试对称性,取 x 和 y 的最小值和最大值,并将它们相加。这个值越接近于零,ROI 就越对称。

abs(max(x_coords)+min(x_coords))+ abs(max(y_coords)+min(y_coords))

为了测试区域的圆形程度,我们可以测试到原点的距离如何增加的斜率。由于我们知道面积和周长之间的这种关系,我们可以找到我们期望的斜率。

斜率 =  = 1/3

因为对称性的高分是零,让我们对这个度量使用相同的评分系统。

line = linfit(lindgen(n_elements(power)),power[sort(power)])

score = abs(line[1]-.3333)

最后一步是分配权重(我使用了权重 1)并计算总体得分。提取交通信号灯(或任何其他圆形)的完整代码可以在本文底部找到。

这种特征提取方法需要时间来开发和完善,这让我为那些需要快速开发特征提取模型的人带来了一些令人兴奋的消息。我们内部一直在开发另一种称为 MEGA 的特征提取方法,可通过我们的 定制解决方案组 获得。这是一种机器学习工具,它接收你正在寻找的特征的示例,然后生成该特征在图像中可能位置的的热力图。

请继续关注,我们将深入探讨这种新方法与经典特征提取技术(如上面我介绍的方法)的比较。

pro traffic_light_fx

compile_opt idl2

file = 'C:\Blogs\FX_to_ROIs\Stevens_Creek_Blvd_traffic_light.jpg'

e=envi()

view = e.GetView()

;File was created from FX segmentation only. High Edge and Merge settings.

t0 = ENVITask('FXSegmentation')

raster = e.Openraster(file)

t0.INPUT_RASTER = raster

layer = view.CreateLayer(raster)

t0.OUTPUT_RASTER_URI = e.GetTemporaryFilename('.dat')

t0.MERGE_VALUE = 85.0

t0.SEGMENT_VALUE = 90.0

t0.Execute

t1 = envitask('ImageThresholdToROI')

t1.INPUT_RASTER = t0.OUTPUT_RASTER

t1.OUTPUT_ROI_URI = e.GetTemporaryFilename('.xml')

loop_max = max((t0.OUTPUT_RASTER).GetData(), MIN=loop_min)

num_areas = loop_max-loop_min+1

t1.ROI_NAME = 'FX_Area_' + strtrim(indgen(num_areas)+1, 2)

t1.ROI_COLOR = transpose([[bytarr(num_areas)],[bytarr(num_areas)],[bytarr(num_areas)+255]])

arr = indgen(num_areas) + loop_min

t1.THRESHOLD = transpose([[arr],[arr],[intarr(num_areas)]])

t1.execute

allROIs = t1.OUTPUT_ROI

c_scores = []

c_loc = []

for i=0, n_elements(allROIs)-1 do begin

addr = (allROIs[i]).PixelAddresses(raster)

n_pix = n_elements(addr)/2

if n_pix gt 60 then begin

x_avg = total(addr[0,*])/n_pix

y_avg = total(addr[1,*])/n_pix

x_coords = reform(addr[0,*] - x_avg)

y_coords = reform(addr[1,*] - y_avg)

power = (x_coords^2 + y_coords^2)

line = linfit(lindgen(n_elements(power)),power[sort(power)])

this_score = abs(max(x_coords) + min(x_coords)) + max(y_coords) + min(y_coords)) + abs(line[1]-.3333)

c_scores = [c_scores, this_score]

c_loc = [c_loc, i]

endif

endfor

idx = sort(c_scores)

sort_scores = c_scores[idx]

sort_locs = c_loc[idx]

for i=0, 3 do begin

lightROI = allROIs[sort_locs[i]]

!null = layer.AddRoi(lightROI)

endfor

end

警惕菱形关系:多重类继承的危险 使用 Motion JPEG2000 压缩高光谱数据