版权声明:本文为博主newston原创文章,允许转载,但转载必须保留原创链接。 https://blog.csdn.net/newston/article/details/88653981
遥感图像处理中,有时需要获取正射后影像的有效区域,背景值可以通过GDAL中的
函数获取。如果没有,可以通过设置来给定这个值。一般DOM背景无效值为0,DSM为-9999.00000。而海洋遥感数据背景无效值可能为-32767.00000。
首选,使用无效值将影像二值化,然后对二值数据进行边界追踪。其中最重要的是两点:1初始点的选取;2追踪规则(方向)。代码如下:
struct Point
{
double x,y;
};
template<class TT> vector<Point> GetImageArea(TT *pData, TT nodata, int width, int height)
{
//如果遥感影像过大,先采样,再返回
//首先将影像二值化
unsigned char *pBinaryData= new unsigned char[(width)*(height)];
memset(pBinaryData, sizeof(unsigned char)*(width)*(height), 255);//二值化时,255背景区域,0位有效区域
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (pData[i*width + j] != nodata)
pBinaryData[i*width + j] = 0;
}
}
//int direction[8][2] = { { -1, 1 }, { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 } };//普通图像左下角为(0,0)
int direction[8][2] = { { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 }, { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 } };//遥感图像右上角为(0,0)
//边界起始点,待处理的当前点,当前点的邻域点
Point startP, currentP, neighborP;
vector<Point> vPoints = vector<Point>();
//是否当前点与起始边界点重合的标志变量
int findStartPoint = 0;
//循环变量,图像坐标
int i, j;
for (i = 0; i<height; i++){
for (j = 0; j<width; j++){
//找到起始边界点
if (pBinaryData[i*width + j] == 0){
startP.x = j;
startP.y = i;
vPoints.push_back(startP);
findStartPoint = 1;
break;
}
}
//已经找到起始边界点
if (findStartPoint)
break;
}
//边界跟踪
//从初始点开始跟踪
currentP.x = startP.x;
currentP.y = startP.y;
//邻域点是否边界点标志变量
int isContourP;
//开始方向
int startDirect = 0;
//0表示还没有返回最初的边界起始点
findStartPoint = 0;
while (findStartPoint == 0){
isContourP = false;
while (isContourP == false){
neighborP.x = currentP.x + direction[startDirect][0];
neighborP.y = currentP.y + direction[startDirect][1];
//搜索到邻域点
//如果邻域点超出范围
if (neighborP.x >= 0 && neighborP.y >= 0 && neighborP.x < width && neighborP.y < height && pBinaryData[int(neighborP.y)*width + int(neighborP.x)] == 0){
isContourP = true;
currentP.x = neighborP.x;
currentP.y = neighborP.y;
if (currentP.x == startP.x&¤tP.y == startP.y)
findStartPoint = true;//回到边界起始点了
vPoints.push_back(currentP);
//扫描方向逆时针旋转90度
startDirect -= 2;
if (startDirect < 0)
startDirect += 8;
}
else{
//扫描方向顺时针旋转45度
startDirect++;
if (startDirect == 8)
startDirect = 0;
}
}
}
if (pBinaryData != NULL)
{
delete pBinaryData;
pBinaryData= NULL;
}
return vPoints ;
}
参见