1. 程式人生 > >利用 ImageAI 在 COCO 上學習目標檢測

利用 ImageAI 在 COCO 上學習目標檢測

ImageAI是一個python庫,旨在使開發人員能夠使用簡單的幾行程式碼構建具有包含深度學習和計算機視覺功能的應用程式和系統。 這個 AI Commons 專案https://commons.specpal.science 由 Moses Olafenwa 和 John Olafenwa 開發和維護。為了更好的使用 ImageAI,我將其 Fork 到 CodeXZone/ImageAI。同時,ImageAI 也提供了中文手冊:imageai。下面我將藉助該教程一步一步的學習目標檢測。

利用 cocoz 載入 COCO 資料集

首先,利用 cocoz 載入 COCOZ:

import sys
# 將 cocoapi 新增進入環境變數
sys.path.append(r'D:\API\cocoapi\PythonAPI')
from pycocotools.cocoz import AnnZ, ImageZ, COCOZ
# ------------------

import numpy as np
from matplotlib import pyplot as plt
from IPython import display


def use_svg_display():
    # 用向量圖顯示, 效果更好
    display.set_matplotlib_formats('svg')


def show_imgs(imgs, k=4):
    '''
    展示 多張圖片
    '''
    n = len(imgs)
    h, w = k, n // k
    assert n == h * w, "圖片數量不匹配"
    use_svg_display()
    _, ax = plt.subplots(h, w, figsize=(5, 5))  # 設定圖的尺寸
    K = np.arange(n).reshape((h, w))
    for i in range(h):
        for j in range(w):
            img = imgs[K[i, j]]
            ax[i][j].imshow(img)
            ax[i][j].axes.get_yaxis().set_visible(False)
            ax[i][j].set_xticks([])
    plt.show()
dataDir = r'E:\Data\coco\images'   # COCO 資料根目錄
dataType = 'train2017'
imgZ = ImageZ(dataDir, dataType)

show_imgs(imgZ[300:316])

物體檢測,提取和微調

import sys
sys.path.append('D:/API/ImageAI')

from imageai.Detection import ObjectDetection
import os

execution_path = os.getcwd()

detector = ObjectDetection()  # 建立目標檢測例項
detector.setModelTypeAsRetinaNet()
detector.setModelPath(
    os.path.join(execution_path, "resnet50_coco_best_v2.0.1.h5"))
detector.loadModel()  # 載入預訓練模型

由於 detector.detectObjectsFromImage 比較容易支援解壓後的圖片,所以我們可以提取出一張圖片來做測試:

input_image = imgZ.Z.extract(imgZ.names[0]) # 輸入檔案的路徑
output_image = os.path.join(execution_path, "image2new.jpg")  # 輸出檔案的路徑

detections = detector.detectObjectsFromImage(
    input_image=input_image, output_image_path=output_image)

for eachObject in detections:
    print(eachObject["name"] + " : ", eachObject["percentage_probability"])
    print("--------------------------------")
motorcycle :  99.99607801437378
--------------------------------

detectObjectsFromImage() 函式返回一個字典列表,每個字典包含影象中檢測到的物件資訊,字典中的物件資訊有 name(物件類名)和 percentage_probability(概率)以及 box_points(圖片的左上角與右下角的座標)。

detections
[{'name': 'motorcycle',
  'percentage_probability': 99.99607801437378,
  'box_points': array([ 34,  92, 546, 427])}]

下面我們看看其標註框:

img = plt.imread(output_image)
plt.imshow(img)
plt.show()

為了直接使用壓縮檔案,我們可以修改 detectObjectsFromImage 的預設引數 input_type='file'input_type='array'

input_image = imgZ[202]  # 輸入檔案的路徑
output_image = os.path.join(execution_path, "image2.jpg")  # 輸出檔案的路徑

detections = detector.detectObjectsFromImage(
    input_image=input_image, output_image_path=output_image, input_type='array')

for eachObject in detections:
    print(eachObject["name"] + " : ", eachObject["percentage_probability"])
    print("--------------------------------")

img = plt.imread(output_image)
plt.imshow(img)
plt.show()
tennis racket :  54.25310730934143
--------------------------------
person :  99.85058307647705
--------------------------------

detections, objects_path = detector.detectObjectsFromImage(
    input_image=imgZ[900], input_type = 'array',
    output_image_path=os.path.join(execution_path, "image3new.jpg"),
    extract_detected_objects=True)

for eachObject, eachObjectPath in zip(detections, objects_path):
    print(eachObject["name"] + " : ", eachObject["percentage_probability"])
    print("Object's image saved in ", eachObjectPath)
    print("--------------------------------")
person :  56.35678172111511
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\person-1.jpg
--------------------------------
person :  75.83483457565308
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\person-2.jpg
--------------------------------
person :  60.49004793167114
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\person-3.jpg
--------------------------------
person :  85.2730393409729
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\person-4.jpg
--------------------------------
person :  83.12703967094421
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\person-5.jpg
--------------------------------
bus :  99.7751772403717
Object's image saved in  D:\API\CVX\draft\image3new.jpg-objects\bus-6.jpg
--------------------------------

extract_detected_objects=True 將會把檢測到的物件提取並儲存為單獨的影象;這將使函式返回 2 個值,第一個是字典陣列,每個字典對應一個檢測到的物件資訊,第二個是所有提取出物件的影象儲存路徑,並且它們按照物件在第一個陣列中的順序排列。我們先看看原圖:

plt.imshow(imgZ[900])
plt.show()

顯示識別出來的物件:

show_imgs([plt.imread(fname) for fname in objects_path], 2)

還有一個十分重要的引數 minimum_percentage_probability 用於設定預測概率的閾值,其預設值為 50(範圍在 \(0-100\)之間)。如果保持預設值,這意味著只有當百分比概率大於等於 50 時,該函式才會返回檢測到的物件。使用預設值可以確保檢測結果的完整性,但是在檢測過程中可能會跳過許多物件。下面我們看看修改後的效果:

detections = detector.detectObjectsFromImage(
    input_image=imgZ[900],
    input_type='array',
    output_image_path=os.path.join(execution_path, "image3new.jpg"),
    minimum_percentage_probability=70)

for eachObject in detections:
    print(eachObject["name"] + " : ", eachObject["percentage_probability"])
    print("--------------------------------")
person :  75.83483457565308
--------------------------------
person :  85.2730393409729
--------------------------------
person :  83.12703967094421
--------------------------------
bus :  99.7751772403717
--------------------------------

我們將 minimum_percentage_probability 設定為 70,此時僅僅只能檢測到 4 個。