主要就是用到了两个容器,一个vector,一个list。其中vector用来存贮查找到的所有类型相同的区域,list用于暂时保存找到的类型相同的点,然后以找到的点为新的中心,查找该点的八方向,用来循环查找新的类型相同的点
代码如下:
#include<iostream>
#include<gdal_priv.h>
#include<list>
#include<vector>
using namespace std;
struct MyPoint
{
int x;
int y;
MyPoint& operator=(MyPoint& other)
{
x=other.x;
y=other.y;
return *this;
}
MyPoint(int x1,int y1)
{
x=x1;
y=y1;
}
MyPoint(){};
};
vector<CPoint> m_vecReoginPt;//将同一个区域的点存在这个容器中
int Flag=0;
int main()
{
void RegionGrow(unsigned char* pInImg,unsigned char* GrowFlag, int Width,int Height,int i, int j);
void SetRed(unsigned char* pOutImg,int Width, int Height);
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
GDALDataset* pInDataset = (GDALDataset*) GDALOpen("SingleBand.tif",GA_ReadOnly);
int Width = pInDataset->GetRasterXSize();
int Height = pInDataset->GetRasterYSize();
int BandCount = pInDataset->GetRasterCount();
GDALRasterBand* pInRasterBand;
GDALDriver* pOutDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
GDALDataset* pOutDataset = pOutDriver->Create("Out.tif",Width, Height, BandCount, GDT_Byte, NULL);
GDALRasterBand* pOutRasterBand;
unsigned char** data = new unsigned char* [BandCount]();
for(int i = 0; i < BandCount; ++i)
data[i] = new unsigned char [Width * Height]();
//memset( data, 0, sizeof(unsigned char) * BandCount * Width * Height);
unsigned char** pOutImg = new unsigned char* [BandCount]();
for(int i = 0; i < BandCount; ++i)
pOutImg[i] = new unsigned char [Width * Height]();
for(int i = 0; i < BandCount ; ++i)
{
pInRasterBand = pInDataset->GetRasterBand(i+1);
pOutRasterBand = pOutDataset->GetRasterBand(i+1);
CPLErr err = pInRasterBand->RasterIO( GF_Read, 0, 0, Width, Height, data[i], Width, Height, GDT_Byte, NULL, NULL);
if(err != CE_None)
cout<<"写入失败"<<endl;
unsigned char* GrowFlag = new unsigned char[Width * Height];
memset(GrowFlag, 0, sizeof(unsigned char)*Width*Height);
memcpy(pOutImg[i], data[i], sizeof(unsigned char) * Width * Height);
for(int k=0; k<Height; ++k)
for(int j=0; j<Width; ++j)
{
if(data[i][k*Width+j]==255 && GrowFlag[k*Width+j]==0)
{
RegionGrow(data[i], GrowFlag, Width, Height, k, j);
if(m_vecReoginPt.size()>1)
{
// cout<<m_vecReoginPt.size()<<endl;
SetRed(pOutImg[i], Width, Height);
cout<<".";
}
}
}
err=pOutRasterBand->RasterIO( GF_Write, 0, 0, Width, Height, pOutImg[i], Width, Height, GDT_Byte, NULL, NULL);
if(err != CE_None)
cout<<"图像生成失败"<<endl;
}
GDALClose(pOutDataset);
GetGDALDriverManager()->DeregisterDriver(pOutDriver);
cout<<"处理结束"<<endl;
getchar();
return 0;
}
void RegionGrow(unsigned char* pInImg,unsigned char* GrowFlag, int Width,int Height,int k, int j)
{
int direction[8][2] = {-1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, -1, 0};
list<MyPoint>ptlist;//将符合条件的点存入链表,用于循环查找类似的点
ptlist.push_back(MyPoint(k,j));
int y, x, index, y2, x2;
index = k * Width + j;
GrowFlag[index] = 1; //标记像素已遍历过
m_vecReoginPt.clear();
while(1)
{
if(ptlist.size()==0)
break;
x = ptlist.front().x;
y = ptlist.front().y;
ptlist.pop_front(); //输出第一个元素,判读其邻域
m_vecReoginPt.push_back(MyPoint(x,y));
for(int i=0; i<8; i++)
{
x2 = x + direction[i][0];
y2 = y + direction[i][1];
if(y2<0 || y2>=Width || x2<0 || x2>=Height) //超出图像边界,则返回
continue;
index = x2*Width + y2;
if(pInImg[index]==0 || GrowFlag[index]==1) //像素值与连通域值不相等或已搜寻过,返回
continue;
// cout<<(int)pInImg[index]<<endl;
GrowFlag[index] = 1;
ptlist.push_back(MyPoint(x2, y2)); //连通点存入链表
}
}
}
void SetRed(unsigned char* pOutImg,int Width, int Height)
{
//为了显示颜色,这里使用的是三波段图像
//用于设置每个波段不同的像素值
//第一波段像素值变为65,第二波段变为136,第三波段变为211
//Flag/5中5指的是有5个检测出来的区域
if(Flag/5==0)
{
int i,j;
while (m_vecReoginPt.size()!=0)
{
i=m_vecReoginPt.back().x;
j=m_vecReoginPt.back().y;
pOutImg[i * Width + j] = 65;
m_vecReoginPt.pop_back();
}
Flag++;
}
else if(Flag/5==1)
{
int i,j;
while (m_vecReoginPt.size()!=0)
{
i=m_vecReoginPt.back().x;
j=m_vecReoginPt.back().y;
pOutImg[i * Width + j] = 136;
m_vecReoginPt.pop_back();
}
Flag++;
}
else if(Flag/5==2)
{
int i,j;
while (m_vecReoginPt.size()!=0)
{
i=m_vecReoginPt.back().x;
j=m_vecReoginPt.back().y;
pOutImg[i * Width + j] = 211;
m_vecReoginPt.pop_back();
}
Flag++;
}
}
现在opencv用得比较多,所以改写为使用Mat类的区域增长
void RegionGrow(Mat pInImg,Mat GrowFlag, int Width,int Height,int k, int j)
{
int direction[8][2] = {-1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, -1, 0};
list<MyPoint>ptlist;//将符合条件的点存入链表,用于循环查找类似的点
ptlist.push_back(MyPoint(k,j));
int y, x, index, y2, x2;
// index = k * Width + j;
// GrowFlag[index] = 1; //标记像素已遍历过
GrowFlag.at<uchar>(k,j) = 1;
m_vecReoginPt.clear();
while(1)
{
if(ptlist.size()==0)
break;
x = ptlist.front().x;
y = ptlist.front().y;
ptlist.pop_front(); //输出第一个元素,判读其邻域
m_vecReoginPt.push_back(MyPoint(x,y));
for(int i=0; i<8; i++)
{
x2 = x + direction[i][0];
y2 = y + direction[i][1];
if(y2<0 || y2>=Width || x2<0 || x2>=Height) //超出图像边界,则返回
continue;
// index = x2*Width + y2;
if(pInImg.at<uchar>(x2,y2) == 0 || GrowFlag.at<uchar>(x2,y2)==1) //像素值与连通域值不相等或已搜寻过,返回
continue;
// cout<<(int)pInImg[index]<<endl;
GrowFlag.at<uchar>(x2,y2) = 1;
ptlist.push_back(MyPoint(x2, y2)); //连通点存入链表
}
}
}