CV案例:應用Keras SSD進行物體檢測

ZSYL 2021-08-15 14:00:49 阅读数:453

本文一共[544]字,预计阅读时长:1分钟~
cv 案例 keras ssd

1. 案例效果

我們使用已經訓練過的模型進行加載之後,總共基礎訓練時有動物、載具等等共20個物體類別的訓練集。

以下是對沒有訓練過的圖像的檢測結果:

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

2. 案例需求

使用開源的SSD網絡結構進行檢測的是的代碼編寫,由於開源代碼使用 keras 編寫,沒有tf.keras版本,需要下載 keras-1.2.2 包

pip install keras==1.2.2
  • 使用SSD網絡模型,輸入圖片數據,處理圖片數據
  • 得到預測的類別和預測的比特置
  • 在圖片中顯示出來

3. 步驟分析以及代碼

  • 代碼結構:
    • ckpt:模型參數保存目錄
    • image:測試圖片
    • nets:模型網絡路徑
    • utils:公共組件(模型工具,BBox處理)

在這裏插入圖片描述

  • 定義好類別數量以及輸出
class SSDTrain(object):
def __init__(self):
self.classes_name = ['Aeroplane', 'Bicycle', 'Bird', 'Boat', 'Bottle',
'Bus', 'Car', 'Cat', 'Chair', 'Cow', 'Diningtable',
'Dog', 'Horse', 'Motorbike', 'Person', 'Pottedplant',
'Sheep', 'Sofa', 'Train', 'Tvmonitor']
self.classes_nums = len(self.classes_name) + 1
self.input_shape = (300, 300, 3)

3.1 模型預測流程

  • SSD300模型輸入以及加載參數

  • 讀取多個本地路徑測試圖片,preprocess_input以及保存圖像像素值(顯示需要)

  • 模型預測結果,得到7308個priorbox

  • 進行非最大抑制算法處理

  • SSD300模型輸入以及加載參數

    • by_name:按照每一層名字進行填充參數

    • If `by_name` is True, weights are loaded into layers
      only if they share the same name. This is useful
      for fine-tuning or transfer-learning models where
      some of the layers have changed.
      
model = SSD300(self.input_shape, num_classes=self.classes_nums)
model.load_weights('./ckpt/weights_SSD300.hdf5', by_name=True)
  • 讀取多個本地路徑測試圖片,preprocess_input以及保存圖像像素值(顯示需要)

需要使用

from keras.applications.imagenet_utils import preprocess_input
from keras.preprocessing.image import load_img, img_to_array
from scipy.misc import imread
import os
from nets.ssd_net import SSD300
from utils.ssd_utils import BBoxUtility

代碼:

# 循環讀取圖片進行多個圖片輸出檢測
feature = []
images = []
for pic_name in os.listdir("./image/"):
img_path = os.path.join("./image/", pic_name)
print(img_path)
# 讀取圖片
# 轉換成數組
# 模型輸入
img = load_img(img_path, target_size=(self.input_shape[0], self.input_shape[1]))
img = img_to_array(img)
feature.append(img)
images.append(imread(img_path))
# 處理圖片數據,ndarray數組輸入
inputs = preprocess_input(np.array(feature))
  • 模型預測結果,得到priorbox
# 預測
preds = model.predict(inputs, batch_size=1, verbose=1)
  • 進行非最大抑制算法處理
# 定義BBox工具
bbox_util = BBoxUtility(self.classes_nums)
# 使用非最大抑制算法過濾
results = bbox_util.detection_out(preds)
print(results[0].shape, results[1].shape)

3.2 圖片的檢測結果顯示

需要下載圖像顯示庫

pip install matplotlib
  • 對結果進行標記

    • 對每張圖片的中的物體的6個信息進行獲取
  • 1、先獲取每張圖片6列中的結果

for i, img in enumerate(images_data):
# 通過i獲取圖片label, location, xmin, ymin, xmax, ymax
pre_label = outputs[i][:, 0]
pre_conf = outputs[i][:, 1]
pre_xmin = outputs[i][:, 2]
pre_ymin = outputs[i][:, 3]
pre_xmax = outputs[i][:, 4]
pre_ymax = outputs[i][:, 5]
print("label:{}, probability:{}, xmin:{}, ymin:{}, xmax:{}, ymax:{}".
format(pre_label, pre_conf, pre_xmin, pre_ymin, pre_xmax, pre_ymax))
  • 2、過濾預測框到指定類別的概率小的 prior box
top_indices = [i for i, conf in enumerate(pre_conf) if conf >= 0.6]
top_conf = pre_conf[top_indices]
top_label_indices = pre_label[top_indices].tolist()
top_xmin = pre_xmin[top_indices]
top_ymin = pre_ymin[top_indices]
top_xmax = pre_xmax[top_indices]
top_ymax = pre_ymax[top_indices]
# print("pre_label:{}, pre_loc:{}, pre_xmin:{}, pre_ymin:{},pre_xmax:{},pre_ymax:{}".
# format(tag_label, tag_loc, tag_xmin, tag_ymin, tag_xmax, tag_ymax))

對結果進行標記-完整代碼:

def tag_picture(self, images, results):
""" 對圖片預測結果畫圖顯示 :param images: :param results: :return: """
for i, img in enumerate(images):
# 解析輸出結果,每張圖片的標簽,置信度和比特置
pre_label = results[i][:, 0]
pre_conf = results[i][:, 1]
pre_xmin = results[i][:, 2]
pre_ymin = results[i][:, 3]
pre_xmax = results[i][:, 4]
pre_ymax = results[i][:, 5]
print("label:{}, probability:{}, xmin:{}, ymin:{}, xmax:{}, ymax:{}".
format(pre_label, pre_conf, pre_xmin, pre_ymin, pre_xmax, pre_ymax))
# 過濾置信度低的結果
top_indices = [i for i, conf in enumerate(pre_conf) if conf >= 0.6]
top_conf = pre_conf[top_indices]
top_label_indices = pre_label[top_indices].tolist()
top_xmin = pre_xmin[top_indices]
top_ymin = pre_ymin[top_indices]
top_xmax = pre_xmax[top_indices]
top_ymax = pre_ymax[top_indices]
# 定義21中顏色,顯示圖片
# currentAxis增加圖中文本顯示和標記顯示
colors = plt.cm.hsv(np.linspace(0, 1, 21)).tolist()
plt.imshow(img / 255.)
currentAxis = plt.gca()
for i in range(top_conf.shape[0]):
xmin = int(round(top_xmin[i] * img.shape[1]))
ymin = int(round(top_ymin[i] * img.shape[0]))
xmax = int(round(top_xmax[i] * img.shape[1]))
ymax = int(round(top_ymax[i] * img.shape[0]))
# 獲取該圖片預測概率,名稱,定義顯示顏色
score = top_conf[i]
label = int(top_label_indices[i])
label_name = self.classes_name[label - 1]
display_txt = '{:0.2f}, {}'.format(score, label_name)
coords = (xmin, ymin), xmax - xmin + 1, ymax - ymin + 1
color = colors[label]
# 顯示方框
currentAxis.add_patch(plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2))
# 左上角顯示概率以及名稱
currentAxis.text(xmin, ymin, display_txt, bbox={
'facecolor': color, 'alpha': 0.5})
plt.show()

4. 完整代碼

"""SSD物體檢測案例"""
from computerVision.nets.ssd_net import SSD300
from computerVision.utils.ssd_utils import BBoxUtility
from tensorflow.python.keras.preprocessing.image import load_img, img_to_array
from tensorflow.python.keras.applications.imagenet_utils import preprocess_input
import matplotlib.pyplot as plt
from imageio import imread
import numpy as np
import os
""" - 定義好類別數量以及輸出 - 模型預測流程 - SSD300模型輸入以及加載參數 - 讀取多個本地路徑測試圖片,preprocess_input以及保存圖像像素值(顯示需要) - 模型預測結果,得到7308個priorbox - 進行非最大抑制算法處理 - 圖片的預測結果顯示 """
class SSDTest(object):
def __init__(self):
# 定義識別類別
self.classes_name = ['Aeroplane', 'Bicycle', 'Bird', 'Boat', 'Bottle',
'Bus', 'Car', 'Cat', 'Chair', 'Cow', 'Diningtable',
'Dog', 'Horse', 'Motorbike', 'Person', 'Pottedplant',
'Sheep', 'Sofa', 'Train', 'Tvmonitor']
# 定義模型的輸入參數 + 1 背景
self.classes_nums = len(self.classes_name) + 1
self.input_shape = (300, 300, 3)
def test(self):
""" 對於輸入圖片進行預測物體比特置 :return: """
# - SSD300模型輸入以及加載參數
model = SSD300(self.input_shape, num_classes=self.classes_nums)
model.load_weights('./ckpt/weights_SSD300.hdf5', by_name=True) # 按照名字加載參數
# 模型特征
feature = []
images_data = []
# - 讀取多個本地路徑測試圖片,preprocess_input以及保存圖像像素值(顯示需要)
for path in os.listdir('./images'):
img_path = os.path.join('./images/', path)
# 1. 輸入到SSD網絡中,數組
image = load_img(img_path, target_size=(self.input_shape[0], self.input_shape[1]))
image = img_to_array(image)
feature.append(image)
# 2. 讀取圖片二進制數據,matplotlib顯示使用
images_data.append(imread(img_path))
# - 模型預測結果,得到7308個priorbox
# 圖片特征處理
inputs = preprocess_input(np.asarray(feature))
# print(inputs)
predict = model.predict(inputs)
# (2, 7308, 33) 2代錶圖片數量,7308代錶每個圖片預測的default boxes數量,33: 4(比特置)+ 21(預測概率) + 8(其他default boxes參數)
print(predict.shape)
# - 進行非最大抑制算法處理NMS 21類別
bb = BBoxUtility(self.classes_nums)
res = bb.detection_out(predict) # 將圖片解析格式
# (200, 6) (200, 6)
print(res[0].shape, res[1].shape)
# 200個候選框,每個候選框比特置,類別
return res, images_data
def tag_picture(self, images_data, outputs):
""" 顯示預測結果到圖片中 :return: """
# 1. 獲取每張圖片的預測結果中的值
for i, img in enumerate(images_data):
# 獲取res當中對應的記過label,location,xmin,ymin,xmax,ymax
pre_label = outputs[i][:, 0]
pre_conf = outputs[i][:, 1]
pre_xmin = outputs[i][:, 2]
pre_ymin = outputs[i][:, 3]
pre_xmax = outputs[i][:, 4]
pre_ymax = outputs[i][:, 5]
# print('pre_label:{}, pre_conf:{}, pre_xmin:{}, pre_ymin:{}, pre_xmax:{}, pre_ymax:{}'.
# format(pre_label, pre_conf, pre_xmin, pre_ymin, pre_xmax, pre_ymax))
# 由於檢測出的物體還是很多,所以進行顯示過濾(%90)
top_indices = [i for i, conf in enumerate(pre_conf) if conf > 0.6]
top_conf = pre_conf[top_indices]
top_label_indices = pre_label[top_indices].tolist()
top_xmin = pre_xmin[top_indices]
top_ymin = pre_ymin[top_indices]
top_xmax = pre_xmax[top_indices]
top_ymax = pre_ymax[top_indices]
print('after filter top_label_indices:{}, top_conf:{}, top_xmin:{}, top_ymin:{}, top_xmax:{}, top_ymax:{}'.
format(top_label_indices, top_conf, top_xmin, top_ymin, top_xmax, top_ymax))
# matplotlib畫圖顯示結果
# 定義21中顏色,顯示圖片
# currentAxis增加圖中文本顯示和標記顯示
colors = plt.cm.hsv(np.linspace(0, 1, 21)).tolist()
plt.imshow(img / 255.)
currentAxis = plt.gca()
for i in range(top_conf.shape[0]):
xmin = int(round(top_xmin[i] * img.shape[1]))
ymin = int(round(top_ymin[i] * img.shape[0]))
xmax = int(round(top_xmax[i] * img.shape[1]))
ymax = int(round(top_ymax[i] * img.shape[0]))
# 獲取圖片預測概率,名稱,定義顯示顏色
score = top_conf[i]
label = int(top_label_indices[i])
label_name = self.classes_name[label - 1]
diplay_test = '{:0.2f}, {}'.format(score, label_name)
coords = (xmin, ymin), xmax - xmin + 1, ymax - ymin + 1
color = colors[label]
# 顯示方框
currentAxis.add_patch(plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2))
# 左上角顯示概率以及名稱
currentAxis.text(xmin, ymin, diplay_test, bbox={
'facecolor': color, 'alpha': 0.5})
plt.show()
return None
if __name__ == '__main__':
ssd = SSDTest()
outputs, images_data = ssd.test()
# 圖片的預測結果顯示
ssd.tag_picture(images_data, outputs)

加油!

感謝!

努力!

版权声明:本文为[ZSYL]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815140041127y.html