概率神经网络的全称是Probabilistic neural network,它主要用于模式分类,是基于贝叶斯策略前馈神经网络。它有着坚实的数学理论基础,当然本文并不打算从数学符号来对它进行介绍(有兴趣的可翻阅推荐书目),而是通过一个简单的C语言程序来认知它。

      介绍程序之前,先看下它基本模型的结构示意图:

 

概率神经网络(PNN)

      图中可以看到基本分为三层,如果有了解神经网络的话就很熟悉了。第一层是输入层,就如它的名字负责接收数据的输入;第二层是模式层,对数据进行收集整理;第三层是类别层,就是数据整理完后归属于哪一个类别的信息。最后就根据类别的信息输出了,如果把输出也作为一层的话,也可以看成四层结构。其中模式层神经元激活函数取高斯型函数 e(net-1)/Q*Q ,其中net = wkX (注:公式的来由涉及数学理论推导感兴趣请参考其他文献)

      PNN神经网络主要是用于模式分类,在此我们就运用它实现一个识别车牌号图像中的号码与背景的程序,也就是车牌号图像的二值化。本文仅用这个程序作为PNN神经网络运用的简单DEMO,因此对图像进行些处理以简化编程,采用8位BMP带调色板的图片格式存储。

 

      想想我们看到上面这个车牌识别出上面的车牌号码的原因,很明显是由于车牌的号码白色和它周围的背景蓝色有着鲜明的不同因此才能很容易的识别出车牌号码。对于要完成的程序同样也可以运用颜色差来完成识别。我们知道计算机显示bmp图片时采用的是RBG的值来描绘每一点的像素颜色,虽然看到图像车牌背景都是蓝色,但是如果放大来看蓝色并不完全相同而且还有夹杂着些其他颜色,同样车牌号也并非全部白色。分析到这里目标就清楚了,运用PNN神经网络采集图片中每个像素点的颜色RBG值,将接近蓝色或者背景中出现的其他颜色分为A类,表示背景色;将接近白色的颜色分为B类,表示车牌号色。再用0、1这两个数值来表示A类、B类,重新设置图片中像素的颜色实现了车牌号图像的二值化。

      程序的流程就比较明晰了,大致可分为三步,第一步,选取背景色和号码色的样本图片收集它们各自的颜色样本数据;第二步,运用收集的颜色数据训练PNN神经网络;第三步,将需要识别的车牌图片中每个像素的颜色数据输入PNN神经网络完成分类,然后重置图片颜色数据完成二值化。

      PNN神经网络的设计,将RBG三个值作为输入数据(还可以考虑YCbCr ),模式层里的每个神经元代表一种样本颜色(可以看到即使训练完了再添加样本颜色非常方便,只要添加一个神经元即可无须改动先前训练好的神经网络,PNN神经网络的一个很大的优势),类别层的两个单元分别代表背景色类和号码色类。输入层和模式层之间的权重存储在二维指针 **w 中,模式层到类别层的关系存储在**a 中,**a 中的值只能 0和1,每个模式层里的神经元对应的类别有且仅有一条边值为1 用来说明该模式层神经元存储的样本颜色属于该边连接的类别。

      数据收集及神经网络结构实现的伪代码如下:

{

    读取号码颜色样本;

    记录号码颜色样本的颜色,并统计总数countHM;

    读取背景颜色样本;

    记录背景颜色样本的颜色,并统计总数countBJ;

 

    w = (long double **)malloc((countBJ+countHM)*sizeof(long double *));

    a = (int **)calloc((countBJ+countHM),sizeof(int *));

    for(i=0; i<(countBJ+countHM); i++){

        w[i]=(long double *)malloc(3*sizeof(long double));   //RBG  三个值

        a[i]=(int *)calloc(2,sizeof(int));

    }

}

   PNN神经网络训练伪代码:

{

    FOR 记录到的每一种颜色也就是每个模式层单元 j

        Xr,b,g = Xr,b,g/ sqrt(Xr*Xr+Xb*Xb+Xg*Xg); //这里归一化时须采用这种方式

         w[j][Xr,b,g]= Xr,b,g

         IF 颜色属于车牌号码  a[j][1]=1;

         IF 颜色属于车牌背景 a[j][0]=1;

}

     PNN 神经网络分类算法为代码:

{

         FOR 每一行

                FOR 每一列

                     判断该像素点所属类别 estimate(Xr,b,g){

                          FOR 每一个模式层神经元{

                               net=w[i][0]*Xr+w[i][1]*Xb+w[i][2]*Xg;

                               IF (a[i][0] == 1)

                                    BJ +=exp((net-1)/(Q * Q)); //Q为判别颜色相似窗口大小

                               IF (a[i][1] == 1)

                                    HM +=exp((net-1)/(Q * Q));

                          }

                        BJ 与 HM 谁大?

                        如果 BJ 则为背景,否则就是号码;// 在BJ于HM 取相同值时默认为号码类

                    }

     根据类别二值化该像素点;

     保存二值化后的图像;

}

  完成程序后测试结果如下:

  采用的 背景样本图片y1  号码样本图片y2(由于不支持BMP格式图片上传,在此贴出的是转为gif格式后的图片)

  y1   

   y2

  用该两个样本图片训练后,将以下车牌号码图片二值化后效果如下:

          

          

          

  实现的C语言源码比较简陋杂乱、很多考虑不周之处,在此就不打包出来了。

      如果对于PNN概率神经网络的原理和数学推导感兴趣的可翻阅推荐书目,里面讲解很详实。


 

推荐书目:

 《模式分类》 作者: Richard O. Duda / Peter E. Hart / David G. Stork

版权声明:本文为jzhlin原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/jzhlin/archive/2012/08/13/pnn.html?ivk_sa=1024320u