功能:
将文件夹下的20*20像素黑白图片,根据重心位置绘制到28*28图片上,然后保存。经过预处理的图片有利于数字的准确识别。参见MNIST对图片的要求。
此处可下载已处理好的图片:
https://files.cnblogs.com/files/hatemath/20-pixel-numbers.zip
https://files.cnblogs.com/files/hatemath/28-pixel-numbers.zip
1 # encoding: utf-8 2 import os 3 4 5 from PIL import Image 6 import numpy as np 7 import cv2 8 import matplotlib.pyplot as plt 9 import matplotlib.cm as cm 10 11 srcDir = '20-pixel-numbers' 12 dstDir = '28-pixel-numbers' 13 14 #显示图片 15 def showImg(image): 16 plt.imshow(image,cmap=cm.binary) 17 plt.show() 18 19 #按比例调整图片大小 20 def resizeImage(image,width=None,height=None,inter=cv2.INTER_AREA): 21 22 #获取图像尺寸 23 (h,w) = image.shape[:2] 24 if width is None and height is None: 25 return image 26 27 #高度算缩放比例 28 29 if(w > h): 30 newsize = (width,round(h / (w/width))) 31 else: 32 newsize = (round(w/ (h/height)), height) 33 34 #print(newsize) 35 36 37 38 # 缩放图像 39 newimage = cv2.resize(image, newsize, interpolation=inter) 40 return newimage 41 42 #创建新的黑色图片 43 def createBianryImage(bg=(0,0,0), width=28, height=28): 44 45 channels = 1 46 47 image = np.zeros((width,height,channels),np.uint8)#生成一个空灰度图像 48 #cv2.rectangle(image,(0,0),(width,height),bg,1, -1) 49 50 return image.reshape(width, height) 51 52 #两个不同大小的图片合并 53 def mergeImage(bg, fg, x, y): 54 bgH, bgW = bg.shape[:2] 55 fgH, fgW = fg.shape[:2] 56 57 for i in range(fgH): 58 for j in range(fgW): 59 if(y+i < bgH and x+j < bgW): 60 #print('xx', y+i, x+j) 61 bg[y+i, x+j] = fg[i,j] # 这里可以处理每个像素点 62 63 return bg 64 65 # 求像素重心。传入二值图像,其中白色点算重量,黑色点为空 66 def getBarycentre(image): 67 68 h, w = image.shape[:2] 69 70 sumWeightW = 0 71 sumWeightH = 0 72 73 count = 0 74 75 for i in range(h): 76 for j in range(w): 77 if(image[i,j] > 128): 78 sumWeightW += j 79 sumWeightH += i 80 count += 1 81 82 if(count == 0): 83 count = 1 84 85 print('getBarycentre: ', round(sumWeightW/count), round(sumWeightH/count) ) 86 return (round(sumWeightW/count), round(sumWeightH/count)) 87 88 89 90 def getFileList(strDir, strType='.png'): 91 lstSrcFiles = [] 92 93 files = os.listdir(strDir) 94 for file in files: 95 if os.path.splitext(file)[1] == strType: 96 lstSrcFiles.append(file) 97 98 return lstSrcFiles 99 100 101 # 读取指定目录下的图片文件,图片为黑白格式,长、宽的最大值为20像素。 102 lstSrcFiles = getFileList(srcDir) 103 print (lstSrcFiles) 104 105 106 for file in lstSrcFiles: 107 binary = cv2.imread(srcDir + '/' + file, cv2.IMREAD_GRAYSCALE) 108 109 # 求像素重心 110 bcW, bcH = getBarycentre(binary) 111 112 # 叠加到28x28的黑色图片上 113 xOffset = round(28/2 - bcW) 114 yOffset = round(28/2 - bcH) 115 116 print('offset', xOffset, yOffset) 117 118 # 另存为 119 cv2.imwrite(dstDir + '/' + file, 120 mergeImage(createBianryImage(), binary, xOffset, yOffset)) 121 #binary)