亚洲综合伊人,成人欧美一区二区三区视频不卡,欧美日韩在线高清,日韩国产午夜一区二区三区,大胆美女艺术,一级毛片毛片**毛片毛片,你瞅啥图片

您當(dāng)前的位置是:  首頁(yè) > 新聞 > 文章精選 >
 首頁(yè) > 新聞 > 文章精選 >

教你如何結(jié)合的WebRTC與TensorFlow實(shí)現(xiàn)圖像檢測(cè)(上篇)

2018-01-10 13:56:18   作者:   來源:聲網(wǎng)Agora   評(píng)論:0  點(diǎn)擊:


  摘要:本文作者介紹了結(jié)合的WebRTC與TensorFlow實(shí)現(xiàn)圖像檢測(cè)的具體過程,不論對(duì)于TensorFlow的使用者,還是的WebRTC的開發(fā)者來講都有參考意義由于文章較長(zhǎng),我們將分為上下篇進(jìn)行連載。
  TensorFlow是目前最流行的機(jī)器學(xué)習(xí)框架之一。TensorFlow的一大優(yōu)勢(shì)是,它的很多庫(kù)都有人積極進(jìn)行維護(hù)和更新。而我最喜歡的其中一個(gè)庫(kù)就是TensorFlow 對(duì)象檢測(cè)API .Tensorflow對(duì)象檢測(cè)API可以對(duì)一張圖形上的多個(gè)對(duì)象進(jìn)行分類,并提供它們的具體位置。該API在將近1000個(gè)對(duì)象類上進(jìn)行了預(yù)先訓(xùn)練,可提供各種經(jīng)過預(yù)先訓(xùn)練的模型,讓你可以在速度與準(zhǔn)確性之間權(quán)衡取舍。
  有這些模型的指引固然很好,但所有這些模型都要使用圖像才能發(fā)揮作用,而這些圖像則需要你自行添加到一個(gè)文件夾中。我其實(shí)很想將其與實(shí)時(shí)的的WebRTC流配合到一起,通過網(wǎng)絡(luò)實(shí)現(xiàn)實(shí)時(shí)的計(jì)算機(jī)視覺。由于未能找到這方面的任何例子或指南,我決定寫這篇博文來介紹具體的實(shí)現(xiàn)方法。對(duì)于使用RTC的人,可以將本文作為一篇快速指南加以參考,了解如何使用TensorFlow來處理的WebRTC流。對(duì)于使用TensorFlow的人士,則可以將本文作為一份快速簡(jiǎn)介,了解如何向自己的項(xiàng)目中添加的WebRTC。使用的WebRTC的人需要對(duì)Python的比較熟悉。而使用TensorFlow的人則需要熟悉網(wǎng)絡(luò)交互和一些JavaScript的。
  本文不適合作為WebRTC或TensorFlow的入門指南使用。如需這樣的指南,應(yīng)參考TensorFlow 入門指南,WebRTC 入門指南等,網(wǎng)上的相關(guān)介紹與指南數(shù)不勝數(shù)。
  利用Tensor Flow和WebRTC檢測(cè)貓咪
  直接告訴我如何實(shí)現(xiàn)吧
  如果你來這里只是為了快速找到一些參考信息,或者懶得讀詳細(xì)的文字介紹,按照下面的方法即可快速著手。首先安裝Docker 。加載一個(gè)命令提示窗口,接著鍵入下面的命令:
  然后在瀏覽器地址欄中鍵入并轉(zhuǎn)到http:// localhost:5000 / local ,接受攝像頭權(quán)限請(qǐng)求,你應(yīng)該會(huì)看到類似下面的界面:
  基本架構(gòu)
  我們首先建立一個(gè)基本架構(gòu),用于在本地將一個(gè)本地網(wǎng)絡(luò)攝像頭流從WebRTC的getUserMedia 發(fā)送到一個(gè)Python服務(wù)器,這要用到Flask 網(wǎng)絡(luò)服務(wù)器和TensorFlow對(duì)象檢測(cè)API(Object Detection API)。具體的設(shè)置大致如下圖所示。
  為搭配使用的WebRTC與TensorFlow對(duì)象檢測(cè)API而建立的基本架構(gòu)
  Flask將提供html和JavaScript文件供瀏覽器呈現(xiàn)。getUserMedia.js負(fù)責(zé)抓取本地視頻流。接下來,objDetect.js將使用HTTP POST 方法向TensorFlow對(duì)象檢測(cè)API發(fā)送圖像,該API則返回它所有看到的對(duì)象(它稱之為“類”)及對(duì)象在圖像中的位置。我們會(huì)將這些詳細(xì)信息封裝到一個(gè)JSON對(duì)象中,然后將該對(duì)象發(fā)回給objDetect.js,這樣我們就能將我們所看到的對(duì)象的方框和標(biāo)簽顯示出來。
  配置
  設(shè)置和前提條件
  在開始之前,我們需要先對(duì)Tensorflow和對(duì)象檢測(cè)API進(jìn)行一些設(shè)置。
  使用泊塢輕松完成設(shè)置
  我在OSX,Windows 10和Raspbian已經(jīng)設(shè)置過好幾次(過程可不簡(jiǎn)單)。各種版本依賴關(guān)系錯(cuò)綜復(fù)雜,把這些關(guān)系理順并非易事,特別是當(dāng)你只是想看看一些前期工作是否行得通時(shí),你可能會(huì)感到氣餒。我推薦使用泊塢來避免這些棘手問題。你將需要學(xué)習(xí)泊塢,這也是非學(xué)不可的東西,與其試著構(gòu)建合適的的Protobuf 版本,倒不如花些時(shí)間學(xué)習(xí)它來得更為高效。TensorFlow項(xiàng)目維護(hù)了一些官方的Docker映像,比如tensorflow / tensorflow 。
  如果你使用泊塢窗,我們就可以使用我為這篇博文創(chuàng)建的映像在命令行中,請(qǐng)運(yùn)行以下命令:
  請(qǐng)注意,在Windows 10命令行中,請(qǐng)使用%cd%。
  ?吹竭@里,你應(yīng)該已經(jīng)進(jìn)入了碼頭工人容器現(xiàn)在,請(qǐng)運(yùn)行:
  這樣,就會(huì)使用最新的TensorFlow Docker映像,并將Docker主機(jī)上的端口5000連接到端口5000,將容器命名為tf-webrtchacks,將一個(gè)本地目錄映射到容器中的一個(gè)新/ code目錄,將該目錄設(shè)為默認(rèn)目錄(我們接下來將在該目錄中操作),然后運(yùn)行的bash以便進(jìn)行命令行交互。完成這些準(zhǔn)備工作后,我們才能開始。
  如果你才剛開始接觸TensorFlow,可能需要先按照噸ensorflow / tensorflow 中的說明運(yùn)行初始Jupyter筆記本,然后再回來執(zhí)行上述命令。
  另一種麻煩的實(shí)現(xiàn)方法
  如果你打算從頭開始,則需要安裝TensorFlow,它自己有很多依賴項(xiàng),比如Python.TensorFlow項(xiàng)目針對(duì)各種平臺(tái)都提供了指南,具體請(qǐng)?jiān)L問https://www.tensorflow.org/install 。對(duì)象檢測(cè)API有也。自己的安裝說明,以及一些額外的依賴項(xiàng)完成這些準(zhǔn)備工作后,請(qǐng)運(yùn)行下面的命令:
  這樣,就應(yīng)該安裝好了所有的Python的依賴項(xiàng),將相應(yīng)的Tensorflow對(duì)象檢測(cè)API文件都復(fù)制了過來,并安裝了Protobufs。如果這一步行不通,我建議檢查setup.py,然后手動(dòng)在其中運(yùn)行命令,以解決存在的任何問題。
  第1部分 - 確保Tensorflow正常工作
  為確保TensorFlow對(duì)象檢測(cè)API正常工作,我們首先從用于演示對(duì)象檢測(cè)的官方版本JupyterNotebook經(jīng)調(diào)整后的版本著手。我將此文件保存為object_detection_tutorial.py 。
  如果你剪切并粘貼該筆記本的每個(gè)部分,得到的結(jié)果應(yīng)如下所示:(由于此段代碼較長(zhǎng),截圖會(huì)影響閱讀,我們更換為文字排版,左右拖動(dòng)可查看長(zhǎng)代碼)
  # IMPORTS
  import numpy as np
  import os
  import six.moves.urllib as urllib
  import sys
  import tarfile
  import tensorflow as tf
  import zipfile
  from collections import defaultdict
  from io import StringIO
  # from matplotlib import pyplot as plt ### CWH
  from PIL import Image
  if tf.__version__ != '1.4.0':
  raise ImportError('Please upgrade your tensorflow installation to v1.4.0!')
  # ENV SETUP  ### CWH: remove matplot display and manually add paths to references
  '''
  # This is needed to display the images.
  %matplotlib inline
  # This is needed since the notebook is stored in the object_detection folder.
  sys.path.append("")
  '''
  # Object detection imports
  from object_detection.utils import label_map_util    ### CWH: Add object_detection path
  #from object_detection.utils import visualization_utils as vis_util ### CWH: used for visualization
  # Model Preparation
  # What model to download.
  MODEL_NAME = 'ssd_mobilenet_v1_coco_2017_11_17'
  MODEL_FILE = MODEL_NAME + '.tar.gz'
  DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/'
  # Path to frozen detection graph. This is the actual model that is used for the object detection.
  PATH_TO_CKPT = MODEL_NAME + '/frozen_inference_graph.pb'
  # List of the strings that is used to add correct label for each box.
  PATH_TO_LABELS = os.path.join('object_detection/data', 'mscoco_label_map.pbtxt') ### CWH: Add object_detection path
  NUM_CLASSES = 90
  # Download Model
  opener = urllib.request.URLopener()
  opener.retrieve(DOWNLOAD_BASE + MODEL_FILE, MODEL_FILE)
  tar_file = tarfile.open(MODEL_FILE)
  for file in tar_file.getmembers():
  file_name = os.path.basename(file.name)
  if 'frozen_inference_graph.pb' in file_name:
  tar_file.extract(file, os.getcwd())
  # Load a (frozen) Tensorflow model into memory.
  detection_graph = tf.Graph()
  with detection_graph.as_default():
  od_graph_def = tf.GraphDef()
  with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
  serialized_graph = fid.read()
  od_graph_def.ParseFromString(serialized_graph)
  tf.import_graph_def(od_graph_def, name='')
  # Loading label map
  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)
  # Helper code
  def load_image_into_numpy_array(image):
 。╥m_width, im_height) = image.size
  return np.array(image.getdata()).reshape(
 。╥m_height, im_width, 3)).astype(np.uint8)
  # Detection
  # For the sake of simplicity we will use only 2 images:
  # image1.jpg
  # image2.jpg
  # If you want to test the code with your images, just add path to the images to the TEST_IMAGE_PATHS.
  PATH_TO_TEST_IMAGES_DIR = 'object_detection/test_images' #cwh
  TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, 'image{}.jpg'.format(i)) for i in range(1, 3) ]
  # Size, in inches, of the output images.
  IMAGE_SIZE = (12, 8)
  with detection_graph.as_default():
  with tf.Session(graph=detection_graph) as sess:
  # Definite input and output Tensors for detection_graph
  image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
  # Each box represents a part of the image where a particular object was detected.
  detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
  # Each score represent how level of confidence for each of the objects.
  # Score is shown on the result image, together with the class label.
  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_path in TEST_IMAGE_PATHS:
  image = Image.open(image_path)
  # the array based representation of the image will be used later in order to prepare the
  # result image with boxes and labels on it.
  image_np = load_image_into_numpy_array(image)
  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
  image_np_expanded = np.expand_dims(image_np, axis=0)
  # Actual detection.
  (boxes, scores, classes, num) = sess.run(
  [detection_boxes, detection_scores, detection_classes, num_detections],
  feed_dict={image_tensor: image_np_expanded})
  ### CWH: below is used for visualizing with Matplot
  '''
  # Visualization of the results of a detection.
  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=IMAGE_SIZE)
  plt.imshow(image_np)
  '''
  在這里我就不再贅述實(shí)際TensorFlow代碼的作用了,這方面的信息可在Jupyter _ECSHOP演示及其他教程中找到。我將重點(diǎn)介紹我們對(duì)代碼所做的修改。
  我注釋了幾個(gè)小節(jié):
  更改了一些位置引用
  刪除了對(duì)Python matplot的所有引用。Python matplot用于在GUI環(huán)境中以可視化方式呈現(xiàn)輸出結(jié)果。在我的Docker環(huán)境中沒有設(shè)置它 - 根據(jù)你采用的具體運(yùn)行方式,可以酌情決定是否保留這些引用。
  對(duì)象檢測(cè)API的輸出結(jié)果
  正如第111行所示,對(duì)象檢測(cè)API輸出4種對(duì)象:
  • 類 - 一個(gè)由對(duì)象名組成的數(shù)組
  • 分值 - 一個(gè)由置信度分值組成的數(shù)組
  • 方框 - 檢測(cè)到的每個(gè)對(duì)象所在的位置
  • 數(shù)量 - 檢測(cè)到的對(duì)象總數(shù)
  類,分值和方框都是相互并列,大小相等的數(shù)組,因此類[N]與分?jǐn)?shù)[N]和盒[n]的都是一一對(duì)應(yīng)的。
  由于我刪去了可視化功能,我們需要通過某種方式來查看結(jié)果,所以我們要把下面的命令添加到文件末尾:
  第一個(gè)np.squeeze部分只是將多維數(shù)組輸出縮減成一維,這與原來的可視化代碼一樣。我認(rèn)為這是TensorFlow的一個(gè)副產(chǎn)品,因?yàn)樗ǔ?huì)輸出多維數(shù)組。
  接著我們要為它輸出的分值設(shè)置一個(gè)閾值。好像TensorFlow默認(rèn)會(huì)返回100個(gè)對(duì)象。其中很多對(duì)象嵌套在置信度更高的對(duì)象內(nèi)或與這些對(duì)象重疊。在選擇閾值方面我還沒有發(fā)現(xiàn)任何最佳做法,不過對(duì)于這些示例圖像來說,50%似乎是合適的。
  最后,我們需要循環(huán)遍歷這些數(shù)組,直接輸出那些超過閾值的分值。
  如果運(yùn)行下面的命令:
  應(yīng)該會(huì)獲得下面的輸出:
  第2部分 - 打造一項(xiàng)對(duì)象API網(wǎng)絡(luò)服務(wù)
  在這一部分,我們將對(duì)教程代碼作一些改動(dòng),以將其作為一項(xiàng)網(wǎng)絡(luò)服務(wù)加以運(yùn)行。我在Python方面的經(jīng)驗(yàn)頗為有限(主要在Raspberry Pi項(xiàng)目中使用過),所以如有不對(duì)的地方,添加請(qǐng)備注或提交拉取請(qǐng)求,以便我可以修正。
  2.1將演示代碼轉(zhuǎn)變成一項(xiàng)服務(wù)
  至此我們已經(jīng)讓TensorFlow Object API能夠正常工作了,接下來我們就將它封裝成一個(gè)可以調(diào)用的函數(shù)。我將演示代碼復(fù)制到了一個(gè)名為object_detection_api.py 的新python文件中。你可以看到,我刪除了很多沒有用到或注釋掉的行,以及用于將詳細(xì)信息輸出到控制臺(tái)的部分(暫時(shí)刪除)。
  由于我們要將這些信息輸出到網(wǎng)絡(luò)上,因此最好將我們的輸出結(jié)果封裝成一個(gè)JSON對(duì)象為此,請(qǐng)務(wù)必向你導(dǎo)入的內(nèi)容中添加一個(gè)importjso語句,然后再添加下面的命令:
  接下來,我們要重復(fù)利用之前的代碼創(chuàng)建一個(gè)get_objects函數(shù):
  在此函數(shù)中我們添加了一個(gè)圖像輸入?yún)?shù)和一個(gè)默認(rèn)為0.5的閾值。其余內(nèi)容都是在演示代碼的基礎(chǔ)上重構(gòu)的。
  現(xiàn)在我們?cè)傧虼撕瘮?shù)添加一些代碼,以查詢具體的值并將它們輸出到一個(gè)JSON對(duì)象中:
  這一次我們是使用對(duì)象類來創(chuàng)建一些初始元數(shù)據(jù)并將這些元數(shù)據(jù)添加到輸出列表中。然后我們使用循環(huán)向此列表中添加對(duì)象數(shù)據(jù)。最后,將此列表轉(zhuǎn)換成JSON并予以返回。
  之后,我們來創(chuàng)建一個(gè)測(cè)試文件(這里要提醒自己:先做測(cè)試),以檢查它是否調(diào)用了object_detection_test.py :
  至此萬事俱備,接下來就是運(yùn)行了。
  除了前面的控制臺(tái)輸出之外,你應(yīng)該還會(huì)看到一個(gè)JSON字符串:
  2.2添加一個(gè)網(wǎng)絡(luò)服務(wù)器
  我們已經(jīng)有了函數(shù) - 接下來我們就用它來打造一項(xiàng)網(wǎng)絡(luò)服務(wù)。
  先使用測(cè)試用的路由(路由)運(yùn)行
  我們有了一個(gè)可以輕松添加到網(wǎng)絡(luò)服務(wù)的良好API。我發(fā)現(xiàn)使用Flask 是最簡(jiǎn)單的測(cè)試方法。我們來創(chuàng)建一個(gè)server.py ,然后執(zhí)行一次快速測(cè)試:
  現(xiàn)在,運(yùn)行該服務(wù)器:
  確保該服務(wù)正常工作
  然后調(diào)用該網(wǎng)絡(luò)服務(wù)就我自己的情況而言,我只是從主機(jī)運(yùn)行了下面的命令(因?yàn)槲业牟磯]實(shí)例現(xiàn)在正在前臺(tái)運(yùn)行該服務(wù)器)。:
  。json.tool將幫助你為輸出結(jié)果設(shè)置格式你應(yīng)該會(huì)看到下面的結(jié)果:
  好了,接下來我們就要接受一個(gè)包含一個(gè)圖片文件及其他一些參數(shù)的POST,使用真實(shí)路由運(yùn)行了為此,需要在/測(cè)試路由函數(shù)下添加一個(gè)新的和/或圖像路由:
  這樣就會(huì)從一個(gè)采用表單編碼方式的POST中獲取圖片,并且可以選擇指定一個(gè)閾值,然后將該圖片傳遞給我們的object_detection_api。
  我們來測(cè)試一下:
  這時(shí)看到的結(jié)果應(yīng)該與上面使用/測(cè)試路徑時(shí)相同。繼續(xù)測(cè)試,可以指定你任選的其他本地圖像的路徑。
  讓該服務(wù)在本地主機(jī)以外的位置也能正常工作
  如果你打算在本地主機(jī)上運(yùn)行瀏覽器,可能就不需要再做些什么。但如果是真實(shí)的服務(wù),甚至是在需要運(yùn)行很多測(cè)試的情況下,這就不太現(xiàn)實(shí)了。如果要跨網(wǎng)絡(luò)運(yùn)行網(wǎng)絡(luò)服務(wù),或者使用其他資源運(yùn)行網(wǎng)絡(luò)服務(wù),都需要用到CORS幸好,在路由前添加以下代碼就可以輕松解決這一問題:
  讓該服務(wù)支持安全源
  最佳做法是搭配HTTPS使用的WebRTC,因?yàn)殂t和Safari瀏覽器等瀏覽器若不作專門配置,則僅支持安全源(不過鉻可以很好地支持本地主機(jī),你也可以將野生設(shè)為允許在非安全網(wǎng)站上捕獲信息-到跳轉(zhuǎn)此處。的調(diào)試工具部分了解詳情)為此,你需要獲取一些SSL證書或生成一些自托管證書我將我自己的證書放在了SSL /目錄中,然后將最后一行app.run更改為:
  如果你使用的是自簽名證書,你在使用卷曲進(jìn)行測(cè)試時(shí)可能需要添加--insecure選項(xiàng):
  • 嚴(yán)格來講并非一定要生成你自己的證書,而且這會(huì)增加一定的工作量,所以在server.py最底部,我依然讓SSL版本保持被注釋掉的狀態(tài)。
  • 如果是要投入生產(chǎn)環(huán)境中使用的應(yīng)用程序,你可能需要使用的nginx之類的代理向外發(fā)送HTTPS,同時(shí)在內(nèi)部依然使用HTTP(此外還要做很多其他方面的改進(jìn))。
  • 添加一些路由以便提供我們的網(wǎng)頁(yè)
  • 在開始介紹瀏覽器端的工作之前,我們先為后面需要用到的一些路由生成存根為此,請(qǐng)將下面的代碼放在索引()路由后面:
  • 蟒蛇方面的工作到此就結(jié)束了。接下來我們將用到的JavaScript,并且需要編寫一些HTML。
  • 我們將在下篇分享瀏覽器端的開發(fā),以及優(yōu)化方面經(jīng)驗(yàn)。
【免責(zé)聲明】本文僅代表作者本人觀點(diǎn),與CTI論壇無關(guān)。CTI論壇對(duì)文中陳述、觀點(diǎn)判斷保持中立,不對(duì)所包含內(nèi)容的準(zhǔn)確性、可靠性或完整性提供任何明示或暗示的保證。請(qǐng)讀者僅作參考,并請(qǐng)自行承擔(dān)全部責(zé)任。

專題

八宿县| 高州市| 崇义县| 阿拉善右旗| 随州市| 西青区| 金昌市| 建始县| 宁远县| 怀集县| 武宁县| 会宁县| 闻喜县| 木兰县| 云安县| 渝中区| 峨眉山市| 界首市| 蓝田县| 华宁县| 连云港市| 阜阳市| 铁力市| 安泽县| 上高县| 铁岭市| 武鸣县| 阜平县| 清徐县| 阿鲁科尔沁旗| 古田县| 滦南县| 神木县| 扶沟县| 榆林市| 岢岚县| 临高县| 西乡县| 界首市| 通许县| 新竹县|