CV學習筆記(二十):數據集拼接生成

作者:雲時之間
來源:知乎
鏈接:https://zhuanlan.zhihu.com/p/139918526
編輯:王萌


上一次使用了text_renderer嘗試生成類似於銀行卡的數據,但是實際下來效果並不好,我分析了一下原因:
①:text_renderer輸出的背景和真實銀行卡圖片有很大的差異
②:大多數銀行卡採用的是突出的字體,text_renderer很難去模擬
分析出以上的問題後,現在的重點開始轉換成如何去近似的模擬銀行卡數據集,最好的方法就是使用真實的銀行卡卡號片段來拼接成數據。
一邊說代碼,一邊捋順思路:



一:準備數據

首先準備了大概50張的銀行卡卡號片段的真實圖片,儘量保證每張圖片的長度爲3-4位,爲什麼分爲3-4位?分析了大多數的銀行卡後,發現一個規律:
信用卡卡號:0000 0000 0000 0000
儲蓄卡卡號:0000 0000 0000 0000 000
我們用CTPN檢測的時候,往往會一段一段的檢測,然後拼接起來,這種效果理論上會更好準備的數據如下:
圖片的分辨率180*46
CV學習筆記(二十):數據集拼接生成
現在分析代碼:
第一步:選擇生成數量,讀取圖片
這部分註釋很清楚,不再贅述
CV學習筆記(二十):數據集拼接生成








二:裁剪圖片,拼接圖片

這部分是整個程序之中的關鍵,我繪製了一個圖,結合圖來說一下
CV學習筆記(二十):數據集拼接生成
因爲準備的數據集是3-4個字符一張圖,DenseNet的輸入長度爲10時比較合適(具體爲什麼還沒搞清楚),因此拼接的圖片字符長度也是10個字符:讀取圖片
CV學習筆記(二十):數據集拼接生成
這裏用到cut_image函數對image3進行裁剪:
CV學習筆記(二十):數據集拼接生成
裁剪前後對比:
CV學習筆記(二十):數據集拼接生成
對圖片進行拼接:
CV學習筆記(二十):數據集拼接生成
拼接後效果:
CV學習筆記(二十):數據集拼接生成










三:數據增強

因爲DenseNet的輸入爲280*32的圖像,並且爲減少計算,需要將圖像轉換爲灰度圖像
CV學習筆記(二十):數據集拼接生成
轉換爲灰度圖像後,這裏需要使用ImageDataGenerator類,簡單的說ImageDataGenerator是keras.processing.image模塊裏的圖片生成器,每次喂進去一個batch_size的數據,然後對這個批次的數據進行樣本增強,用來擴充樣本數據集的大小,增強模型的泛化能力,更模擬真實情況,比如旋轉,縮放,對比度轉換等等。

CV學習筆記(二十):數據集拼接生成

CV學習筆記(二十):數據集拼接生成

四:劃分訓練集和測試集

我們將訓練集和測試集按照8:2的比例進行劃分
CV學習筆記(二十):數據集拼接生成
運行,數據生成完畢
CV學習筆記(二十):數據集拼接生成


五:代碼

import os
import numpy as np
import cv2
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
import os

#ToTAL是生成樣本種子數量 ,真實樣本數量爲 TOTAL * 10
print("--------實際生成樣本數爲ToTal* 10--------")
TOTAL=int(input("輸入要生成的種子數:"))
#圖片路徑,顯示圖片的名稱
path_image=r'./images_base/'
list_path=os.listdir(path_image)

loca=["0,0,30,46","30,0,60,46","60,0,90,46","90,0,120,46"]
ALLIMAGE=len(list_path)#得到給出的訓練集數量,image_base的數量
print("總共{0}張圖片,需要生成{1}張圖片\n------------正在生成中------------------".format(ALLIMAGE,TOTAL*10))

if not os.path.exists("./images"):
    os.mkdir("./images")

#對半裁圖片,輸入圖片從120*46->60*46
def cut_image(imge,l2,l3,l0=0,l1=46):
    src2 = imge[l0:l1, l2:l3]
    return src2

for i in range(TOTAL):
    #生成0-allmage,三個的隨機數
    rad_num=np.random.randint(0,ALLIMAGE,(1,3))

    img_path=[]

    for j in rad_num[0]:
        #取image_base裏邊的隨機圖片
         img_path.append([r"./images_base/"+str(list_path[j])])

         # img_path=img_path[0]
    imge1=cv2.imread(" ".join(img_path[0]))
    imge2 = cv2.imread(" ".join(img_path[1]))
    imge3 = cv2.imread(" ".join(img_path[2]))
    src1=cut_image(imge3, 0, 60)

    tmp = np.zeros((46, 300, 3), np.uint8)
    tmp[0:46, 0:120] = imge1
    tmp[0:46, 120:240] = imge2
    tmp[0:46, 240:300] = src1
    cv2.imshow("-",tmp)
    cv2.waitKey(0)
    '''
    名稱爲image1的前4位+image2前4位+src1的前兩位
    '''
    name = " ".join(img_path[0]).split("/")[2][0:4] + " ".join(img_path[1]).split("/")[2][0:4] + \
           " ".join(img_path[2]).split("/")[2][0:2] + "I"
    # print(name)
    '''
    tmp輸入300*46->DenseNet輸入爲280*32->Reshape後灰度
    '''
    tmp = cv2.resize(tmp, (280, 32))
    tmp = cv2.cvtColor(tmp, cv2.COLOR_BGR2GRAY)
    '''
    數據增強:
    隨機旋轉,除以總寬度0.01,除以總寬度0.015,
    空間隨機縮放範圍0.06
    隨機填充
     '''
    datagen = ImageDataGenerator(   #數據增強
        rotation_range=2,
        width_shift_range=0.01,
        height_shift_range=0.015,
        zoom_range=0.06,
        fill_mode='nearest')

    #把圖片的整數結構轉成浮點型
    x = img_to_array(tmp)
    x = x.reshape((1,) + x.shape)
    i = 0
    '''
    接收numpy數組和標籤爲參數,生成經過數據提升或標準化後的batch數據,並在一個無限循環中不斷的返回batch數據
    '''
    for batch in datagen.flow(x, batch_size=1,  # save_to_dir 文件夾   prefix圖片名字   format格式
                              save_to_dir='images', save_prefix=name, save_format='jpg'):
        i += 1
        if i > 10:  # 如果不break會無限循環
            break  # otherwise the generator would loop indefinitely

    # cv2.imwrite("./out_data/" + name, tmp)

print("=====生成數據集======")
path_image=r'./images/'
list_path=os.listdir(path_image)
'''
生成訓練集和測試集的txt文件
'''
f1=open("./data_train.txt",'w')
f2=open("./data_test.txt",'w')

for i in list(list_path)[0:int(len(list_path)*0.8)]: #劃分80%訓練
    f1.write(""+str(i))
    label=list(i)[0:10]
    for j in label:
        if j=="_":
            f1.write(" " + str(11))
        else:
            f1.write(" "+str(int(j)+1))
    f1.write("\n")

for i in list(list_path)[int(len(list_path)*0.8):]:
    f2.write(""+str(i))
    label=list(i)[0:10]
    for j in label:
        if j=="_":
            f2.write(" " + str(11))
        else:
            f2.write(" "+str(int(j)+1))
    f2.write("\n")
print("數據集生成完畢")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章