python二進位圖像數據集生成:bin和.h

2022-01-07 AI研修 潛水摸大魚

實現功能

    讀取圖像數據集,經預訓練模型提取特徵後,將特徵向量保存為二進位格式的embedding.bin和embedding.h文件,方便部署測試。

功能的整體框架


"""Script to generate Face Id embeddings"""import argparseimport os.path as pathfrom mtcnn.mtcnn import MTCNNfrom ai85.ai85_adapter import AI85SimulatorAdapterfrom utils import append_db_file_from_path, save_embedding_db, create_embeddings_include_file
CURRENT_DIR = path.abspath(path.dirname(path.abspath(__file__)))MODEL_PATH = path.join(CURRENT_DIR, 'model', 'ai85-streaming_seqfaceid_nobias_x6.pth.tar')

def create_db_from_folder(args): """ Main function of the script to generate face detector, AI85 simulator and calls the utility functions to generate embeddings and store them in required format. """     face_detector = MTCNN(image_size=80, margin=0, min_face_size=60, thresholds=[0.6, 0.8, 0.92], factor=0.85, post_process=True, device='cpu') ai85_adapter = AI85SimulatorAdapter(MODEL_PATH) embedding_db, _ = append_db_file_from_path(args.db, face_detector, ai85_adapter, db_dict=None, verbose=True) if not embedding_db: print(f'Cannot create a DB file. No face could be detected from the images in folder ', f'`{args.db}`') return     save_embedding_db(embedding_db, path.join(CURRENT_DIR, args.db_filename + '.bin'), add_prev_imgs=True)     create_embeddings_include_file(CURRENT_DIR, args.db_filename, args.include_path)

def parse_arguments(): """ Function to parse comman line arguments. """ parser = argparse.ArgumentParser(description='Create embedding database file.') parser.add_argument('--db', '-db-path', type=str, default='db', help='path for face images') parser.add_argument('--db-filename', type=str, default='embeddings', help='filename to store embeddings') parser.add_argument('--include-path', type=str, default='embeddings', help='path to include folder')
args = parser.parse_args() return args

def main(): """ Entry point of the script to parse command line arguments and run the function to generate embeddings. """ args = parse_arguments() create_db_from_folder(args)

if __name__ == "__main__": main()

其中,圖像讀入模型處理函數append_db_file_from_path如下:

def append_db_file_from_path(folder_path, mtcnn, ai85_adapter, db_dict=None, verbose=True,                             preview_images=False):    """Creates embeddings for each image in the given folder and appends to the existing embedding    dictionary    """    existing_db_dict = db_dict    db_dict = defaultdict(dict)    img_list = []    subj_id = 0    subject_list = sorted(os.listdir(folder_path))    for subject in subject_list:        print(f'Processing subject: {subject}')        img_id = 0        subject_path = os.path.join(folder_path, subject)        if not os.path.isdir(subject_path):            continue        if not os.listdir(subject_path):            subj_id += 1        for file in os.listdir(subject_path):            print(f'\tFile: {file}')            img_path = os.path.join(subject_path, file)            img_rot = get_image_rotation(img_path)            img = imread(img_path)            img = rotate_image(img, img_rot)            if img.dtype == np.float32:                img = (255 * img).astype(np.uint8)            img = get_face_image(img, mtcnn)            if img is not None:                if img.shape == (160, 120, 3):                    img_id += 1                    img = equalize_hist(img, 99)                    current_embedding = ai85_adapter.get_network_out(img)[:, :, 0, 0]                    current_embedding = current_embedding.astype(np.int8).flatten()                    img_list.append(img)                    db_dict[subject]['Embedding_%d' % img_id] = {'emb': current_embedding,                                                                 'img': img}        max_photo = 0    if verbose:        if existing_db_dict:            print('New entries for the DB')        else:            print('A new DB with')    for idx, subj in enumerate(db_dict.keys()):        if verbose:            print(f'\t{subj}: {len(db_dict[subj].keys())} images')        if len(list(db_dict[subj].keys())) > max_photo:            max_photo = len(list(db_dict[subj].keys()))    if verbose:        if existing_db_dict:            print('have been appended!')        else:            print('has been created!')
preview = None if preview_images: preview = 125*np.ones((len(db_dict.keys()) * 160, max_photo * 120, 3)) for idx, subj in enumerate(db_dict.keys()): start_y = 0 + idx * 160 start_x = 0 for img_ind in db_dict[subj].keys(): preview[start_y:start_y+160, start_x:start_x+120, :] = db_dict[subj][img_ind]['img'] start_x += 120 preview = preview.astype(np.uint8) if verbose: plt.figure(figsize=(1.5*max_photo, 2*len(db_dict.keys()))) plt.imshow(preview) plt.show()
if existing_db_dict: integrated_db = copy.deepcopy(existing_db_dict) for subj in db_dict.keys(): if subj in existing_db_dict.keys(): img_id = max(list(existing_db_dict[subj].keys())) + 1 for ind in db_dict[subj].keys(): integrated_db[subj]['Embedding_%d' % img_id] = integrated_db[subj][ind] img_id += 1 else: integrated_db[subj] = integrated_db[subj] db_dict = integrated_db
return db_dict, preview

提取到預處理圖像及其特徵嵌入,即可將其鍵值對存儲到二進位文件中,如下:

def save_embedding_db(emb_db, db_path, add_prev_imgs=False):    """    Saves embedding database in binary format    前面幾個是圖像和特徵嵌入的相關信息    The data in order:        1 byte : number of subjects (S)        2 bytes: length of embeddings (L)        2 bytes: number of embeddings (N)        2 bytes: length of image width (W)        2 bytes: length of image height (H)        2 bytes: length of subject names (K)        K bytes: subject names        (L+1)*N bytes: embeddings            1 byte : subject id            L bytes: embedding        (W*H*3)*N bytes: image    """
subject_names, subject_arr, embedding_arr, img_arr = create_data_arrs(emb_db, add_prev_imgs)
subject_arr = subject_arr.astype(np.uint8) embedding_arr = embedding_arr.astype(np.int8)
names_str = ' '.join(subject_names) names_bytes = bytearray() names_bytes.extend(map(ord, names_str))
S = np.unique(subject_arr).size K = len(names_bytes) N, L = embedding_arr.shape W = 120 H = 160
db_data = bytearray(np.uint8([S])) db_data.extend(L.to_bytes(2, 'big', signed=False)) db_data.extend(N.to_bytes(2, 'big', signed=False)) db_data.extend(W.to_bytes(2, 'big', signed=False)) db_data.extend(H.to_bytes(2, 'big', signed=False))
db_data.extend(K.to_bytes(2, 'big', signed=False)) db_data.extend(names_bytes)
for i, emb in enumerate(embedding_arr): db_data.extend(bytearray([subject_arr[i]])) db_data.extend(bytearray(emb))
if add_prev_imgs: for img in img_arr: db_data.extend(bytearray(img))
with open(db_path, 'wb') as file: file.write(db_data)
print(f'Binary embedding file is saved to "{db_path}".')

順便轉成.h文件,方便工程部署:

def create_embeddings_include_file(db_folder, db_filename, include_folder):    """Converts binary embedding to a .h file to compile as a C code.    """    db_path = os.path.join(db_folder, db_filename + '.bin')    data_bin = bytearray()
with open(db_path, "rb") as file: S = int.from_bytes(file.read(1), byteorder='big', signed=False) L = int.from_bytes(file.read(2), byteorder='big', signed=False) N = int.from_bytes(file.read(2), byteorder='big', signed=False) W = int.from_bytes(file.read(2), byteorder='big', signed=False) H = int.from_bytes(file.read(2), byteorder='big', signed=False) K = int.from_bytes(file.read(2), byteorder='big', signed=False)
subject_names_str = file.read(K).decode('ascii') subject_names_list = subject_names_str.split(' ') subject_names_str = '\0'.join(subject_names_list) + '\0'
names_bytes = bytearray() names_bytes.extend(map(ord, subject_names_str))
K = len(subject_names_str)
data_bin.extend(S.to_bytes(1, 'little', signed=False)) data_bin.extend(L.to_bytes(2, 'little', signed=False)) data_bin.extend(N.to_bytes(2, 'little', signed=False)) data_bin.extend(W.to_bytes(2, 'little', signed=False)) data_bin.extend(H.to_bytes(2, 'little', signed=False)) data_bin.extend(K.to_bytes(2, 'little', signed=False))
data_bin.extend(names_bytes)
for _ in range((L+1)*N): next_d = file.read(1) data_bin.extend(next_d)
data_arr = [] data_line = [] for next_d in data_bin: data_line.append(f'0x{next_d:02x}') if (len(data_line) % 18) == 0: data_arr.append(','.join(data_line)) data_line.clear()
data_arr.append(','.join(data_line)) data = ', \\\n '.join(data_arr)
db_h_path = os.path.join(include_folder, db_filename + '.h') with open(db_h_path, 'w') as h_file: h_file.write('#define EMBEDDINGS { \\\n ') h_file.write(data) h_file.write(' \\\n}')
print(f'Embedding file is saved to {db_h_path}')

相關焦點

  • 大跌眼鏡:python print竟然不能輸出二進位內容
    我在這個團隊裡面最主要的工作就是寫python代碼了,大家在文章中看到的代碼,很多都是我寫出來的哦。前幾天收到一個朋友的私信,他使用python開發cgi程序(這個方向實在是比較冷門),在讀取png文件並輸出的時候,遇到了讓人無法理解的兩個bug,小編花了一上午的時間,各種查資料,終於幫他解決了問題。
  • python安裝dlib庫的大坑
    (Newman clustering)18、RBF網絡(Radial Basis Function Networks,見附錄)19、多層感知器(Multi Layer perceptrons)二、數值算法三、圖模型接口算法四、圖片處理五、線程六、網絡七、圖形用戶接口八、數據壓縮與集成算法
  • 「python學習手冊-筆記」003.數值類型
    各種進位的表示python的整數默認採用十進位進行表示. 同樣,也支持二進位,八進位,十六進位的表示. **二進位:**0b或者0B開頭表示 **八進位:**0o或者0O開頭表示(注意第二個字符是字母o) **十六進位:**0x或者0X開頭表示 可以使用內置函數bin(I),oct(I),hex(I)來進行進位轉換.
  • 絕對收藏的Python小例子(上)
    十進位轉換為二進位:In [2]: bin(10)Out[2]: '0b1010'十進位轉換為八進位:In [3]: oct(9)Out[3]: '0o11'十進位轉換為十六進位:In [4]: hex(15)Out[4]: '0xf'
  • 三種用Python從圖像數據中提取特徵的技術
    全文共4073字,預計學習時長8分鐘你之前是否使用過圖像數據?也許你想建立自己的物體檢測模型,或者僅僅是想統計走進某棟建築物的人數,使用計算機視覺技術處理圖像擁有無窮無盡的可能性。但數據科學家最近有這樣一種研究趨勢,他們堅信,在處理非結構化數據(尤其是圖像數據)時,深度學習模型是不斷向前發展的。
  • Python中pip常見問題以及解決辦法
    原因是我習慣只鍵入pip,每個指南都使用pip命令,所以每次我想複製和粘貼命令時,我都要將pip修改為{{1浪費時間。當我輸入pip3時,我有一個pip的錯誤,這意味著不會執行pip: command not found命令。是否可以將pip分指向pip?
  • Python基本數據類型
    整數類型4種進位表示形式十進位:1010,99,-217二進位:以0b或0B開頭:0b101,-0B101八進位:以0o或0O開頭:0o123,-0O456十六進位:以0x或0X開頭:0x9a,-0X89浮點類型浮點數之間的運算存在不確定尾數 !
  • Python基礎教程(一) - 快速入門
    從今天開始學習python,會將學習到的相關知識整理到這裡。今後的所有內容都基於Ubuntu系統中進行的,和其他語言一樣,讓我們先來"Hello World!"吧。Hello world!#!/usr/bin/python為Linux系統下Python解釋器的路徑,通常python解釋器的路徑安裝在/usr/local/bin或/usr/bin目錄下。程序輸入和raw_input()內建函數從用戶得到數據輸入的最好方式使用raw_input()函數,它讀取標準輸入,並將讀取到的數據賦值給指定的變量。
  • 使用Python+OpenCV進行圖像處理(二)| 視覺入門
    我們必須格外注意的是:如果我們把邊緣檢測算法應用到高解析度的圖像上,我們就會得到很多我們不感興趣的檢測結果;相反,如果我們把圖像模糊太多,我們就會丟失數據。因此,我們需要找到一個適當的模糊量,從而不失去理想的邊緣。
  • Python實戰|8個常用的Python數據分析庫(附案例+源碼)
    提供了真正的數組功能以及對數據進行快速處理的函數,是Python中相當成熟和常用的庫。SciPy包含的功能有最優化、線性代數、積分、插值、擬合、特殊函數、快速傅立葉變換、信號處理和圖像處理、常微積分求解等其他科學與過程中常用的計算。
  • ...19感染者篩查;生成式摘要;圖像融合數據集;端到端臉部分析等
    目錄異常呼吸模式分類器可能有助於以準確和不顯眼的方式對COVID-19感染者進行大規模篩查基於單句和雙句打分的生成式摘要MFFW:一種新的多聚焦圖像融合數據集基於互連卷積神經網絡的端到端臉部分析AAAI2020
  • 生成的圖像數據集效果不好?也許你需要考慮內容分布的差異
    ,所以為了不斷提高模型表現,模型本身的設計和訓練數據擴增方面的研究也都非常多。對於圖像相關的任務,傳統上有基於變換的數據擴增方法,雷鋒網 AI 科技評論曾經介紹過谷歌式的暴力收集、有 Facebook 利用用戶上傳圖像的標籤,也有蘋果的生成並微調。生成數據的方法當然是最理想的,畢竟許多任務中所有有關的圖像加起來也沒有多少,而且生成數據的同時也直接獲得了真實標籤。
  • 使用OpenCV+Python進行圖像處理的初學者指南
    我們可以通過調用「cv2」模塊來導入包,如下所示:數字圖像可分為;彩色圖像、灰度圖像、二值圖像和多光譜圖像。彩色圖像包括每個像素的顏色信息。以灰色陰影作為唯一顏色的圖像是灰度圖像,而二值圖像正好有兩種顏色,主要是黑色和白色像素。多光譜圖像是在某些特定波長內捕獲跨越電磁光譜的圖像數據的圖像。
  • python圖像處理-gif動圖
    python圖像處理-1python圖像處理-批量生成純色圖片python圖像處理-添加文字python圖像處理-貼圖
  • C/C+編程筆記:C語言進位詳解,二進位、八進位和十六進位!
    二進位 我們不妨將思維拓展一下,既然可以用 0~9 共十個數字來表示數值,那麼也可以用0、1兩個數字來表示數值,這就是二進位(Binary)。例如,數字 0、1、10、111、100、1000001 都是有效的二進位。
  • 如何用二進位表示一張圖片
    因為每種基本色的強度最終也是用二進位去表示的。如果用2位二進位數去表示,那麼最多能表示4種強度(00,01,10,11),位數越多,能表達的等級就越多。那麼為什麼選擇了用8位二進位數去表示呢?這應該是一個經過考量後選的一個最合適的數字。如果選擇的位數太少,能表達的顏色十分有限。如果選擇的位數太多,誠然能表達更豐富的顏色,但是已經遠超普通人類能辨認的極限了,沒有意義,甚至還會造成存儲空間的浪費。
  • 基於Python生成鉛筆素描圖
    基於Python的鉛筆素描圖昝道廣概述前言思考彩色圖像和鉛筆素描對比素描一刻
  • python數據挖掘常用工具有哪幾種?
    python有強大的第三方庫,廣泛用於數據分析,數據挖掘、機器學習等領域,下面小編整理了python數據挖掘的一些常用庫,希望對各位小夥伴學習python數據挖掘有所幫助。1. Numpy能夠提供數組支持,進行矢量運算,並且高效地處理函數,線性代數處理等。
  • 大話二進位,八進位,十進位,十六進位之間的轉換
    還是和往常一樣,吃著抄手,討論著我們最近都在公司做什麼項目,一次無意的談話,他問我知道什麼是二進位麼,我說知道,他接著問,你知道怎麼用嗎,我說不知道,難道不會用二進位,還不能寫代碼了麼?說了這麼多畢竟丁大叔,還是那麼牛逼,只怪自己學而不精嘛,於是有了這篇文章。
  • 生成「貓狗版」川普,造假臉工具StarGANv2被玩壞,算法已開源
    但是Deepfake生成人臉違和感太強,GAN生成假臉又很難深度定製。現在來自韓國團隊開發的風格遷移模型StarGANv2可以完美解決這個問題。如果你是一個對GAN長期關注的同學,那麼一定還記得StarGAN,它是韓國高麗大學和Clova AI研究院在2017年底推出的風格遷移模型。