python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集

achived發表於2021-08-15

現有條件:Mnist資料集,下載地址:跳轉 下載後的四個.gz檔案解壓後放到同一個資料夾下,如:/raw

Step 1:將Mnist資料集轉為jpg圖片(程式碼來自這篇部落格)

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集
 1 import os
 2 from skimage import io
 3 import torchvision.datasets.mnist as mnist
 4 
 5 root='./raw'
 6 train_set = (
 7     mnist.read_image_file(os.path.join(root, 'train-images.idx3-ubyte')),
 8     mnist.read_label_file(os.path.join(root, 'train-labels.idx1-ubyte'))
 9         )
10 test_set = (
11     mnist.read_image_file(os.path.join(root, 't10k-images.idx3-ubyte')),
12     mnist.read_label_file(os.path.join(root, 't10k-labels.idx1-ubyte'))
13         )
14 # print("training set :",train_set[0].size())
15 # print("test set :",test_set[0].size())
16 
17 def convert_to_img(train=True):
18     if(train):
19         f=open(root+'train.txt','w')
20         data_path=root+'/train/'
21         if(not os.path.exists(data_path)):
22             os.makedirs(data_path)
23         for i, (img,label) in enumerate(zip(train_set[0],train_set[1])):
24             img_path=data_path+str(i)+'.jpg'
25             # io.imsave(img_path,img.numpy())
26             f.write(img_path+' '+str(label)+'\n')
27         f.close()
28     else:
29         f = open(root + 'test.txt', 'w')
30         data_path = root + '/test/'
31         if (not os.path.exists(data_path)):
32             os.makedirs(data_path)
33         for i, (img,label) in enumerate(zip(test_set[0],test_set[1])):
34             img_path = data_path+ str(i) + '.jpg'
35             # io.imsave(img_path, img.numpy())
36             f.write(img_path + ' ' + str(label) + '\n')
37         f.close()
38 
39 convert_to_img(True)#轉換訓練集
40 convert_to_img(False)#轉換測試集
View Code

此時,轉換後的jpg儲存格式如下:

test和train中的圖片全是未按標籤分類的混合jpg圖片

Step 1.1: 將資料根據txt檔案按label分類

在train和test資料夾下分別手動建立10個資料夾,命名從0-9,如新建一個資料夾,資料夾名字為6

程式碼實現過程中由於有些需要重複操作,為了便於直接使用 我下面直接按使用步驟全部貼出(可能重複程式碼有點多,看懂後你可以直接修改

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集
 1 # 1.1.1 將train檔案中的tensor(換為=
 2     fileName = 'rawtrain.txt'
 3     f = open(fileName,'w')
 4     lines = f.readlines()
 5 
 6     for line in lines:
 7         f.write(line.replace("tensor(","="))
 8     f.close()
 9 # 1.1.2 將train檔案中的)去掉,不能同時執行tensor(和)的操作,必須順序執行
10     fileName = 'rawtrain.txt'
11     f = open(fileName,'w')
12     lines = f.readlines()
13 
14     for line in lines:
15         f.write(line.replace(")", ""))
16     f.close()
17 
18 # 1.1.3 將上述的檔名換為'rawtest.txt' 重複執行
19 
20 # 1.1.4 按rawtrain.txt檔案將圖片移動至對對應標籤的資料夾下
21     fileName = 'rawtrain.txt'
22     f = open(fileName,'r')
23     lines = f.readlines()
24     label = [-1]
25     f = open(fileName,'w')
26 
27     for line in lines:
28         splitL = line.split('=')
29         labelnum = int(splitL[1])
30         label.append(labelnum)
31     f.close()
32     del label[0]
33     #  此時label儲存圖片標籤
34 
35     # 讀取圖片並移動
36     root = './raw/train'
37     i = 0
38     lens = len(os.listdir(root))
39     while(lens > 10):
40         img_path = os.path.join(root, str(i)+'.jpg')
41         img_label = label[i]
42         img_new_path = os.path.join(root, str(img_label), str(i)+'.jpg')
43         shutil.move(img_path, img_new_path)
44         i += 1
45         lens = len(os.listdir(root))
46 
47 
48 # 1.1.5 按rawtest.txt檔案將圖片移動至對對應標籤的資料夾下
49     fileName = 'rawtest.txt'
50     f = open(fileName,'r')
51     lines = f.readlines()
52     label = [-1]
53     f = open(fileName,'w')
54 
55     for line in lines:
56         # f.write(line.replace("tensor(","="))
57         # f.write(line.replace(")", ""))
58         splitL = line.split('=')
59         labelnum = int(splitL[1])
60         label.append(labelnum)
61     f.close()
62     del label[0]
63     #  此時label儲存圖片標籤
64 
65     # 讀取圖片
66     root = './raw/test'
67     i = 0
68     lens = len(os.listdir(root))
69     while(lens > 10):
70         img_path = os.path.join(root, str(i)+'.jpg')
71         img_label = label[i]
72         img_new_path = os.path.join(root, str(img_label), str(i)+'.jpg')
73         shutil.move(img_path, img_new_path)
74         i += 1
75         lens = len(os.listdir(root))
View Code

 

Step 2: 將raw下的jpg圖片隨機分為10個資料集,每個資料集中的圖片數相同(包括train and test),並且每個資料集下的圖片按標籤分類

分類後的結構如下圖:

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集

程式碼實現:

Step 2.1:新建所需要的所有資料夾

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集
 1 root = './newDataSet/'
 2     for labelname in range(10):
 3         # domain
 4         domain_path = os.path.join(root, "domain"+str(labelname))
 5         # train / test
 6         for use2 in range(2):
 7             useName = ''
 8             if use2 == 0:
 9                 useName = 'train'
10             else:
11                 useName = 'test'
12             use_path = os.path.join(domain_path, useName)
13             # label
14             for i in range(10):
15                 label_path = os.path.join(use_path, str(i))
16                 if os.path.exists(label_path) != True:
17                     try:
18                         os.mkdir(label_path)  # 建立單層資料夾
19                     except Exception as e:
20                         os.makedirs(label_path)  # 建立多層資料夾
View Code

Step 2.2: 將raw下的資料按一定比例複製到新的資料夾下(我的程式碼下不同子資料集的訓練資料是來自train的每個標籤200張-無交叉,test每個標籤50張)

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集
 1    num = 0
 2     d_num = 0
 3     src_root = './raw/train'
 4     # src_root = './raw/test'  # 先執行train 執行結束後再註釋掉train 執行test圖片複製
 5     dst_root = './newDataSet/'
 6     aims = 'train'
 7     # aims = 'test'
 8     for label in os.listdir(src_root):  # 0
 9         label_path = os.path.join(src_root, label)
10         for img in os.listdir(label_path):  # 1.jpg
11             img_path = os.path.join(label_path, str(img))
12             img_new_path = os.path.join(dst_root, "domain"+str(d_num), aims, str(label), str(img))
13             shutil.copyfile(img_path, img_new_path)
14             num += 1
15             if num == 200:
16             # if num == 50:  # for test
17                 d_num += 1
18                 num = 0
19                 if d_num == 10:
20                     d_num = 0
21                     break
View Code

 

Step 3: 將raw下的jpg圖片分為10個資料集,每個資料集中的圖片數相同(包括train and test),並且每個資料集下的圖片僅包含一個標籤的圖片,雖然資料夾結構和第2步相同,但是,如/domain 8/train/1路徑下無圖片,僅/domain 8/train/8下有數字8的圖片,而domain0也僅是Label為0的資料夾下有數字為0的圖片

Step 3.1:新建所需的所有資料夾,程式碼參考Step 2.1 只是需要將root名稱換一個

Step 3.2: 將raw下資料按標籤和一定比例複製到新的資料夾下。

python 將Mnist資料集轉為jpg,並按比例/標籤拆分為多個子資料集
 1  num = 0
 2     # src_root = './raw/test'
 3     src_root = './raw/train'  # 對train檔案操作後需要對test檔案執行相同的操作
 4     dst_root = './newDatSet1/'
 5     aims = 'train'
 6     # aims = 'test'
 7     for label in os.listdir(src_root):  # 0
 8         label_path = os.path.join(src_root, label)
 9         for img in os.listdir(label_path):  # 1.jpg
10             img_path = os.path.join(label_path, str(img))
11             img_new_path = os.path.join(dst_root, "domain" + str(label), aims, str(label), str(img))
12             shutil.copyfile(img_path, img_new_path)
13             num += 1
14             if num == 2000:  # train資料為2k,測試資料為500,全部為一個Label的資料
15             # if num == 500:
16                 num = 0
17                 break
View Code

至此 兩個需要的新的拆分格式的資料集建立完畢。所有程式碼已經測試,均正常執行。

 

後續:我的方法好像有點繁瑣了...參考這篇tensorflow的部落格好像更簡單。。。

Step 2: 將raw下的jpg圖片隨機分為10個資料集,每個資料集中的圖片數相同(包括train and test),並且每個資料集下的圖片按標籤分類

相關文章