功能:
將文件夾下的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)