链码的优越性在于:对于上一个链码方向逆时针旋转120度,开始查找下一个方向,然后顺时针一次查找八个方向,直到找到符合条件的点,再开始下一轮的查找
代码:
#include <iostream>
#include <string>
#include "gdal_priv.h"
using namespace std;
/********************************************************
* 根据容差判断两像素颜色是否相近
* 参数c1、c2为两种颜色信息,delta为容差
********************************************************/
bool IsSameColor(unsigned char c1, unsigned char c2, int delta)
{
return ( abs(c1 - c2) < delta);
}
/*******************************************************************************
* 寻找下一轮廓点
* 参数:imageBuf为要搜索的图形,w、h为图像尺寸,x、y为当前边界点坐标
n为上一轮廓点到当前轮廓点的链码,color为区域的颜色
*******************************************************************************/
int NextPoint(unsigned char** imageBuf, int w, int h, int y, int x, int n, unsigned char color)
{
int directData[8][2] //链码向量表
={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};
int startIndex = n + 3 + 8; //确定起始链码,对于上一个链码方向旋转120度,开始查找下一个方向,然后顺时针一次查找八个方向,直到找到符合条件的点
int i;
//对邻域进行搜索
for(i = 0;i <= 7;i++)
{
int index = (startIndex - i) % 8;
int nx = x + directData[index][0];
int ny = y + directData[index][1];
//判断边界点
if(nx >= 0 && nx < w && ny >= 0 && ny < h)
if( IsSameColor(imageBuf[ny][nx],color,1) )
{
return index;
}
}
//如果没找到新的边界点返回错误信息
return 9;
}
/****************************************************************
* 单区域的轮廓跟踪
* 参数:imageBuf为跟踪的图像,w、h为图像尺寸,x、y为搜索起始点,
* n为起始链码,color为区域颜色
****************************************************************/
int* SingleTrack(unsigned char** imageBuf, int w, int h, int y, int x, int n, unsigned char color)
{
int directData[8][2] = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};//链码向量表
int* track = new int[9999]; //为链码表开辟存储单元
int k = 0;
int nx = x,ny = y;
int index = n;
//保存起始点坐标
track[0] = y;
track[1] = x;
//循环搜索下一边界点 直到回到起始点
do
{
index = NextPoint(imageBuf,w,h,ny,nx,index,color);
if(index == 9) break;
track[k+3] = index;
k++;
nx += directData[index][0];
ny += directData[index][1];
}
while( nx!=x || ny!=y );
track[2] = k; //记录链码表的长度
return track;
}
//用链码表追踪图像的轮廓
//track为链码表,track[0],track[1]分别存放的是起始轮廓的坐标(y,x),track[2]存放链码表的长度,后面的为轮廓上每个点的链码值
//一定要注意x,y的本别对应关系,y对应Height,x对应Width,这一点很容易出现内存异常
int main()
{
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
string str1="1.1.bmp";
string str2="1.2.bmp";
GDALDataset* pInDataset=(GDALDataset*)GDALOpen(str1.data() ,GA_ReadOnly);
if(pInDataset == nullptr)
{
cout<<"未找到输入图像"<<endl;
getchar();
return 1;
}
int Width=pInDataset->GetRasterXSize();
int Height = pInDataset->GetRasterYSize();
int band = pInDataset->GetRasterCount();
//double dGeoTrans[6]={};
//pInDataset->GetGeoTransform(dGeoTrans);
//const char* cProjectionRef = pInDataset->GetProjectionRef();
unsigned char* Image = new unsigned char[Width * Height];
memset(Image,0,sizeof(unsigned char) * Width * Height);
GDALRasterBand* pRasterBand = pInDataset->GetRasterBand(1);
CPLErr err=pRasterBand->RasterIO(GF_Read ,0 ,0 ,Width ,Height ,Image ,Width ,Height ,GDT_Byte ,0 ,0);
unsigned char** ImageBuf = new unsigned char* [Height];
for(int i = 0;i < Height;++i)
{
ImageBuf[i] = new unsigned char[Width];
memset(ImageBuf[i],0,sizeof(unsigned char) * Width);
}
//int a ,b;
//int flag = 0;
for(int i = 0;i < Height;++i)
{
for(int j = 0;j < Width;++j)
{
ImageBuf[i][j] = Image[i * Width + j];
//if(flag == 0)
//{
// if(ImageBuf[i][j] == 255)
//}
}
}
//为检测一张特定的图像,设定的(0,794)该坐标点。为任意轮廓即可
unsigned char color = ImageBuf[0][794];
int* track = SingleTrack(ImageBuf,Width,Height,0,794,0,color);
//for(int i = 0;i < track[2];++i)
//{
// cout<<track[i]<<endl;
//}
unsigned char* OutImage = new unsigned char[Width * Height];
memset(OutImage,0,sizeof(unsigned char) * Width * Height);
int directData[8][2] = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};//链码向量表
int y = track[0];
int x = track[1];
for(int i = 3;i < track[2];++i)
{
OutImage[y * Width + x] = 255;
x += directData[track[i]][0];
y += directData[track[i]][1];
}
GDALDriver* pOutDriver = GetGDALDriverManager()->GetDriverByName("BMP");
GDALDataset* pOutDataset = pOutDriver->Create(str2.data() ,Width ,Height ,1 ,GDT_Byte ,NULL);
GDALRasterBand* pOutRasterband=pOutDataset->GetRasterBand(1);
pOutRasterband->RasterIO(GF_Write ,0 ,0 ,Width ,Height ,OutImage ,Width ,Height ,GDT_Byte ,0 ,0);
delete Image;
for(int i = 0;i < Height;++i)
{
delete ImageBuf[i];
}
delete ImageBuf;
delete OutImage;
GDALClose(pInDataset);
GDALClose(pOutDataset);
GetGDALDriverManager()->DeregisterDriver(pOutDriver);
system("pause");
return 0;
}