本篇文章是試圖幫助自己簡化 MaskRCNN 的執行流程,只想要輸入一張圖片,並回傳結果。
環境準備
- 安裝 CUDA,安裝對應 Tensorflow 版本的 CUDA。
對應的版本,請參考官方說明: https://www.tensorflow.org/install/source#gpu
本章節使用他人建置好的 MaskRCNN 環境: Tensorflow 2.0 ,所以安裝
CUDA 10.1 Update 2
並記得設定 CUDA_PATH
- (Windows 建議要做) 安裝 Anaconda 並安裝 Python 3.6
conda create -n mask_rcnn python=3.7 - 在 MaskRCNN 先前的 release 中 (46f8ea5) 下載 mask_rcnn_coco.h5 權重模型
https://github.com/matterport/Mask_RCNN/releases
環境建置
切換 conda 環境:
conda activate mask_rcnn
git clone 專案:
git clone https://github.com/akTwelve/Mask_RCNN.git aktwelve_mask_rcnn
在 aktwelve_mask_rcnn 目錄下安裝依賴套件:
pip install -r requirements.txt
在 aktwelve_mask_rcnn 目錄下安裝 mask_rcnn:
python setup.py clean --all install
應用 - 直接輸入圖片跟模型,得到輸出
想要直接看到輸出,只能用 Jupyter Notebook, 或是直接到 mask_rcnn/visualize.py 修改。
以下是,改動 15 - 17 行參數,並可以直接得到輸出結果的方式:
- INFERENCE_IMAGE: 要辨識的圖片
- WEIGHTS_PATH: mask_rcnn_coco.h5 權重模型 的位置
- MASK_RCNN_PROJECT_PATH: 剛才 clone 的 MaskRCNN 目錄
討論部分 - 執行多張圖片如何進行?
不要直接把上一個小節的 Code 全部包成 Function ,這樣的話每一次呼叫 Function 就會重新載入模型,會浪費很多計算成本,而且速度又非常的慢。
所以,可以直接用 cv 把圖片載入,丟到 Line:76 - Line 83 去執行,每次更改 results 辨識的結果就好。
討論部分 - 可以讓他輸出成圖片嗎? 如果只有 Jupyter-Notebook 能看到結果,那我可以用哪些參數?
想要輸出成圖片,可以直接去原本官方的 code (visualize.py) 複製 display_instance 的 function,然後把裡面的 plot 改成 save 就能儲存辨識的結果,可是,這可能不會是大多應用程式會需要的。
我們真正關心的是能不能拿到辨識後的標籤、方框位置、Shape(多邊形) 資料,而這些資料正是 Line 81 套用的 r['rois'], r['masks'], r['class_ids'], classes, r['scores']。
正如以下的程式碼,我直接拿 visualize.py 修改了一個可以直接存成圖片的 function,可以直接把這段 code 跟上面的 Inference code 放在一起。
import os
import sys
import random
import itertools
import colorsys
import numpy as np
from skimage.measure import find_contours
import matplotlib.pyplot as plt
from matplotlib import patches, lines
from matplotlib.patches import Polygon
import IPython.display
def saveimg(image, boxes, masks, class_ids, class_names,
scores=None, title="",
figsize=(16, 16), ax=None,
show_mask=True, show_bbox=True,
colors=None, captions=None,filename=None):
"""
boxes: [num_instance, (y1, x1, y2, x2, class_id)] in image coordinates.
masks: [height, width, num_instances]
class_ids: [num_instances]
class_names: list of class names of the dataset
scores: (optional) confidence scores for each box
title: (optional) Figure title
show_mask, show_bbox: To show masks and bounding boxes or not
figsize: (optional) the size of the image
colors: (optional) An array or colors to use with each object
captions: (optional) A list of strings to use as captions for each object
"""
# Number of instances
N = boxes.shape[0]
if not N:
print("\n*** No instances to display *** \n")
else:
assert boxes.shape[0] == masks.shape[-1] == class_ids.shape[0]
# If no axis is passed, create one and automatically call show()
auto_show = False
if not ax:
_, ax = plt.subplots(1, figsize=figsize)
auto_show = True
# Generate random colors
colors = colors or visualize.random_colors(N)
# Show area outside image boundaries.
height, width = image.shape[:2]
ax.set_ylim(height + 10, -10)
ax.set_xlim(-10, width + 10)
ax.axis('off')
ax.set_title(title)
masked_image = image.astype(np.uint32).copy()
for i in range(N):
color = colors[i]
# Bounding box
if not np.any(boxes[i]):
# Skip this instance. Has no bbox. Likely lost in image cropping.
continue
y1, x1, y2, x2 = boxes[i]
if show_bbox:
p = patches.Rectangle((x1, y1), x2 - x1, y2 - y1, linewidth=2,
alpha=0.7, linestyle="dashed",
edgecolor=color, facecolor='none')
ax.add_patch(p)
# Label
if not captions:
class_id = class_ids[i]
score = scores[i] if scores is not None else None
label = class_names[class_id]
caption = "{} {:.3f}".format(label, score) if score else label
else:
caption = captions[i]
ax.text(x1, y1 + 8, caption,
color='w', size=11, backgroundcolor="none")
# Mask
mask = masks[:, :, i]
if show_mask:
masked_image = visualize.apply_mask(masked_image, mask, color)
# Mask Polygon
# Pad to ensure proper polygons for masks that touch image edges.
padded_mask = np.zeros(
(mask.shape[0] + 2, mask.shape[1] + 2), dtype=np.uint8)
padded_mask[1:-1, 1:-1] = mask
contours = find_contours(padded_mask, 0.5)
for verts in contours:
# Subtract the padding and flip (y, x) to (x, y)
verts = np.fliplr(verts) - 1
p = Polygon(verts, facecolor="none", edgecolor=color)
ax.add_patch(p)
ax.imshow(masked_image.astype(np.uint8))
plt.savefig(filename)
在這裡可以注意到最後一行直接讓 plt 變成 savefig,如此一來原本的程式只要把 display_instances() 換成 saveimg 就行了。
原本的 visualize.display_instance 用法:
# Display results
ax = get_ax(1)
r = results[0]
visualize.display_instances(im, r['rois'], r['masks'], r['class_ids'],
classes, r['scores'], ax=ax,
title="Predictions"改成:
# Display results
ax = get_ax(1)
r = results[0]
saveimg(im, r['rois'], r['masks'], r['class_ids'],
classes, r['scores'], ax=ax,
title="Predictions",filename="./test.png")就會在指定路徑儲存了。
討論部分 - 針對原本的腳本執行,移植內容
在這邊,我直接移植了 classes, MaskRCNN 訓練都需要類別 (label) 的標籤,裡面是除了 'BG' (背景也是標籤) 以外,該模型訓練對應的標籤值,如果照原本官方的 sample 去跑,可能會需要下載到一個很大的 .json 檔案,裡面是放 coco 標記的資料,因為太麻煩,我就直接把所有標籤寫此在上面的工具中。
Reference:
https://www.immersivelimit.com/tutorials/mask-rcnn-for-windows-10-tensorflow-2-cuda-101
https://github.com/akTwelve/tutorials/blob/master/mask_rcnn/MaskRCNN_TrainAndInference.ipynb
https://www.itread01.com/content/1545048486.html

沒有留言:
張貼留言