如何使用空间掩码限制栅格处理范围?

时间:2014-02-24 22:15:13

标签: image matlab image-processing shapefile arcpy

我试图限制MATLAB中的栅格处理,使其仅包含shapefile边界内的区域,类似于ArcGIS Spatial Analyst函数使用mask的方式。以下是我正在使用的一些(可重现的)样本数据:

这是我用来计算NDVI

的MATLAB脚本
file = 'C:\path\to\doi1m2011_41111h4nw_usda.tif';
[I R] = geotiffread(file);
outputdir = 'C:\output\'

% Calculate NDVI
NIR = im2single(I(:,:,4));
red = im2single(I(:,:,1));

ndvi = (NIR - red) ./ (NIR + red);
double(ndvi);
imshow(ndvi,'DisplayRange',[-1 1]);

% Stretch to 0 - 255 and convert to 8-bit unsigned integer
ndvi = floor((ndvi + 1) * 128); % [-1 1] -> [0 256]
ndvi(ndvi < 0) = 0;             % not really necessary, just in case & for symmetry
ndvi(ndvi > 255) = 255;         % in case the original value was exactly 1
ndvi = uint8(ndvi);             % change data type from double to uint8

% Write NDVI to .tif file (optional)
tiffdata = geotiffinfo(file);
outfilename = [outputdir 'ndvi_' 'temp' '.tif'];  
geotiffwrite(outfilename, ndvi, R, 'GeoKeyDirectoryTag', tiffdata.GeoTIFFTags.GeoKeyDirectoryTag) 

下图说明了我想用MATLAB完成的工作。在本例中,我使用ArcGIS raster calculator(Float(Band4-Band1)/ Float(Band4 + Band1))在右侧生成NDVI。我还将研究区域shapefile指定为mask in the environment settings

enter image description here

问题:

如何使用多边形shapefile作为空间蒙版来限制MATLAB中的栅格处理范围,以复制图中显示的结果?

我的尝试失败

roipolypoly2mask,虽然我似乎无法正确应用这些功能(考虑到这些是空间数据)以产生所需的效果。

修改

我尝试了以下方法将shapefile转换为蒙版,但没有成功。不知道我在哪里错了...

s = 'C:\path\to\studyArea.shp'

shp = shaperead(s)
lat = [shp.X];
lon = [shp.Y];

x = shp.BoundingBox(2) - shp.BoundingBox(1)
y = shp.BoundingBox(3) - shp.BoundingBox(1) 

x = poly2mask(lat,lon, x, y)

错误讯息:

Error using poly2mask
Expected input number 1, X, to be finite.

Error in poly2mask (line 49)
validateattributes(x,{'double'},{'real','vector','finite'},mfilename,'X',1);

Error in createMask (line 13)
x = poly2mask(lat,lon, x, y)

2 个答案:

答案 0 :(得分:1)

这里有三个步骤,我将为此创建3个函数:

  1. 计算完整输入图像的NDVI:ndvi = comp_ndvi(nir, red)
  2. 从shapefile计算掩码:mask = comp_mask(shape)
  3. 合并NDVI和面具:output = combine_ndvi_mask(ndvi, mask)
  4. 您的问题中包含comp_ndvi()的代码。 combine_ndvi_mask()的代码取决于您要对遮罩区域执行的操作;如果你想让它们变成白色,它可能看起来像:

    function output = combine_ndvi_mask(ndvi, mask)
    output = ndvi;
    output(~mask) = 255;
    end
    

    comp_mask()中,您需要使用poly2mask()将多边形顶点转换为栅格蒙版。为了在这里提供帮助,我需要知道你已经拥有了什么。你有顶点加载到MATLAB?你用poly2mask试过了什么?

答案 1 :(得分:1)

您可以通过以下方式阅读感兴趣的区域:

roi = shaperead('study_area_shapefile/studyArea.shp');

砍掉尾随的NaN:

rx = roi.X(1:end-1);
ry = roi.Y(1:end-1);

如果你的shapefile中有多个多边形,它们会被NaN分开,你必须单独处理它们。

然后使用sat-image空间参考中的worldToIntrinsic方法将多边形点转换为图像坐标:

[ix, iy] = R.worldToIntrinsic(rx,ry);

这假设两个坐标系都相同。

然后你可以通过以下方式制作面具:

mask = poly2mask(ix,iy,R.RasterSize(1),R.RasterSize(2));

您可以在进行任何计算之前使用原始多层图像上的蒙版:

I(repmat(~mask,[1,1,4])) = nan;

或者通过以下方式在单层(即红色)上使用它

red(~mask) = nan;

如果区域非常小,将掩蔽图像转换为稀疏矩阵可能是有益的(对于存储器和计算能力)。我没有尝试,如果这有任何速度差异。

red(~mask) = 0;
sred = sparse(double(red));

不幸的是,稀疏的matrizes只能用双打,所以你的uint8需要在转换之前。

通常,您应该从图像中裁剪ROI。查看对象“roi”和“R”以查找有用的参数和方法。我没有在这里做过。

最后我的脚本版本,稍作其他一些改动:

file = 'doi1m2011_41111h4nw_usda.tif';
[I R] = geotiffread(file);
outputdir = '';

% Read Region of Interest
roi = shaperead('study_area_shapefile/studyArea.shp');
% Remove trailing nan from shapefile
rx = roi.X(1:end-1);
ry = roi.Y(1:end-1);
% convert to image coordinates
[ix, iy] = R.worldToIntrinsic(rx,ry);
% make the mask
mask = poly2mask(ix,iy,R.RasterSize(1),R.RasterSize(2));
% mask sat-image
I(repmat(~mask,[1,1,4])) = 0;

% convert to sparse matrizes
NIR = sparse(double(I(:,:,4)));
red = sparse(double(I(:,:,1)));
% Calculate NDVI
ndvi = (NIR - red) ./ (NIR + red);
% convert back to full matrizes
ndvi = full(ndvi);
imshow(ndvi,'DisplayRange',[-1 1]);

% Stretch to 0 - 255 and convert to 8-bit unsigned integer
ndvi = (ndvi + 1) / 2 * 255; % [-1 1] -> [0 255]
ndvi = uint8(ndvi);          % change and round data type from double to uint8 

% Write NDVI to .tif file (optional)
tiffdata = geotiffinfo(file);
outfilename = [outputdir 'ndvi_' 'temp' '.tif'];  
geotiffwrite(outfilename, ndvi, R, 'GeoKeyDirectoryTag', tiffdata.GeoTIFFTags.GeoKeyDirectoryTag);
mapshow(outfilename);