• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Python实现识别手写数字 Python图片读入与处理

python 搞代码 4年前 (2022-01-08) 29次浏览 已收录 0个评论

这篇文章主要为大家详细介绍了Python实现识别手写数字,Python图片的读入与处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

写在前面

在上一篇文章中,我们已经讲过了我们想要写的全部思路,所以我们不再说全部的思路。

我这一次将图片的读入与处理的代码写了一下,和大纲写的过程一样,这一段代码分为以下几个部分:

  • 读入图片;
  • 将图片读取为灰度值矩阵;
  • 图片背景去噪;
  • 切割图片,得到手写数字的最小矩阵;
  • 拉伸/压缩图片,得到标准大小为100×100大小矩阵;
  • 将图片拉为1×10000大小向量,存入训练矩阵中。

所以下面将会对这几个函数进行详解。

代码分析

基础内容

首先我们现在最前面定义基础变量

 import os from skimage import io import numpy as np ##Essential vavriable 基础变量 #Standard size 标准大小 N = 100 #Gray threshold 灰度阈值 color = 100/255 

其中标准大小指的是我们在最后经过切割、拉伸后得到的图片的尺寸为NxN。灰度阈值指的是在某个点上的灰度超过阈值后则变为1.

接下来是这图像处理的一部分的主函数

 filenames = os.listdir(r"./num/") pic = GetTrainPicture(filenames) 

其中filenames得到在num目录下所有文件的名称组成的列表。pic则是通过函数GetTrainPicture得到所有训练图像向量的矩阵。这一篇文章主要就是围绕这个函数进行讲解。

GetTrainPicture函数

GetTrainPicture函数内容如下

 #Read and save train picture 读取训练图片并保存 def GetTrainPicture(files): Picture = np.zeros([len(files), N**2+1]) #loop all pictures 循环所有图片文件 for i, item in enumerate(files): #Read the picture and turn RGB to grey 读取这个图片并转为灰度值 img = io.imread('./num/'+item, as_grey = True) #Clear the noise 清除噪音 img[img>color] = 1 #Cut the picture and get the picture of handwritten number #将图片进行切割,得到有手写数字的的图像 img = CutPicture(img) #Stretch the picture and get the standard size 100x100 #将图片进行拉伸,得到标准大小100x100 img = StretchPicture(img).reshape(N**2) #Save the picture to the matrix 将图片存入矩阵 Picture[i, 0:N**2] = img #Save picture's name to the matrix 将图片的名字存入矩阵 Picture[i, N**2] = float(item[0]) return Picture 

可以看出这个函数的信息量非常大,基本上今天做的所有步骤我都把封装到一个个函数里面了,所以这里我们可以看到图片处理的所有步骤都在这里。

提前准备

首先是创建了一个用来存放所有图像向量的矩阵Picture,大小为fx10001,其中f代表我们拥有的训练图片的数目,10001的前10000位代表图片展开后的向量长度,最后一维代表这一个向量的类别,比如说时2就代表这个图片上面写的数字是2.

接下来用的是一个for循环,将files里面每一个图片进行一次迭代,计算出向量后存入picture。

在循环中的内容就是对每一张图片进行的操作。

读入图片并清除背景噪音

首先是io.imread函数,这个函数是将图片导出成为灰度值的矩阵,每一个像素点是矩阵上的一个元素。

接下来是img[img>color]=1这一句。这一句运用了逻辑运算的技巧,我们可以将其分为两部分

 point = img > color img[point] = 1 

首先是img>color,img是一个矩阵,color是一个数。意义就是对img中所有元素进行判断是否大于color这个数,并输出一个与img同等大小的矩阵,对应元素上是该值与color判断后的结果,有False与True。如果大于这个数,那么就是Ture,否则是False。下面举个例子,不再赘述。

 a = np.array([1, 2, 3, 4]) print(a>2) #以下为输出结果 [False False True True] 

之后的img[point] = 1说明将所有True的值等于1。举个例子

 a = np.array([1, 2, 3, 4]) p = a > 2 a[p] = 0 print(a) #以下为输出结果 [1 2 0 0] 

因此我通过这样的方法来清除掉了与数字颜色差别太大的背景噪音。

切割图像

首先切割图像的函数我写的是CutPicture。我们来说一下这个切割图像的意思。比如说有一个人写字写的特别小,另一个人写字写的特别大。就像是下图所示,所以我们进行这样的操作。沿着图片的边进行切割,得到了下面切割后的图片,让数字占满整个图片,从而具有可比性。

所以下面贴出代码,详细解释一下我是怎么做的。

 #Cut the Picture 切割图象 def CutPicture(img): #初始化新大小 size = [] #图片的行数 length = len(img) #图片的列数 width = len(img[0,:]) #计算新大小 size.append(JudgeEdge(img, length, 0, [-1, -1])) size.append(JudgeEdge(img, width, 1, [-1, -1])) size = np.array(size).reshape(4) print(size) return img[size[0]:size[1]+1, size[2]:size[3]+1] 

首先函数导入过来的的参数只有一个原img。

我第一步做的是把新的大小初始化一下,size一共会放入四个值,第一个值代表原图片上的手写数字图案的最高行,第二个值代表的是最低行,第三个值代表数字图案的最左列,,第四个只代表最右列**。这个还看不明白的话就看上面的图示,就是沿着图片切割一下就好了。

接下来的length和width分别代表着原图片的行数与列数,作用在下面。我又创建了一个JudgeEdge函数,这个函数是输出它的行数或者列数的两位数字。第一个append是给size列表放入了两个行序号(最高行和最低行),第二个append是给size放进两个列序号(最左列和最右列)。所以接下来就看JudgeEdge函数是干什么的。

 def JudgeEdge(img, length, flag, size): for i in range(length): #Cow or Column 判断是行是列 if flag == 0: #Positive sequence 正序判断该行是否有手写数字 line1 = img[img[i,:]<color] #Negative sequence 倒序判断该行是否有手写数字 line2 = img[img[length-1-i,:]<color] else: line1 = img[img[:,i]<color] line2 = img[img[:,length-<strong style="color:transparent">来源gaodaima#com搞(代@码网</strong>1-i]=1 and size[0]==-1: size[0] = i if len(line2)>=1 and size[1]==-1: size[1] = length-1-i #If get the both of edge, break 若上下边界都得到,则跳出 if size[0]!=-1 and size[1]!=-1: break return size 

JudgeEdge函数的参数flag就是用来判断是行还是列,当flag=0时,说明以行为基础开始循环;当flag=1时说明以列为基础进行循环。所以参数length传递的时候就是行数和列数。接下来的for循环就是根据length的大小看似是循环。

当是行时,我这里用line1和line2起到的是一个指针的作用,即在第i行时,line1的内容就是这一行拥有非白色底(数值为1)的像素的个数;line2的作用则是反序的,也就是他计算的是倒数i行非白色像素个数,这样做的目的是能够快一点,让上下同时开始进行寻找,而不用line1把整个图片循环一遍,line2把整个图片循环一遍,大大节省了时间。

寻找这一行拥有非白色底的像素的个数这一个语句同样的运用了逻辑判断,和上文中去噪的原理一模一样。

当line里面有数的时候,说明已经到达了手写数字的边缘。这时候就记录下来,然后就不再改变。当两个line都不等于初始值-1时,说明已经找到了两个边缘,这时候就可以跳出循环并且return了。

这个函数就是这样。所以说切割图像的完整代码就是这样子,下面就要

以上就是Python实现识别手写数字 Python图片读入与处理的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Python实现识别手写数字 Python图片读入与处理

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址