链码表追踪二值图像的最外层轮廓

来源:互联网 发布:乾隆下江南 知乎 编辑:程序博客网 时间:2024/06/05 17:52

链码的优越性在于:对于上一个链码方向逆时针旋转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;}
1 0
原创粉丝点击