im2rec.py代码解读
生活随笔
收集整理的這篇文章主要介紹了
im2rec.py代码解读
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
im2rec.py解讀
直接給代碼,注釋我寫上了。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License.from __future__ import print_function import os import syscurr_path = os.path.abspath(os.path.dirname(__file__)) sys.path.append(os.path.join(curr_path, "../python")) import mxnet as mx import random import argparse import cv2 import time import tracebacktry:import multiprocessing except ImportError:multiprocessing = None#一個生成器,生成(圖片序號,路徑,圖片標簽) def list_image(root, recursive, exts): #root圖片根目錄 recursive是否遞歸遍歷(遞歸遍歷根目錄下的子目錄并為每個文件夾中的圖像指定一個唯一的標簽) exts支持圖片類型i = 0if recursive: #判遞歸 是:遞歸根目錄下每個文件夾,每個文件夾下的圖片一個標簽 否:不遞歸,同一標簽0cat = {}for path, dirs, files in os.walk(root, followlinks=True): #遞歸遍歷圖像目錄 (os.walk,文件遍歷器)dirs.sort()files.sort()for fname in files: #遍歷圖像文件fpath = os.path.join(path, fname)suffix = os.path.splitext(fname)[1].lower() #獲取文件擴展名(先分離文件命和文件擴展名,然后拿擴展名)if os.path.isfile(fpath) and (suffix in exts): #判:是否文件和是否為支持擴展名if path not in cat: #將不重復的路徑添加到字典中cat[path] = len(cat)yield (i, os.path.relpath(fpath, root), cat[path]) #生成(圖片序號,路徑,圖片標簽)i += 1for k, v in sorted(cat.items(), key=lambda x: x[1]):print(os.path.relpath(k, root), v)else:for fname in sorted(os.listdir(root)):fpath = os.path.join(root, fname)suffix = os.path.splitext(fname)[1].lower()if os.path.isfile(fpath) and (suffix in exts):yield (i, os.path.relpath(fpath, root), 0) #生成(圖片序號,路徑,圖片標簽0)i += 1#負責編寫.lst的內容 def write_list(path_out, image_list):with open(path_out, 'w') as fout:for i, item in enumerate(image_list):line = '%d\t' % item[0]for j in item[2:]:line += '%f\t' % jline += '%s\n' % item[1]fout.write(line)#生成xxx.lst文件,制作.lst的主函數 def make_list(args):image_list = list_image(args.root, args.recursive, args.exts)image_list = list(image_list)if args.shuffle is True: #是否打亂random.seed(100)random.shuffle(image_list)N = len(image_list)chunk_size = (N + args.chunks - 1) // args.chunks #args.chunks(塊數) chunk_size(塊大小)for i in range(args.chunks):chunk = image_list[i * chunk_size:(i + 1) * chunk_size]if args.chunks > 1:str_chunk = '_%d' % ielse:str_chunk = ''sep = int(chunk_size * args.train_ratio)sep_test = int(chunk_size * args.test_ratio)if args.train_ratio == 1.0: #全訓練集的情況write_list(args.prefix + str_chunk + '.lst', chunk)else: #劃分訓練集,驗證集,測試集if args.test_ratio:write_list(args.prefix + str_chunk + '_test.lst', chunk[:sep_test])if args.train_ratio + args.test_ratio < 1.0:write_list(args.prefix + str_chunk + '_val.lst', chunk[sep_test + sep:])write_list(args.prefix + str_chunk + '_train.lst', chunk[sep_test:sep_test + sep])#讀取.lst文件 def read_list(path_in):with open(path_in) as fin:while True:line = fin.readline()if not line:breakline = [i.strip() for i in line.strip().split('\t')]line_len = len(line)if line_len < 3:print('lst should at least has three parts, but only has %s parts for %s' %(line_len, line))continuetry:item = [int(line[0])] + [line[-1]] + [float(i) for i in line[1:-1]]except Exception as e:print('Parsing lst met error for %s, detail: %s' %(line, e))continueyield item#對圖像進行編碼或裁剪 def image_encode(args, i, item, q_out):fullpath = os.path.join(args.root, item[1])if len(item) > 3 and args.pack_label: #判斷是否將多維標簽保存header = mx.recordio.IRHeader(0, item[2:], item[0], 0)else:header = mx.recordio.IRHeader(0, item[2], item[0], 0)if args.pass_through: #是否跳過轉換并按原樣保存圖像try:with open(fullpath, 'rb') as fin:img = fin.read()s = mx.recordio.pack(header, img) #打包q_out.put((i, s, item)) #輸出except Exception as e:traceback.print_exc()print('pack_img error:', item[1], e)q_out.put((i, None, item))returntry: #不跳過編碼img = cv2.imread(fullpath, args.color)except:traceback.print_exc()print('imread error trying to load file: %s ' % fullpath)q_out.put((i, None, item))returnif img is None:print('imread read blank (None) image for file: %s' % fullpath)q_out.put((i, None, item))returnif args.center_crop: #是否裁剪中心圖像以使其為矩形if img.shape[0] > img.shape[1]:margin = (img.shape[0] - img.shape[1]) // 2;img = img[margin:margin + img.shape[1], :]else:margin = (img.shape[1] - img.shape[0]) // 2;img = img[:, margin:margin + img.shape[0]]if args.resize: #調整圖片大小(將圖像的較短邊緣調整為新大小)if img.shape[0] > img.shape[1]:newsize = (args.resize, img.shape[0] * args.resize // img.shape[1])else:newsize = (img.shape[1] * args.resize // img.shape[0], args.resize)img = cv2.resize(img, newsize)try:s = mx.recordio.pack_img(header, img, quality=args.quality, img_fmt=args.encoding) #打包(img_fmt:圖片編碼,jpg或png) (quality:編碼質量,jpge質量保存率,png壓縮率)q_out.put((i, s, item)) #輸出except Exception as e:traceback.print_exc()print('pack_img error on file: %s' % fullpath, e)q_out.put((i, None, item))return#讀取圖片數據函數,讀取制作rec需要的圖片(在使用多線程會用到) def read_worker(args, q_in, q_out):while True:deq = q_in.get()if deq is None:breaki, item = deqimage_encode(args, i, item, q_out)#寫函數,制作recIO(在使用多線程會用到) def write_worker(q_out, fname, working_dir):pre_time = time.time()count = 0fname = os.path.basename(fname)fname_rec = os.path.splitext(fname)[0] + '.rec'fname_idx = os.path.splitext(fname)[0] + '.idx'record = mx.recordio.MXIndexedRecordIO(os.path.join(working_dir, fname_idx),os.path.join(working_dir, fname_rec), 'w')buf = {}more = Truewhile more:deq = q_out.get()if deq is not None:i, s, item = deqbuf[i] = (s, item)else:more = Falsewhile count in buf:s, item = buf[count]del buf[count]if s is not None:record.write_idx(item[0], s)if count % 1000 == 0:cur_time = time.time()print('time:', cur_time - pre_time, ' count:', count)pre_time = cur_timecount += 1#腳本參數定義 def parse_args():parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,description='Create an image list or \make a record database by reading from an image list')parser.add_argument('prefix', help='prefix of input/output lst and rec files.') #輸出文件(.rec或.lst)的前綴,如 xxx.rec xxx.lstparser.add_argument('root', help='path to folder containing images.') #root 圖片文件夾cgroup = parser.add_argument_group('Options for creating image lists')cgroup.add_argument('--list', action='store_true',help='If this is set im2rec will create image list(s) by traversing root folder\and output to <prefix>.lst.\Otherwise im2rec will read <prefix>.lst and create a database at <prefix>.rec')cgroup.add_argument('--exts', nargs='+', default=['.jpeg', '.jpg', '.png'], #可接受圖像擴展名help='list of acceptable image extensions.')cgroup.add_argument('--chunks', type=int, default=1, help='number of chunks.')cgroup.add_argument('--train-ratio', type=float, default=1.0,help='Ratio of images to use for training.')cgroup.add_argument('--test-ratio', type=float, default=0,help='Ratio of images to use for testing.')cgroup.add_argument('--recursive', action='store_true',help='If true recursively walk through subdirs and assign an unique label\to images in each folder. Otherwise only include images in the root folder\and give them label 0.')cgroup.add_argument('--no-shuffle', dest='shuffle', action='store_false',help='If this is passed, \im2rec will not randomize the image order in <prefix>.lst')rgroup = parser.add_argument_group('Options for creating database')rgroup.add_argument('--pass-through', action='store_true',help='whether to skip transformation and save image as is')rgroup.add_argument('--resize', type=int, default=0,help='resize the shorter edge of image to the newsize, original images will\be packed by default.')rgroup.add_argument('--center-crop', action='store_true',help='specify whether to crop the center image to make it rectangular.')rgroup.add_argument('--quality', type=int, default=95,help='JPEG quality for encoding, 1-100; or PNG compression for encoding, 1-9')rgroup.add_argument('--num-thread', type=int, default=1,help='number of thread to use for encoding. order of images will be different\from the input list if >1. the input list will be modified to match the\resulting order.')rgroup.add_argument('--color', type=int, default=1, choices=[-1, 0, 1],help='specify the color mode of the loaded image.\1: Loads a color image. Any transparency of image will be neglected. It is the default flag.\0: Loads image in grayscale mode.\-1:Loads image as such including alpha channel.')rgroup.add_argument('--encoding', type=str, default='.jpg', choices=['.jpg', '.png'],help='specify the encoding of the images.')rgroup.add_argument('--pack-label', action='store_true',help='Whether to also pack multi dimensional label in the record file')args = parser.parse_args()args.prefix = os.path.abspath(args.prefix)args.root = os.path.abspath(args.root)return argsif __name__ == '__main__':args = parse_args()if args.list: #制作.lst文件make_list(args)else: #制作.rec文件if os.path.isdir(args.prefix): #獲取工作目錄working_dir = args.prefixelse:working_dir = os.path.dirname(args.prefix)files = [os.path.join(working_dir, fname) for fname in os.listdir(working_dir) #列表表達式(文件路徑)if os.path.isfile(os.path.join(working_dir, fname))]count = 0for fname in files: #在工作目錄下利用.lst文件生成.rec文件if fname.startswith(args.prefix) and fname.endswith('.lst'):print('Creating .rec file from', fname, 'in', working_dir)count += 1image_list = read_list(fname) # 讀取.lst文件# -- write_record -- #if args.num_thread > 1 and multiprocessing is not None: # 多線程生成.rec文件q_in = [multiprocessing.Queue(1024) for i in range(args.num_thread)]q_out = multiprocessing.Queue(1024)read_process = [multiprocessing.Process(target=read_worker, args=(args, q_in[i], q_out)) \for i in range(args.num_thread)]for p in read_process: # 啟動讀線程p.start()write_process = multiprocessing.Process(target=write_worker, args=(q_out, fname, working_dir)) # 以write_worker函數(方法)設置線程write_process.start() # 啟動寫線程for i, item in enumerate(image_list):q_in[i % len(q_in)].put((i, item))for q in q_in:q.put(None)for p in read_process:p.join()q_out.put(None)write_process.join()else:print('multiprocessing not available, fall back to single threaded encoding')try:import Queue as queueexcept ImportError:import queueq_out = queue.Queue() # 輸出隊列fname = os.path.basename(fname)fname_rec = os.path.splitext(fname)[0] + '.rec'fname_idx = os.path.splitext(fname)[0] + '.idx'record = mx.recordio.MXIndexedRecordIO(os.path.join(working_dir, fname_idx),os.path.join(working_dir, fname_rec), 'w')cnt = 0pre_time = time.time()for i, item in enumerate(image_list):image_encode(args, i, item, q_out) # 根據參數,編碼和裁剪圖片if q_out.empty():continue_, s, _ = q_out.get()record.write_idx(item[0], s)if cnt % 1000 == 0: # 執行進度打印cur_time = time.time()print('time:', cur_time - pre_time, ' count:', cnt)pre_time = cur_timecnt += 1if not count:print('Did not find and list file with prefix %s'%args.prefix)總結
以上是生活随笔為你收集整理的im2rec.py代码解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编民生“假政策”误导公众、造 AI“伪新
- 下一篇: xpath学习