基于canny算子的字符识别的总结

 

使用canny算子对图像进行边缘分割,程序代码:

#include"ImageProcess.h"

#include<math.h>

int get_value(float*ptr,int rows,int cols);

void binarization(Mat img2,int T1,int T2,int rows,int cols);       //对图像二值化

void connect_edge(uchar*temp,int cols);                            //利用双阈值连接图像

int main()

{

    int i,j;

    //int rows,cols;

    Mat img=imread("4.jpg",CV_LOAD_IMAGE_GRAYSCALE);

            if (img.empty())

        {

            fprintf(stderr,"Error:load image failed.");

            waitKey();

               return -1;

        }

    else

    {

        //计算梯度和方向

    int rows=img.rows;

    int cols=img.cols;

 

    float * p=new float[rows*cols];

    float * q=new float[rows*cols];

    float * Canny=new float[rows*cols];            //用canny数组来存放像素点的梯度值

    float *angle=new float[rows*cols];               //用angle数组来存放像素点的方向

    GaussianBlur(img,img,Size(7,7),2,2);             //高斯滤波函数

    for(j=0;j<rows;j++)                              //canny算子对每个像素计算梯度和方向

    {                                               

        for(i=0;i<cols;i++)                           

        {

            p[j*cols+i]=(float)(img.data[j*cols+i+1]-img.data[j*cols+i]+img.data[(j+1)*cols+i+1]-img.data[(j+1)*cols+i]);

            q[j*cols+i]=(float)(img.data[j*cols+i]-img.data[(j+1)*cols+i]+img.data[j*cols+i+1]-img.data[(j+1)*cols+i+1]);

            Canny[j*cols+i]=sqrt( p[j*cols+i]* p[j*cols+i]+ q[j*cols+i]* q[j*cols+i]);

            angle[j*cols+i]=atan2(q[j*cols+i],p[j*cols+i])*180/3.141592654;

   

            if(angle[j*cols+i]<0)

                angle[j*cols+i]+=180;

   

        }

    }

//非极大值抑制                                       img2是一个新图像,将img图像的点,如C

                                                 点,和交叉的dTmp1和dTmp2比较,若c 的梯度

                                                值比任意一个都小,说明C不是那个方向上的极

                                             大值,就把img2灰度值赋为0,否则就是极大值,将

                                                它的梯度值赋给img2的灰度值

Mat img2=img.clone();

    for(j=1;j<rows-1;j++)

    {

        for(i=1;i<cols-1;i++)

        {

            if(Canny[j*cols+i]==0)

                img2.data[j*cols+i]=0;

             else if((angle[j*cols+i]<=22.5)||(angle[j*cols+i]>157.5))

            {

       

                if((Canny[j*cols+i]<Canny[j*cols+i-1])||(Canny[j*cols+i]<Canny[j*cols+i+1]))

                {

                    img2.data[j*cols+i]=0;

                }

                else

                {

                    img2.data[j*cols+i]=(uchar)Canny[j*cols+i];

                }

            }

 

            else if(angle[j*cols+i]>22.5&&angle[j*cols+i]<=67.5)

            {

                 

                if((Canny[j*cols+i]<Canny[(j-1)*cols+i+1])||(Canny[j*cols+i]<Canny[(j+1)*cols+i-1]))

                {

                    img2.data[j*cols+i]=0;

                }

                else

                {

                    img2.data[j*cols+i]=(uchar)Canny[j*cols+i];

                }

            }

 

            else if(angle[j*cols+i]>67.5&&angle[j*cols+i]<=112.5)

            {

               

                if((Canny[j*cols+i]<Canny[(j-1)*cols+i])||(Canny[j*cols+i]<Canny[(j+1)*cols+i]))

                {

                    img2.data[j*cols+i]=0;

                }

                else

                {

                    img2.data[j*cols+i]=(uchar)Canny[j*cols+i];

                }

            }

 

            else if(angle[j*cols+i]>112.5&&angle[j*cols+i]<=157.5)

            {

           

                if((Canny[j*cols+i]<Canny[(j-1)*cols+i-1])||(Canny[j*cols+i]<Canny[(j+1)*cols+i+1]))

                {

                    img2.data[j*cols+i]=0;

                }

                else

                {

                    img2.data[j*cols+i]=(uchar)Canny[j*cols+i];

                }

            }

        }

    }

 

    imshow("image3",img2);

int T_high,T_low;                                             //设两个阈值,一大一小

    T_high=get_value(Canny,rows,cols)+1;

    printf("大阈值为%d ",T_high);

    T_low=T_high/2;

    printf("小阈值为%d ",T_low);

 

    binarization(img2,T_high,T_low,rows,cols);              //调用二值化函数

    imshow("image4",img2);

    for(int i=0;i<cols;i++)                             //将边界赋为其他值

    {

 

        img2.data[i]=0;

        img2.data[(rows-1)*cols+i]=0;

    }

 

    for(int j=0;j<rows;j++)  

    {

        img2.data[j*cols]=0;

        img2.data[j*cols+cols-1]=0;

    }

    for(j=0;j<rows;j++)

    {

        for(i=0;i<cols;i++)

        {

            if(img2.data[j*cols+i]==254)                connect_edge(img2.data+j*cols+i,cols);       //先判断是否是亮点,是,再调用

                                                   connect_edge函数

    }

    }

    for(j=0;j<rows;j++)

    {

        for(i=0;i<cols;i++)

        {

            if(img2.data[j*cols+i]<254)

                img2.data[j*cols+i]=0;

        }

    ,  }

 

delete [] p;

delete [] q;

delete [] Canny,angle;

    namedWindow("image2",CV_WINDOW_AUTOSIZE);

    imshow("image2",img2);

    namedWindow("image",CV_WINDOW_AUTOSIZE);

    imshow("image",img);

   

    waitKey();

    return 0;

}

}

 

//自适应阈值

int get_value(float*ptr,int rows,int cols)

    {

        int T;

        double max_variance=0.0;

        int max_T=0;

   

    for(int m=0;m<=255;m++)

    {

        T=m;

        float foreground_gray=0;//前景总灰度值

        float background_gray=0;//背景总灰度值

        int fore_num=0,back_num=0;//计算个数

        double fore_aver=0;

        double back_aver=0;

 

        for(int j=1;j<rows-1;j++)

        {

            for(int i=1;i<cols-1;i++)

            {

                if(ptr[j*cols+i]>T)

                {

                   foreground_gray=ptr[j*cols+i]+foreground_gray;

                   fore_num++;

                }          

                else

                {

                    background_gray+=ptr[j*cols+i];

                    back_num++;

                }

            }

        }

        if(fore_num!=0)

        {

             fore_aver=((double)foreground_gray)/((double)fore_num);

           

        }

        if(back_num!=0)

        {

             back_aver=(double)background_gray/(double)back_num;

        }

        double fore_proportion=(double)fore_num/(double)(rows*cols);

        double back_proportion=(double)back_num/(double)(rows*cols);

        double total_aver=fore_proportion*fore_aver+back_proportion*back_aver;

        double variance=(fore_aver-total_aver)*(fore_aver-total_aver)*fore_proportion+(back_aver-total_aver)*(back_aver-total_aver)*back_proportion;

        if(variance>max_variance)

        {

            max_variance=variance;

            max_T=T;

        }

    }

    return max_T;

 

}

 

    //二值化

 void binarization(Mat img2,int T1,int T2,int rows,int cols)

{

 

    for(int j=0;j<(rows);j++)

    {

        for(int i=0;i<(cols);i++)

        {

            if(img2.data[j*cols+i]<T1)           //先和大阈值比,小于阈值的赋为0,大于的

                                                  赋为254.

            {

                img2.data[j*cols+i]=0;

            }

            else

            {

                img2.data[j*cols+i]=254;

            }

        }

    }

for(int j=0;j<rows;j++)                        //再和小阈值比,小于的赋为0,大于的且又不是

                                               254的,就是潜在的亮点,赋为128

    {

        for(int i=0;i<cols;i++)

        {

            if(img2.data[j*cols+i]<T2)

            {

                img2.data[j*cols+i]=0;

            }

            else

            {

                if(img2.data[j*cols+i]<254)

                img2.data[j*cols+i]=128;

            }

        }

    }

}

   

void connect_edge(uchar* temp,int cols){               //根据一个灰度值为255的点寻找它的八连通区域有没有128的点,即大于小阈值的点,若有将该点赋为255,继续递归,这样就进行了连接

    * temp=255;

        if(*(temp-cols-1)==128)

            connect_edge(temp-cols-1,cols);

 

        if(*(temp-cols)==128)

            connect_edge(temp-cols,cols);

 

        if(*(temp-cols+1)==128)

            connect_edge(temp-cols+1,cols);

 

        if(*(temp-1)==128)

            connect_edge(temp-1,cols);

 

        if(*(temp+1)==128)

 

            connect_edge(temp+1,cols);

 

        if(*(temp+cols-1)==128)

 

            connect_edge(temp+cols-1,cols);

 

        if(*(temp+cols)==128)

 

            connect_edge(temp+cols,cols);

 

        if(*(temp+cols+1)==128)

 

            connect_edge(temp+cols+1,cols);

 

}

你可能感兴趣的:(基于canny算子的字符识别的总结)