使用Python OpenCV為CNN增加圖像樣本的實現(xiàn)
我們在做深度學(xué)習(xí)的過程中,經(jīng)常面臨圖片樣本不足、不平衡的情況,在本文中,作者結(jié)合實際工作經(jīng)驗,通過圖像的移動、縮放、旋轉(zhuǎn)、增加噪聲等圖像變換技術(shù),能快速、簡便的增加樣本數(shù)量。
本文所有案例,使用OpenCV跨平臺計算機視覺庫,在Python3.6上實現(xiàn),關(guān)于Python及OpenCV安裝使用,請參照本人早先資料,詳見參考內(nèi)容。
1. 圖片拼接及平移
1.1. 圖像移動
圖像平移是將圖像的所有像素坐標(biāo)進行水平或垂直方向移動,也就是所有像素按照給定的偏移量在水平方向上沿x軸、垂直方向上沿y軸移動。
#移動圖像,讓出邊緣,大小不變(此方法比較笨了)
def move_img(img_file1,out_file,tunnel,border_position,border_width):
print('file1=' + img_file1 )
img1 = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
hight,width = img1.shape
# 初始化空圖
final_matrix = np.zeros((hight,width), np.uint8) #,tunnel), np.uint8) #高*款(y,x)20*20*1
# change
x1=0
y1=hight
x2=width
y2=0 #圖片高度,坐標(biāo)起點從上到下
if border_position =='top':
final_matrix[y2:y1 - border_width, x1:x2] = img1[y2 + border_width:y1, x1:x2]
#左側(cè)增加邊或空白
if border_position == 'left':
final_matrix[y2 :y1, x1:x2 - border_width] = img1[y2:y1, x1 + border_width:x2]
if border_position == 'right':
final_matrix[y2 :y1, x1 + border_width:x2] = img1[y2:y1, x1:x2 - border_width]
#底部增加邊或空白
if border_position =='bottom':
final_matrix[y2 + border_width :y1, x1:x2] = img1[y2:y1 - border_width , x1:x2]
if border_position =='copy':
final_matrix[y2 :y1, x1:x2] = img1[y2:y1 , x1:x2]
cv2.imwrite(out_file, final_matrix)
return final_matrix

樣例代碼,詳見第5章節(jié)。
1.2. 圖片拼接
圖片拼接是分別讀取圖片,新建一個目標(biāo)像素大小的0矩陣,最后將讀取的圖片替換新建矩陣中目標(biāo)位置上的元素即可。主要可用于圖像切換場景,例如常見的齒輪式數(shù)字儀表盤,數(shù)字進位時出現(xiàn)的半個數(shù)字。
#圖像四周拼接邊緣,大小不變
def splicing_img(img_file1,img_file2,out_file,tunnel,border_position,border_width):
print('file1=' + img_file1 + ', file2=' + img_file2)
img1 = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img_file2, cv2.IMREAD_GRAYSCALE)
#第二個參數(shù)為如何讀取圖片,包括cv2.IMREAD_COLOR:讀入一副彩色圖片;cv2.IMREAD_GRAYSCALE:以灰度模式讀入圖片;cv2.IMREAD_UNCHANGED:讀入一幅圖片,并包括其alpha通道。
hight,width = img1.shape
final_matrix = np.zeros((hight,width), np.uint8) #,tunnel), np.uint8) #高*款(y,x)20*20*1
# change
x1=0
y1=hight
x2=width
y2=0 #圖片高度,坐標(biāo)起點從上到下
if border_position =='top':
final_matrix[y2 + border_width:y1, x1:x2] = img1[y2:y1 - border_width, x1:x2]
final_matrix[y2:border_width, x1:x2] = img2[y2:border_width, x1:x2]
#左側(cè)增加邊或空白
if border_position == 'left':
final_matrix[y2 :y1, x1+ border_width:x2] = img1[y2:y1, x1:x2 - border_width]
final_matrix[y2:y1, x1:border_width] = img2[y2:y1, x1:border_width]
if border_position == 'right':
final_matrix[y2 :y1, x1:x2 - border_width] = img1[y2:y1, x1 + border_width:x2]
final_matrix[y2:y1, x2-border_width:x2] = img2[y2:y1, x1:border_width]
#底部增加邊或空白
if border_position =='bottom':
final_matrix[y2 :y1 - border_width, x1:x2] = img1[y2+ border_width:y1 , x1:x2]
final_matrix[y1 - border_width:y1, x1:x2] = img2[y2:border_width, x1:x2]
if border_position =='copy':
final_matrix[y2 :y1, x1:x2] = img1[y2:y1 , x1:x2]
cv2.imwrite(out_file, final_matrix)
return final_matrix

2. 圖片仿射變換之平移、旋轉(zhuǎn)
2.1. 關(guān)于仿射變換
仿射變換,又稱仿射映射,是指在幾何中,一個向量空間進行一次線性變換并接上一個平移,變換為另一個向量空間。
仿射變換是在幾何上定義為兩個向量空間之間的一個仿射變換或者仿射映射(來自拉丁語,affine,“和…相關(guān)”)由一個非奇異的線性變換(運用一次函數(shù)進行的變換)接上一個平移變換組成。仿射變換可以通過一系列的原子變換的復(fù)合來實現(xiàn),包括:平移(Translation)、縮放(Scale)、翻轉(zhuǎn)(Flip)、旋轉(zhuǎn)(Rotation)和剪切(Shear)。
2.2. Python上的OpenCV實現(xiàn) 2.2.1. 旋轉(zhuǎn)
旋轉(zhuǎn)是通過仿射變換實現(xiàn)的,首先,旋轉(zhuǎn)需要先定義一個旋轉(zhuǎn)矩陣,使用cv2.getRotationMatrix2D()函數(shù)。
參數(shù)1:需要旋轉(zhuǎn)的中心點;
參數(shù)2:需要旋轉(zhuǎn)的角度;
參數(shù)3:需要縮放的比例。
#旋轉(zhuǎn)圖像,輸入文件名、輸出文件名,旋轉(zhuǎn)角度
def rotationImg(img_file1,out_file,ra):
# 獲取圖片尺寸并計算圖片中心點
img = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
(h, w) = img.shape[:2]
center = (w/2, h/2)
M = cv2.getRotationMatrix2D(center, ra, 1.0)
rotated = cv2.warpAffine(img, M, (w, h))
#cv2.imshow("rotated", rotated)
#cv2.waitKey(0)
cv2.imwrite(out_file, rotated)
return rotated

2.2.2. 平移
使用仿射變換平移圖像,首先使用已經(jīng)給出的平移矩陣M:[[1,0,x],[0,1,y]],x、y分別是x與y在橫向、縱向移動像數(shù)。

#仿射變換技術(shù),平移圖片,x_off:x方向平移像數(shù);y_off:y方向平移像數(shù),正數(shù)是右、下方移動,負數(shù)為左、上方移動 def translation_img(img_file1,out_file,x_off,y_off): img = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE) rows,cols = img.shape # 定義平移矩陣,需要是numpy的float32類型 # x軸平移x_off,y軸平移y_off, 2*3矩陣 M = np.float32([[1,0,x_off],[0,1,y_off]]) dst = cv2.warpAffine(img,M,(cols,rows)) cv2.imwrite(out_file, dst)

3. 圖片縮放及剪裁
3.1. 圖片縮放
圖片縮放使用CV2的cv2.resize()函數(shù),函數(shù)語法如下:cv2.resize(img, (dstWeight,dstHeight)),第一個參數(shù)是源圖像數(shù)據(jù),第二個參數(shù)(目標(biāo)寬度,目標(biāo)高度)。
在實際應(yīng)用中,輸入圖像大小是固定不變,這樣在縮放圖片后,如果是放大,則需要剪裁,如果縮寫,則出現(xiàn)空余區(qū)域。(注:本案例中參數(shù)deviation,用于取放大圖像的起點位置,參照位置為左上角)
#縮放,輸入文件名,輸出文件名,放大高與寬,偏離度
def resizeImg(img_file1,out_file,dstWeight,dstHeight,deviation):
img1 = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
imgshape = img1.shape
h = imgshape[0]
w = imgshape[1]
final_matrix = np.zeros((h,w), np.uint8)
x1=0
y1=h
x2=w
y2=0 #圖片高度,坐標(biāo)起點從上到下
dst = cv2.resize(img1, (dstWeight,dstHeight))
if h<dstHeight:
final_matrix[y2 :y1, x1:x2] = dst[y2+deviation:y1+deviation , x1+deviation:x2+deviation]
else:
if deviation == 0:
final_matrix[y2 :dstHeight, x1:dstWeight] = dst[y2 :dstHeight,x1 :dstWeight]
else:
final_matrix[y2 + deviation:dstHeight + deviation, x1 + deviation:dstWeight + deviation] = dst[y2 :dstHeight,x1 :dstWeight]
cv2.imwrite(out_file, final_matrix)
return final_matrix
3.2. 圖片剪裁
在做圖像處理時,一般是圖像大小保持一致,因此,圖片剪裁時,圖片大小不變,去掉不需要的部分。
#剪切圖片 def cut_img(img_file1,out_file,top_off,left_off,right_off,bottom_off): img1 = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE) hight,width = img1.shape x1=0 y1=hight x2=width y2=0 #圖片高度,坐標(biāo)起點從上到下hight,width = img1.shape #灰度圖像,不使用通道tunnel final_matrix = np.zeros((hight,width), np.uint8) #,tunnel), np.uint8) #高*款(y,x)20*20*1 final_matrix[y2 + top_off:y1 - bottom_off, x1 + left_off:x2 - right_off] = img1[y2 + top_off:y1 - bottom_off, x1 + left_off:x2 - right_off] cv2.imwrite(out_file, final_matrix) return final_matrix

4. 圖片增加高斯噪聲/椒鹽噪聲
在matlab中,存在執(zhí)行直接得函數(shù)來添加高斯噪聲和椒鹽噪聲。Python-OpenCV中雖然不存在直接得函數(shù),但是很容易使用相關(guān)的函數(shù)來實現(xiàn)。
4.1. 添加鹽椒噪聲
# 添加椒鹽噪聲,prob:噪聲比例
def sp_noiseImg(img_file1,prob):
image = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
output = np.zeros(image.shape,np.uint8)
thres = 1 - prob
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = random.random()
if rdn < prob:
output[i][j] = 0
elif rdn > thres:
output[i][j] = 255
else:
output[i][j] = image[i][j]
return output
噪聲比依次是:0.1、0.05、0.01。
4.2. 添加高斯噪聲
# 添加高斯噪聲
# mean : 均值
# var : 方差
def gasuss_noiseImg(img_file1, out_file, mean=0, var=0.001):
image = cv2.imread(img_file1, cv2.IMREAD_GRAYSCALE)
image = np.array(image/255, dtype=float)
noise = np.random.normal(mean, var ** 0.5, image.shape)
out = image + noise
if out.min() < 0:
low_clip = -1.
else:
low_clip = 0.
out = np.clip(out, low_clip, 1.0)
out = np.uint8(out*255)
cv2.imwrite(out_file, out)
return out
5. 代碼測試
''' Created on 2019年5月20日 @author: xiaoyw ''' #coding: utf-8 import numpy as np import cv2 import os import random #函數(shù)部分略過,見上文 if __name__ == '__main__': file1 = 'dog.jpg' move_img(file1,'timg11.jpg',1,'top',35) move_img(file1,'timg12.jpg',1,'left',35) move_img(file1,'timg13.jpg',1,'right',35) move_img(file1,'timg14.jpg',1,'bottom',35) cut_img(file1,'dog_cut.jpg',20,10,20,30) rotationImg(file1,'dog_ra1.jpg',30) rotationImg(file1,'dog_ra1.jpg',60) rotationImg(file1,'dog_ra2.jpg',-90) sp_noiseImg(file1,'dog_sp_01.jpg',0.01) sp_noiseImg(file1,'dog_sp_05.jpg',0.05) sp_noiseImg(file1,'dog_sp_10.jpg',0.1) resizeImg(file1,'dog_big.jpg',250,280,0) resizeImg(file1,'dog_small.jpg',100,200,0) splicing_img(file1,file1,'dog2.jpg',1,'right',50) translation_img(file1,'timg15.jpg',10,10) translation_img(file1,'timg16.jpg',-20,-30) pass
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python?CNN卷積神經(jīng)網(wǎng)絡(luò)實戰(zhàn)教程深入講解
- python人工智能tensorflow構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)CNN
- Python人工智能深度學(xué)習(xí)CNN
- Python神經(jīng)網(wǎng)絡(luò)TensorFlow基于CNN卷積識別手寫數(shù)字
- Python中人臉圖像特征提取方法(HOG、Dlib、CNN)簡述
- Python搭建Keras CNN模型破解網(wǎng)站驗證碼的實現(xiàn)
- Python實現(xiàn)CNN的多通道輸入實例
- Python+Tensorflow+CNN實現(xiàn)車牌識別的示例代碼
- Python與CNN的碰撞詳解
相關(guān)文章
python實現(xiàn)端口轉(zhuǎn)發(fā)器的方法
這篇文章主要介紹了python實現(xiàn)端口轉(zhuǎn)發(fā)器的方法,涉及Python實現(xiàn)端口轉(zhuǎn)發(fā)的技巧,支持TCP和UDP協(xié)議,需要的朋友可以參考下2015-03-03
Django模板標(biāo)簽中url使用詳解(url跳轉(zhuǎn)到指定頁面)
這篇文章主要介紹了Django模板標(biāo)簽中url使用詳解(url跳轉(zhuǎn)到指定頁面),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
Python中openpyxl實現(xiàn)vlookup函數(shù)的實例
在本篇文章里小編給大家整理的是關(guān)于Python中openpyxl實現(xiàn)vlookup函數(shù)的實例內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。2020-10-10
python使用__slots__讓你的代碼更加節(jié)省內(nèi)存
如果要限制添加的屬性,例如,Student類只允許添加 name、gender和score 這3個屬性,就可以利用Python的一個特殊的slots來實現(xiàn)。這篇文章主要給大家介紹了關(guān)于python如何使用__slots__讓你的代碼更加節(jié)省內(nèi)存的相關(guān)資料,需要的朋友可以參考下2018-09-09
Python基于scrapy采集數(shù)據(jù)時使用代理服務(wù)器的方法
這篇文章主要介紹了Python基于scrapy采集數(shù)據(jù)時使用代理服務(wù)器的方法,涉及Python使用代理服務(wù)器的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04
Python編程ContextManager上下文管理器講解
這篇文章主要介紹了Python編程中對Context Manager上下文管理器的詳解說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-09-09

