摘要:classobjectDetectThread(QThread): objectSignal = pyqtSignal(str) def__init__(self): super().__init__() def run(self): detection_graph =EventHandlerData.detection_graph withdetection_graph.as_default(): withtf.Session(graph=detection_graph)assess: (im_width, im_height) =EventHandlerData.image.size image_np = np.array(EventHandlerData.image.getdata()).reshape((im_height, im_width,3)).astype(np.uint8) image_np_expanded = np.expand_dims(image_np,axis=0) image_tensor = detection_graph.get_tensor_by_name('image_tensor:0') boxes = detection_graph.get_tensor_by_name('detection_boxes:0') scores = detection_graph.get_tensor_by_name('detection_scores:0') classes = detection_graph.get_tensor_by_name('detection_classes:0') num_detections = detection_graph.get_tensor_by_name('num_detections:0') (boxes, scores, classes, num_detections) = sess.run( [boxes,scores,classes,num_detections], feed_dict={image_tensor: image_np_expanded}) objectText =[] # 如果識別概率大於百分之四十,我們就在文本框內顯示所識別物體 for i, cinenumerate(classes[0]): ifscores[0][i]>0.4 object =EventHandlerData.category_index[int(c)]['name'] ifobject notinobjectText: objectText.append(object) else: break self.objectSignal.emit(', '.join(objectText)) EventHandlerData.detectReady = True # 本幀圖片識別完,isImageDetect 字段置爲 True,再次開始讀取並轉換 Agora 遠端實時音視頻 EventHandlerData.isImageDetect = True。我們利用 Agora Python SDK 來完成音視頻的編解碼、降噪、回聲消除、低延時傳輸等任務,並將視頻圖像以 RGB 格式傳輸給 TensorFlow,然後我們通過 TensorFlow 來進行圖像識別,將識別結果返回給客戶端。

近兩年來,Python 在衆多編程語言中的熱度一直穩居前五,熱門程度可見一斑。 Python 擁有很活躍的社區和豐富的第三方庫,Web 框架、爬蟲框架、數據分析框架、機器學習框架等,開發者無需重複造輪子,可以用 Python 進行 Web 編程、網絡編程,開發多媒體應用,進行數據分析,或實現圖像識別等應用。其中圖像識別是最熱門的應用場景之一,也是與實時音視頻契合度最高的應用場景之一。

本文將分享 TensorFlow 圖像識別的實現。然後,我們嘗試將 TensorFlow 與 Agora Python SDK 結合,來實現在實時音視頻通話下的圖像識別。我們利用 Agora Python SDK 來完成音視頻的編解碼、降噪、回聲消除、低延時傳輸等任務,並將視頻圖像以 RGB 格式傳輸給 TensorFlow,然後我們通過 TensorFlow 來進行圖像識別,將識別結果返回給客戶端。

先分享一下 Demo 的識別效果。左圖是對端的視頻圖像,右下角是我們本地的視頻圖像,在識別對端圖像後,右側的文本框中會顯示出識別結果。注意,這個 貼紙只是後期 P 上去的,我們在 Demo 中還沒有加入貼圖的功能,如果你感興趣,可以試着在 Demo 基礎上做改進,豐富功能。

首先,我們還是要先介紹一下 TensorFlow 的圖像識別原理與方法。

TensorFlow 圖片及物體識別

TensorFlow 是 Google 的開源深度學習庫,你可以使用這個框架以及 Python 編程語言,構建大量基於機器學習的應用程序。而且還有很多人把 TensorFlow 構建的應用程序或者其他框架,開源發佈到 GitHub 上。所以我們今天主要基於 Tensorflow 學習下物體識別。

TensorFlow 提供了用於檢測圖片或視頻中所包含物體的 API, 詳情點擊此處。

物體檢測是檢測圖片中所出現的全部物體並且用矩形(Anchor Box)進行標註,物體的類別可以包括多種,例如人、車、動物、路標等。舉個例子瞭解 TensorFlow 物體檢測 API 的使用方法,這裏使用預訓練好的 ssd_mobilenet_v1_coco 模型(Single Shot MultiBox Detector),更多可用的物體檢測模型可以 點擊這裏

加載庫

複製代碼

# -*- coding:
utf-8-*-

importnumpyas
np
import
tensorflowastf
import
matplotlib.pyplotasplt
fromPILimport
Image

fromutils
importlabel_map_util
fromutils
importvisualization_utilsasvis_util

定義部分常量

複製代碼

PATH_TO_CKPT='ssd_mobilenet_v1_coco_2017_11_17/frozen_inference_graph.pb'
PATH_TO_LABELS='ssd_mobilenet_v1_coco_2017_11_17/mscoco_label_map.pbtxt'
NUM_CLASSES=90

加載預訓練好的模型

複製代碼

detection_graph = tf.Graph()
withdetection_graph.as_default():
od_graph_def = tf.GraphDef()
withtf.gfile.GFile(PATH_TO_CKPT, 'rb')asfid:
od_graph_def.ParseFromString(fid.read())
tf.import_graph_def(od_graph_def,name='')

加載分類標籤數據

複製代碼

label_map= label_map_util.load_labelmap(PATH_TO_LABELS)
categories= label_map_util.convert_label_map_to_categories(label_map,max_num_classes=NUM_CLASSES, use_display_name=True)
category_index= label_map_util.create_category_index(categories)

將圖片轉化爲數組,並測試圖片路徑

複製代碼

def load_image_into_numpy_array(image):
(im_width, im_height) =image.size
returnnp.array(image.getdata()).reshape((im_height, im_width,3)).astype(np.uint8)

TEST_IMAGE_PATHS = ['test_images/image1.jpg','test_images/image2.jpg']

使用模型進行物體檢測

複製代碼

withdetection_graph.as_default():
withtf.Session(graph=detection_graph)assess:
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
for image_pathinTEST_IMAGE_PATHS:
image =Image.open(image_path)
image_np = load_image_into_numpy_array(image)
image_np_expanded = np.expand_dims(image_np,axis=0)
(boxes, scores, classes, num) = sess.run(
[detection_boxes,detection_scores,detection_classes,num_detections],
feed_dict={image_tensor: image_np_expanded})

vis_util.visualize_boxes_and_labels_on_image_array(image_np,np.squeeze(boxes), np.squeeze(classes).astype(np.int32), np.squeeze(scores), category_index, use_normalized_coordinates=True, line_thickness=8)
plt.figure(figsize=[12,8])
plt.imshow(image_np)
plt.show()

檢測結果如下,第一張圖片檢測出了兩隻狗狗

實時音視頻場景下 Tensorflow 物體識別

既然 Tensorflow 在靜態圖片的物體識別已經相對成熟,那在現實場景中,大量的實時音視頻互動場景中,如何來做物體識別?我們現在基於聲網實時視頻的 SDK,闡述如何做物體識別。

首先我們瞭解視頻其實就是由一幀一幀的圖像組合而成,所以從這個層面來說,視頻中的目標識別就是從每一幀圖像中做目標識別,從這個層面上講,二者沒有本質區別。在理解這個前提的基礎上,我們就可以相對簡單地做實時音視頻場景下 Tensorflow 物體識別。

1)讀取 Agora 實時音視頻,截取遠端視頻流的圖片

複製代碼

defonRenderVideoFrame(uid, width, height, yStride,
uStride, vStride, yBuffer, uBuffer, vBuffer,
rotation, renderTimeMs, avsync_type):
# 用 isImageDetect 字段判斷前一幀圖像是否已完成識別,若完成置爲True, 執行以下代碼,執行完置爲 false
ifEventHandlerData.isImageDetect:
y_array = (ctypes.c_uint8 * (width * height)).from_address(yBuffer)
u_array = (ctypes.c_uint8 * ((width // 2) * (height // 2))).from_address(uBuffer)
v_array = (ctypes.c_uint8 * ((width // 2) * (height // 2))).from_address(vBuffer)

Y= np.frombuffer(y_array, dtype=np.uint8).reshape(height, width)
U= np.frombuffer(u_array, dtype=np.uint8).reshape((height // 2, width // 2)).repeat(2, axis=0).repeat(2, axis=1)
V= np.frombuffer(v_array, dtype=np.uint8).reshape((height // 2, width // 2)).repeat(2, axis=0).repeat(2, axis=1)
YUV= np.dstack((Y,U,V))[:height, :width, :]
#AI模型中大多數模型都是RGB格式訓練,聲網提供的視頻回調數據源是YUV格式,我們做下格式轉換
RGB= cv2.cvtColor(YUV, cv2.COLOR_YUV2RGB,3)
EventHandlerData.image =Image.fromarray(RGB)
EventHandlerData.isImageDetect =False

2)Tensorflow 對截取圖片進行物體識別

複製代碼

classobjectDetectThread(QThread):
objectSignal = pyqtSignal(str)
def__init__(self):
super().__init__()
def run(self):
detection_graph =EventHandlerData.detection_graph
withdetection_graph.as_default():
withtf.Session(graph=detection_graph)assess:
(im_width, im_height) =EventHandlerData.image.size
image_np = np.array(EventHandlerData.image.getdata()).reshape((im_height, im_width,3)).astype(np.uint8)
image_np_expanded = np.expand_dims(image_np,axis=0)
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
scores = detection_graph.get_tensor_by_name('detection_scores:0')
classes = detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
(boxes, scores, classes, num_detections) = sess.run(
[boxes,scores,classes,num_detections],
feed_dict={image_tensor: image_np_expanded})
objectText =[]
# 如果識別概率大於百分之四十,我們就在文本框內顯示所識別物體
for i, cinenumerate(classes[0]):
ifscores[0][i]>0.4
object =EventHandlerData.category_index[int(c)]['name']
ifobject notinobjectText:
objectText.append(object)
else:
break
self.objectSignal.emit(', '.join(objectText))
EventHandlerData.detectReady = True
# 本幀圖片識別完,isImageDetect 字段置爲 True,再次開始讀取並轉換 Agora 遠端實時音視頻
EventHandlerData.isImageDetect = True

我們已經將這個 Demo 以及 Agora Python SDK 上傳至 Github,大家可以直接下載使用: Agora Python TensorFlow Demo

Agora Python TensorFlow Demo 編譯指南

  • 點擊下載 Agora Python SDK
  • 若是 Windows,複製.pyd and .dll 文件到本項目文件夾根目錄;若是 IOS,複製.so 文件到本文件夾根目錄
  • 下載 Tensorflow 模型, 然後把 object_detection 文件複製. 到本文件夾根目錄
  • 安裝 Protobuf。然後運行:

複製代碼

protoc object_detection/protos/*.proto--python_out=.
  • 點擊下載預先訓練的模型
  • 推薦使用 ssd_mobilenet_v1_coco
    和 ssdlite_mobilenet_v2_coco,因爲他們相對運行較快
  • 提取 frozen graph, 命令行運行:

複製代碼

python extractGraph.py--model_file='FILE_NAME_OF_YOUR_MODEL'
  • 最後,在 callBack.py 中修改 model name,在 demo.py 中修改 Appid,然後運行即可

請注意,這個 Demo 僅作爲演示使用,從獲取到遠端實時視頻畫面,到 TensorFlow 進行識別處理,再到顯示出識別效果,期間需要 2 至 4 秒。不同網絡情況、設備性能、算法模型,其識別的效率也不同。感興趣的開發者可以嘗試更換自己的算法模型,來優化識別的延時。

如果 Demo 運行中遇到問題,請在 Github 直接提 issue。

作者介紹

金葉清,6 年研發運營經驗,從事開發者社區領域工作近五年。曾負責華爲開發者社區相關運營工作;目前就職於聲網,從事開發者佈道師工作。

相關文章