【图像处理与分析】图像分割方法总结

本文总结了图像分割的几种方法,包括灰度阈值法(全局与自适应阈值)、基于边缘的图像分割(差分法、梯度法、高通滤波)和基于区域的图像分割(区域生长法、分水岭算法)。还提到了分割后的处理技术,如数学形态学和图像平滑。
摘要由CSDN通过智能技术生成

一、灰度阈值法
1、全局阈值法
整幅图像使用同一个阈值做分割处理,适用于目标物和背景有明显对比的图像。这种方法是只考虑像素值不考虑空间特征的,例如峰谷法、最大熵分割法。
如下是一维最大熵分割法实现。
最大熵原理:只掌握关于未知分布的部分知识时,应选取符合这些知识的但是熵值最大的概率分布。因为熵越大,随机变量的不确定性越大,做准确预测的难度越大。

int maxEntropy(IplImage *src);
float calEntropy(CvHistogram *hist,int begin,int end);

int main()
{
    //Mat img =imread("E:/b.jpg",1);

    IplImage *src=cvLoadImage("G:\\4.bmp",CV_LOAD_IMAGE_GRAYSCALE); 
    IplImage *dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
    int threshold=maxEntropy(src);
     cvThreshold(src, dst, threshold, 255, CV_THRESH_BINARY); 
     //imshow("一维最大熵分割",img);
     cvNamedWindow("一维最大熵分割");
     cvShowImage("一维最大熵分割", dst);
     cvWaitKey(0);
     return 0;
}

int maxEntropy(IplImage *src)
{
    assert(src);
    assert(src->depth == 8);  
    assert(src->nChannels == 1);

    int sizes=256;
    float range[2]={
  0,255};
    float *ranges[1]={&range[0]};
    CvHistogram *hist = cvCreateHist(1, &sizes, CV_HIST_ARRAY, ranges, 1);
    cvCalcHist(&src,hist,0,0);
    cvNormalizeHist(hist,0);

    int threthold=0;
    int Entropy_max=0;
    for(int i=0;i<sizes;i++)
    {
        float entropy=calEntropy(hist,0,i)+calEntropy(hist,i,sizes);
        if(entropy>=Entropy_max)
            Entropy_max=entropy;
    }
    return Entropy_max;
}

float calEntropy(CvHistogram *hist,int begin,int end)
{
    float total=0;//总概率
    for(int i=begin;i<end;i++)
    {
        total+=cvQueryHistValue_1D(hist,i);
    }
    float entropy=0;
    for(int i=begin;i<end;i++)
    {
        float probability=cvQueryHistValue_1D(hist,i);
        if(probability==0)
            continue;
        probability/=total;
        entropy-=probability*log(probability);
    }

    return entropy;
}

2、自适应阈值法
在许多情况下,目标和背景的对比度在图像中的各处是不一样的,实际处理时,需要按照具体情况将图像分成若干子区域分别选择阈值,或者动态地根据一定的邻域范围选择每点处的阈值,进行图像分割。
OTSU法,它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
以前在遥感影像灰度阈值分割上尝试了一些自适应阈值法,影像背景地物比较复杂,效果都不太理想。

3、人工确定

二、基于边缘的图像分割
1、差分法
图像差分,就是把两幅图像的对应像素值相减,以削弱图像的相似部分,突出显示图像的变化部分。【原理都是共通的,这个也是比较简单的变化检测方法】
2、梯度法
Canny\Sobel算子等,他们是里面包含有计算梯度幅值和方向的步骤,也是一种梯度算子吧。
Canny 步骤:首先消除噪声,一般使用高斯平滑滤波;然后计算梯度幅值和方向;然后非极大值抑制,也就是说选择局部范围内的极大值,抑制局部范围内的非极大值;最后是双阈值算法检测和连接,这一步是为了保留主要边缘,剔除不连续的、次要的边缘。
这里原理解释主要参考:
http://blog.csdn.net/likezhaobin/article/details/6892176
代码根据该博主提供的代码进行了重构
http://blog.csdn.net/likezhaobin/article/details/6892629


/*****
    int* M ;                       //梯度幅值 
    unsigned char* N;            //非极大值抑制结果
    double* Theta ;             //梯度方向 
******/
void Gaussian(unsigned char* nImageData,unsigned char* pCanny,int nWidth,int nHeight);
void nonMaximumSuppression(unsigned char *pCanny,unsigned char* N,int* M,double* Theta,int nWidth,int nHeight);//极大值抑制
void doubleThresholdDetection(unsigned char* N,int* M,int nWidth,int nHeight);//双阈值检测
void TraceEdge(int y, int x, int nThrLow, unsigned char* pResult, int *pMag, int nWidth,int nHeight);
void main()
{
    /******彩色图灰度化********/
    IplImage *colorImage=cvLoadImage("G:\\5.jpg",-1);//读图,获取彩色图指针

    int width=colorImage->width;
    int height=colorImage->height;
    int sizeofPixel=width*height;//像素数
    IplImage *opencvGrayImage=cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);//定义变换后的灰度图指针
    char *gray=(char*)malloc(sizeof(char)*width*height);//存放转换后的灰度像素值
    for(int i=0;i<sizeofPixel;i++)
    {
        uchar b=(uchar)colorImage->imageData[3*i+0];
        uchar g = (uchar)colorImage->imageData[3 * i + 1];  
        uchar r = (uchar)colorImage->imageData[3 * i + 2];  
        gray[i] = r * 0.299 + g * 0.587 + b * 0.114;  
    }
    opencvGrayImage->imageData=gray;

    unsigned char* nImageData = new unsigned char[width*height];   //保存图像中的数据 
    for(int j=0; j<height; j++)                                     //获取数据
    {  
        for(int i=0; i<width; i++)  
            nImageData[j*width+i] = (unsigned char)opencvGrayImage->imageData[j*width+i];  
    }  

    unsigned char*pCanny = new unsigned char[width*height];        //为平滑后的图像数据分配内存  
    Gaussian(nImageData,pCanny,width,height);//高斯模糊,不太理解

    int* M = new int[width*height];                       //梯度幅值 
    unsigned char* N =new unsigned char[width*height];  //非极大值抑制结果
    double* Theta = new double[width*height];             //梯度方向 
    nonMaximumSuppression(pCanny,N,M,Theta,width,height);//非极大值抑制结果
    doubleThresholdDetection(N,M,width,height);//双阈值检测
  • 10
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值