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

链码的优越性在于:对于上一个链码方向逆时针旋转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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值