识别图片中的数字------基本思路

识别图片中的数字------基本思路

1. 读取矩阵     拿到一张带有数字的图片后,首先就是得到它的rgb矩阵。这对于bmp格式文件来说易如反掌,对于jpg的相对麻烦一些。假设我们现在已经得到了rgb矩阵M(m*n),每个点都有三个属性(r,g,b)。

2. 灰度化       将彩色图片转化为灰色图片,目的在于使图片颜色初步单调,便于第3步的进行。实现方法很多,可以将每个点的(r,g,b)设置为(a*r+b*g+c*b),其中a+b+c=1,即加权平均;也可以设置为(max(r,g,b))或者(min(r,g,b))。我采用的是加权法:0.11*blue+0.59*green+0.30*red。

3. 黑白化       将灰色图片转化为黑白图片。这一步是为了后期处理上的方便。大多数人会选择阈值法:设置一个(rx,gx,bx),逐点比较,将所有的点设置为黑色(0,0,0)或者白色(255,255,255)。我采用的方法是:

view plaincopy to clipboardprint?
//转为黑白两色   
void CMyBitMap::Trans1()   
{   
    ColorData color;   
    for(int i=0;i<width*height;i++)   
    {   
        color=color_data[i];   
        int max=100;   
        if((color.blue < max) || (color .green<max) || (color.red <max))   
        {   
            color.blue=0;   
            color.green=0;   
            color.red=0;   
        }   
        else  
        {   
            color.blue=255;   
            color.green=255;   
            color.red=255;   
        }   
        color_data[i]=color;   
    }   
}  
//转为黑白两色
void CMyBitMap::Trans1()
{
 ColorData color;
 for(int i=0;i<width*height;i++)
 {
  color=color_data[i];
  int max=100;
  if((color.blue < max) || (color .green<max) || (color.red <max))
  {
   color.blue=0;
   color.green=0;
   color.red=0;
  }
  else
  {
   color.blue=255;
   color.green=255;
   color.red=255;
  }
  color_data[i]=color;
 }
}

4. 腐蚀和膨胀      考虑到图片中的数字笔画可能比较细,同时有一些噪音斑点存在,需要进行腐蚀处理+膨胀处理。腐蚀处理就是把图片中线条变得更细,就像白色部分在腐蚀黑色部分一样;膨胀处理就是把线条变粗。在腐蚀的过程中,会把孤立的噪音点清除掉;在膨胀的过程中,会把原有的线条更圆润、清晰。所以需要先进行腐蚀,后进行膨胀。我实现的腐蚀算法很简单:遍历rgb矩阵,如果当前像素点为白色,则将其四周的像素点设置为白色。膨胀算法类似:遍历矩阵,如果当前点为黑色像素,则将其四周的点全部设置为黑色。我们不妨设想一下,如果先进行膨胀,后进行腐蚀,会有什么效果呢?

5.分割       这一步把图片分割为若干块,每一块中都是独立的一个数字,说的数学化一点,就是找到所有数字的外切矩形。如果各个数字没有粘连,则很容易分割;如果数字之间有粘连,则比较困难。常用的方法是检测粘连点(有点类似于图论中的连接两个连通块的桥),然后分割。我找的实验图片都是不粘连的,算是避过了这个难题  :)

6.离散化    第5步以后,我们得到若干矩形,每个矩形中有且仅有一个数字,现在针对每个矩形进行处理。常用的思路是将该矩形映射为一个二维矩阵。我的办法是映射为一个8*8的01矩阵,其中0代表白色块,1代表黑色块,实现方法比较无脑:将矩形分割为8*8的小矩形,然后统计每个小矩形中的黑色块数,如果超过小矩形面积的一半,则认为该小矩形全部为黑色,否则全为白色。下图是该8*8矩阵打印的结果,你能猜出来是哪个数字么?
    1 1 1 1 1 1
1 1 1
1 1           1
  1 1 1 1 1 1 1
              1
              1
              1
            1 1

7.训练    这时我情不自禁的想到了神经网络方法,输入是8*8=64,输出是0到9,共10个。事实上,很多人会采用神经网络方法来训练,可以很方便的得到识别结果的可信率。另一种方法是使用决策树,举个例子:如果8*8的矩阵的第一行有大于5个点为黑色,则该数字很有可能0、2、3、5、7、8、9,一般不会是1和4;如果第一行只有1到2个黑色,则很有可能是1和1;如果第一行有3到4个黑色,则很有可能是0和4(如果这些黑色连续,则很有可能是0;否则可能是4)。构造数十条此类的判断,也可以实现识别功能。如果为每个规则设置一个可信度,这样得到的识别结果也会附加一个可信度。

   上面所说的,只是图像处理和模式识别中最最简单的东西,涉足以后,才发现博大精深呢   :)

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值