上篇說明 Coral USB 加速器在樹梅派的安裝與使用 PyCoral 函式庫實作分類分類(Classification),但實在太久沒寫文章,上一篇文章寫得不甚好至今回頭修了好幾次,接著本篇則是實作另一個範例物件偵測(Object Detection)。
本社群由Nantou.py使用者社群以及南開科技大學福祉中心&USR辦公室負責維護,它是一群熱愛智慧生活科技以及Python的專業教師所組成,大家一同快樂地研究有關數位生活中人工智慧、大數據、物聯網、雲端服務、APPS、福祉科技、感知網路服務、車載網路服務、及網際網路等資通訊技術,並運用這些資通訊以及Pythoin技術來提升我們的日常生活品質,建立更好的生活環境。
上篇說明 Coral USB 加速器在樹梅派的安裝與使用 PyCoral 函式庫實作分類分類(Classification),但實在太久沒寫文章,上一篇文章寫得不甚好至今回頭修了好幾次,接著本篇則是實作另一個範例物件偵測(Object Detection)。
因全球晶片缺貨關係,最近單板電腦(raspberry pi、nvidia jetson nano、...)不是缺貨就是漲翻天,在農曆年前有機會入手 Google coral 裝置來練一下機器學習(Machine Learning, ML),順便也在久久...未出文章的部落格留個紀錄。
在這2022年的大年初一,敏哥想用WebAR技術把國立臺灣工藝研究發展中心2020年推出的樹藝生命之美年暦與智創虎年賀歲圖片結合在一起,虎哩幸福一整年,歡迎大家留意智創生活科技與樹藝工坊,將在3月份推出科技藝術種子教師培訓課程,完全是免費的喔!
1.準備作品與
準備樹藝生命之美年暦的電子檔,可以利用手機拍照。
2.準備智創虎年賀歲圖片檔(smartcreating.jpg)。
3.利用Image Targets Compiler編譯生命之美年暦的圖片檔,轉換成影像物件檔。
把生命之美年暦的圖片檔放到上圖Drop files to upload區。
按下上圖的Start鍵
按下上圖的Download compiled鍵,下載targets.mind,並自行建立一個資料夾,例如:TreeArt。
4.從https://hiukim.github.io/mind-ar-js-doc/quick-start/webpage,取得程式碼,並儲存AR html檔案。
5.開啟Web Server for Chrome,按下"啟用應用程式"。
6.按下上圖中"CHOOSE FOLDER",選擇儲存AR.html程式的資料夾TreeArt。
7.打開Chrome瀏覽器進行測試,http://127.0.0.1:8887/AR.html。
8.修改程式,儲存成AR2.html檔案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-image.prod.js"></script> <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-image-aframe.prod.js"></script> </head> <body> <a-scene mindar-image="imageTargetSrc: ./targets.mind;" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false"> <a-assets> <img id="smartcreating" crossorigin="anonymous" src="smartcreating.jpg"> </a-assets> <a-camera position="0 0 0" look-controls="enabled: false"></a-camera> <a-entity mindar-image-target="targetIndex: 0"> <a-image src="#smartcreating"></a-image> </a-entity> </a-scene> </body> </html> |
MindAR教學網站:https://hiukim.github.io/mind-ar-js-doc/face-tracking-quick-start/webpage
Flask教學網站:https://flask.palletsprojects.com/en/2.0.x/quickstart/#a-minimal-application
1. 安裝Flask套件,開啟cmd應用程式,輸入下列命令。
pip install Flask
2.使用IDLE來編輯程式,並儲存成test.html。
3.切換到工作目錄,使用python test.py來啟動網站。
4.開啟Chrome進行測試,並輸入127.0.0.1:5000。
5.編輯face_ar.html文件,並儲存在templates資料來中,範例程式摘自Minimal Example。
程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-face.prod.js"></script> <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-face-aframe.prod.js"></script> </head> <body> <a-scene mindar-face embedded color-space="sRGB" renderer="colorManagement: true, physicallyCorrectLights" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false"> <a-camera active="false" position="0 0 0"></a-camera> <a-entity mindar-face-target="anchorIndex: 1"> <a-sphere color="green" radius="0.1"></a-sphere> </a-entity> </a-scene> </body> </html> |
1 2 3 4 5 6 7 8 | from flask import Flask from flask import render_template app = Flask(__name__) @app.route("/") def hello_world(name=None): return render_template('face_ar.html', name=name) |
MindAR教學文件:https://hiukim.github.io/mind-ar-js-doc/face-tracking-quick-start/webpage
AFrame教學文件:https://aframe.io/
編輯工具:Notepad++
測試工具:Web Server for Chrome
1.利用Notepad++編輯程式,範例一:Minimal Example,原始程式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-face.prod.js"></script> <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-face-aframe.prod.js"></script> </head> <body> <a-scene mindar-face embedded color-space="sRGB" renderer="colorManagement: true, physicallyCorrectLights" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false"> <a-camera active="false" position="0 0 0"></a-camera> <a-entity mindar-face-target="anchorIndex: 1"> <a-sphere color="green" radius="0.1"></a-sphere> </a-entity> </a-scene> </body> </html> |
<a-scene>
屬性mindar-face說明是由
MindAR 引擎來控制這個場景,第13行<a-entity>
屬性 mindar-face-target="anchorIndex: 1",說明引
擎將跟踪特定的錨點位置-鼻尖。記得存成html文件,本範例為test2.html,並建立TreeArt資料夾。在2022年1月9日受邀參加"2022年南投縣文化資產學會第13屆第1次會員大會",這是一個很有文化內涵的學會,當天除了會員大會外,更安排國立台灣工藝研究發展中心主任張仁吉演講"台灣文化資產的價值與實踐"。
當天收到兩份很棒的工藝作品,其一是學會的藍染衣服,另一個是工藝中心的2022生命之美的年曆。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-image.prod.js"></script> <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/hiukim/mind-ar-js@1.0.0/dist/mindar-image-aframe.prod.js"></script> </head> <body> <a-scene mindar-image="imageTargetSrc: ./targets.mind;" vr-mode-ui="enabled: false" device-orientation-permission-ui="enabled: false"> <a-camera position="0 0 0" look-controls="enabled: false"></a-camera> <a-entity mindar-image-target="targetIndex: 0"> <a-plane color="blue" opaciy="0.5" position="0 0 0" height="0.552" width="1" rotation="0 0 0"></a-plane> </a-entity> </a-scene> </body> </html> |
原始程式:https://github.com/kosmosmo/NFT_Art_Generator
修訂的程式:黃底是有修訂部份,126-130行是把註解拿掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | project_folder = '<您的目錄>/NFT_Art_Generator-master/example/' total_art = 100 from collections import OrderedDict import os, json, random,cv2 import numpy as np def create_json(): layers_map = OrderedDict() my_layers = os.listdir(project_folder+'layers') for layer in my_layers: layers_map[layer] = {} pics = os.listdir(project_folder+'layers'+ '\\' + layer) temp = {'0_no_attributes':{'att_chance':1.0,'black_list_att':[]}} for p in pics: temp[p.split('.')[0]] = {'att_chance':1.0,'black_list_att':[]} layers_map[layer]['link_att'] = None layers_map[layer]['attributes'] = temp with open(project_folder + 'layers_map.json', 'w') as f: f.write(json.dumps(layers_map, indent=4, separators=(',', ': '), sort_keys=True)) return layers_map def get_weight(attributes): population = [] weight = [] for key,val in attributes.items(): population.append(key) weight.append(val['att_chance']) return [population,weight] def generate_att(): with open(project_folder + 'layers_map.json', 'r') as f: layers_map = json.load(f, object_pairs_hook=OrderedDict) attribute_map = OrderedDict() visited = set() i = 0 while i < total_art: print ('generating number ' + str(i)) temp = OrderedDict() atts = '' for key,val in layers_map.items(): if val['link_att'] == None: population, weights = get_weight(val['attributes']) random_pick = random.choices(population=population, weights=weights)[0] temp[key] = random_pick else: if temp[val['link_att']] in val['attributes']: temp[key] = temp[val['link_att']] else: temp[key] ='0_no_attributes' atts += key + ':' + temp[key]+ ',' if atts not in visited: visited.add(atts) attribute_map[i] = temp i += 1 with open(project_folder + 'attributes_map.json', 'w') as f: f.write(json.dumps(attribute_map, indent=4, separators=(',', ': '), sort_keys=True)) return attribute_map def generate_art(attribute_map=None): if not attribute_map: with open(project_folder + 'attributes_map.json', 'r') as f: attribute_map = json.load(f, object_pairs_hook=OrderedDict) for key,val in attribute_map.items(): print('generating img ' + key) img1 = np.zeros((1, 1,3), dtype=np.uint8) for key1,val1 in val.items(): if val1 == "0_no_attributes":continue img_path = project_folder + 'layers\\' +key1 + '\\' + val1 + ".png" fg = cv2.imread(img_path, -1) fg = cv2.cvtColor(fg, cv2.COLOR_RGB2RGBA) fgMask = fg[:, :, 3:] img = fg[:, :, :-1] bgMask = 255 - fgMask imgMask = cv2.cvtColor(fgMask, cv2.COLOR_GRAY2BGR) bgMask = cv2.cvtColor(bgMask, cv2.COLOR_GRAY2BGR) bgNew = (img1 * (1 / 255.0)) * (bgMask * (1 / 255.0)) imgNew = (img * (1 / 255.0)) * (imgMask * (1 / 255.0)) result = np.uint8(cv2.addWeighted(bgNew, 255.0, imgNew, 255.0, 0.0)) img1 = result """ # no compression cv2.imwrite(project_folder + 'outputs\\'+ key +'.png', img1) """ cv2.imwrite(project_folder + 'outputs\\'+ key + '.jpg', img1, [int(cv2.IMWRITE_JPEG_QUALITY), 90]) def generate_trait_data(): with open(project_folder + 'attributes_map.json', 'r') as f: attribute_map = json.load(f, object_pairs_hook=OrderedDict) trait_data_path = project_folder + 'outputs_data/' for key,val in attribute_map.items(): res = [] for k,v in val.items(): if v == "0_no_attributes":continue att = {} k = '_'.join(k.split('_')[1:]) att['trait_type'] = k att['value'] = v.replace('_', ' ') res.append(att) with open(trait_data_path + str(key) +'.json', 'w') as f: f.write(json.dumps(res, indent=4, separators=(',', ': '), sort_keys=True)) def slicing_dic(order_dic,start,end): list_dict = list(order_dic.items()) slice_dic = list_dict[start:end] res = OrderedDict(slice_dic) return (res) ''' from itertools import islice from multiprocessing import Process if __name__ == '__main__': with open(project_folder + 'attributes_map.json', 'r') as f: attribute_map = json.load(f, object_pairs_hook=OrderedDict) #attribute_map = slicing_dic(attribute_map,0,2000) # breaking the map into smaller chunks for render. def chunks(data, SIZE=100): it = iter(data) for i in range(0, len(data), SIZE): yield {k:data[k] for k in islice(it, SIZE)} for item in chunks(attribute_map): proc = Process(target=generate_art, args=(item,)) proc.start() ''' create_json() generate_att() generate_art() generate_trait_data() |