<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于OpenCV與tensorflow實(shí)現(xiàn)實(shí)時手勢識別

          共 15372字,需瀏覽 31分鐘

           ·

          2021-08-20 22:57

          點(diǎn)擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時間送達(dá)

          干貨-閱讀需10分鐘左右


          基于OpenCV與tensorflow object detection API使用遷移學(xué)習(xí),基于SSD模型訓(xùn)練實(shí)現(xiàn)手勢識別完整流程,涉及到數(shù)據(jù)集收集與標(biāo)注、VOC2012數(shù)據(jù)集制作,tfrecord數(shù)據(jù)生成、SSD遷移學(xué)習(xí)與模型導(dǎo)出,OpenCV攝像頭實(shí)時視頻流讀取與檢測處理,整個過程比較長,操作步驟比較多,這里說一下主要階段與關(guān)鍵注意點(diǎn)。

          第一階段:數(shù)據(jù)收集與數(shù)據(jù)標(biāo)注
          第二階段:VOC2012數(shù)據(jù)集與訓(xùn)練集制作
          第三階段:基于SSD模型的遷移學(xué)習(xí)
          第四階段:模型導(dǎo)出與使用


          數(shù)據(jù)收集與數(shù)據(jù)標(biāo)注


          手勢數(shù)據(jù)收集,我通過OpenCV程序打開了一個攝像頭,在攝像頭前面我嘗試了三種手勢變換,分別是,我讓OpenCV在讀取視頻流的過程中,對每一幀數(shù)據(jù)進(jìn)行了保存,最終挑選得到1000張手勢數(shù)據(jù)。OpenCV打開攝像頭與保存手勢圖像的代碼如下:


          import cv2 as cv

          # image = cv.imread("D:/vcprojects/images/three.png")
          capture = cv.VideoCapture("D:/vcprojects/images/visit.mp4")
          detector = cv.CascadeClassifier(cv.data.haarcascades + "haarcascade_frontalface_alt.xml")
          while True:
              ret, image = capture.read()
              if ret is True:
                  cv.imshow("frame", image)
                  faces = detector.detectMultiScale(image, scaleFactor=1.05, minNeighbors=1,
                                                    minSize=(3030), maxSize=(120120))
                  for x, y, width, height in faces:
                      cv.rectangle(image, (x, y), (x+width, y+height), (00255), 2, cv.LINE_8, 0)
                  cv.imshow("faces", image)
                  c = cv.waitKey(50)
                  if c == 27:
                      break
              else:
                  break

          cv.destroyAllWindows()

          最終我去掉一些模糊過度的圖像,生成的手勢圖像部分?jǐn)?shù)據(jù)如下:


          數(shù)據(jù)標(biāo)注


          數(shù)據(jù)標(biāo)注我選擇使用labelImg工具,它的GITHUB地址如下:

          https://github.com/tzutalin/labelImg
          每標(biāo)注一張圖像保存時候它就會生成一個對應(yīng)的xml文件,這些XML文件格式符合PASCAL VOC2012格式,也是ImageNet中數(shù)據(jù)集的標(biāo)準(zhǔn)格式。打開標(biāo)注的界面如下:

          我通過此工具標(biāo)注了900張圖像,完成了Demo程序整個數(shù)據(jù)標(biāo)注工作。

          VOC2012數(shù)據(jù)集制作與訓(xùn)練集生成


          有了標(biāo)注好的數(shù)據(jù)XML文件與圖像文件之后,這里需要完成下面幾件事情才可以制作生成標(biāo)準(zhǔn)的VOC2012數(shù)據(jù)集。首先我們需要了解一下PASCAL VOC2012數(shù)據(jù)集的標(biāo)準(zhǔn)格式,VOC2012標(biāo)準(zhǔn)數(shù)據(jù)格式目錄結(jié)構(gòu)如下:


          除了根目錄VOCdevkit可以修改重命名,其余子目錄結(jié)構(gòu)必須完全一致、而且跟我們對象檢測數(shù)據(jù)訓(xùn)練相關(guān)的幾個目錄是必須要有的,它們是:

          • VOC2012目錄必須存在

          • Annotations里面是我們在標(biāo)注數(shù)據(jù)生成的XML文件

          • ImageSets/Main文件夾里面是所有圖像數(shù)據(jù)每個類別對象的classname_train.txt與classname_val.txt文件列表


          text文件的每一行都是一個文件名+空格+ 1或者-1,其中:
           1 表示圖像中包含該classname
          -1 表示不包含該classname

          生成該text文件很容易,直接python代碼掃描目錄,生成XML,代碼如下:

          def generate_classes_text():
              print("start to generate classes text...")
              ann_dir = "D:/hand_data/VOC2012/Annotations/"

              handone_train = open("D:/hand_data/VOC2012/ImageSets/Main/handone_train.txt"'w')
              handone_val = open("D:/hand_data/VOC2012/ImageSets/Main/handone_val.txt"'w')

              handfive_train = open("D:/hand_data/VOC2012/ImageSets/Main/handfive_train.txt"'w')
              handfive_val = open("D:/hand_data/VOC2012/ImageSets/Main/handfive_val.txt"'w')

              handtwo_train = open("D:/hand_data/VOC2012/ImageSets/Main/handtwo_train.txt"'w')
              handtwo_val = open("D:/hand_data/VOC2012/ImageSets/Main/handtwo_val.txt"'w')

              files = os.listdir(ann_dir)
              for xml_file in files:
                  if os.path.isfile(os.path.join(ann_dir, xml_file)):
                      xml_path = os.path.join(ann_dir, xml_file)
                      tree = ET.parse(xml_path)
                      root = tree.getroot()
                      for elem in root.iter('filename'):
                          filename = elem.text
                      for elem in root.iter('name'):
                          name = elem.text

                      if name == "handone":
                          handone_train.write(filename.replace(".jpg"" ") + str(1) + "\n")
                          handone_val.write(filename.replace(".jpg"" ") + str(1) + "\n")

                          handfive_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handfive_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")

                          handtwo_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handtwo_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                      if name == "handtwo":
                          handone_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handone_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")

                          handfive_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handfive_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")

                          handtwo_train.write(filename.replace(".jpg"" ") + str(1) + "\n")
                          handtwo_val.write(filename.replace(".jpg"" ") + str(1) + "\n")

                      if name == "handfive":
                          handone_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handone_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")

                          handfive_train.write(filename.replace(".jpg"" ") + str(1) + "\n")
                          handfive_val.write(filename.replace(".jpg"" ") + str(1) + "\n")

                          handtwo_train.write(filename.replace(".jpg"" ") + str(-1) + "\n")
                          handtwo_val.write(filename.replace(".jpg"" ") + str(-1) + "\n")

              handone_train.close()
              handone_val.close()
              handfive_train.close()
              handfive_val.close()
              handtwo_train.close()
              handtwo_val.close()
          • JPEGImages文件夾里面是所有圖像文件,這里特別聲明一下我剛開始不知道,在數(shù)據(jù)生成的時候都保存為PNG格式了,VOC2012根本不會支持,只能是JPG格式才可以。

          在VOC2012必須有的就是以上的三個目錄,其它的目錄可以沒有,因?yàn)樵诒敬螌ο髾z測中還用不到。至此我們把數(shù)據(jù)制作成VOC2012支持的標(biāo)準(zhǔn)格式了,下面創(chuàng)建一個text文件,命名為:
          hand_label_map.pbtxt
          把下面內(nèi)容copy進(jìn)去

          item {
            id1
            name: 'handfive'
          }

          item {
            id2
            name: 'handone'
          }

          item {
            id3
            name: 'handtwo'
          }

          保存之后,運(yùn)行下面的命令行開始生成tfrecord數(shù)據(jù):

          有個警告,運(yùn)行成功,看不清命令行,參考這里:


          基于SSD模型的遷移學(xué)習(xí)


          細(xì)節(jié)不想在重復(fù),之前發(fā)過一篇文章,專門講過如何通過公開數(shù)據(jù)集,基于tensorflow Object Detection API使用預(yù)訓(xùn)練模型實(shí)現(xiàn)遷移學(xué)習(xí)的文章,不懂可以查看這里:

          tensorflow object detection API訓(xùn)練公開數(shù)據(jù)集Oxford-IIIT Pets Dataset

          說一下我的config文件里面除了需要修改PATH_TO_BE_CONFIGURED,還需要把這里改一下:

          一切準(zhǔn)備就緒我可以開始通過下面的命令行實(shí)現(xiàn)訓(xùn)練:

          看不清楚看這里參考:

          num_steps = 100,完成100個step之后,通過tensorboard查看效果:

          loss曲線變化


          模型導(dǎo)出與使用


          訓(xùn)練好之后可以通過tensorflow object detection API自帶的工具直接導(dǎo)出模型


          frozen_inference_graph.pb

          然后用opencv+tensorflow實(shí)現(xiàn)一個讀攝像頭視頻流,實(shí)時手勢檢測的程序,代碼如下:

          import os
          import sys
          import tarfile

          import cv2
          import numpy as np
          import tensorflow as tf

          sys.path.append("..")
          cap = cv2.VideoCapture(0)
          from utils import label_map_util
          from utils import visualization_utils as vis_util

          ##################################################
          # 作者:賈志剛
          # 微信:gloomy_fish
          # tensorflow object detection tutorial
          ##################################################

          # Path to frozen detection graph
          PATH_TO_CKPT = 'D:/tensorflow/handset/export/frozen_inference_graph.pb'

          # List of the strings that is used to add correct label for each box.
          PATH_TO_LABELS = os.path.join('D:/tensorflow/handset/data''hand_label_map.pbtxt')

          NUM_CLASSES = 3
          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='')

          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
              return np.array(image.getdata()).reshape(
                (im_height, im_width, 3)).astype(np.uint8)


          out = cv2.VideoWriter("D:/test.mp4", cv2.VideoWriter_fourcc('D''I''V''X'), 15,
                               (np.int(640), np.int(480)), True)
          with detection_graph.as_default():
            with tf.Session(graph=detection_graph) as sess:
              while True:
                ret, image_np = cap.read()
                print(image_np.shape)
                # image_np == [1, None, None, 3]
                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')
                # Actual detection.
                (boxes, scores, classes, num_detections) = sess.run(
                    [boxes, scores, classes, num_detections],
                    feed_dict={image_tensor: image_np_expanded})
                # 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)
                out.write(image_np)
                cv2.imshow('object detection', image_np)
                c = cv2.waitKey(10)
                if c == 27# ESC
                  cv2.imwrite("D:/tensorflow/run_result.png", image_np)
                  cv2.destroyAllWindows()
                  break

          out.release()
          cap.release()
          cv2.destroyAllWindows()

          測試結(jié)果如下:


          親測有效,效果杠杠的!從此無心愛良夜、任它明月下西樓

          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實(shí)戰(zhàn)項(xiàng)目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計(jì)數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺。

          下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講即可下載含有20個基于OpenCV實(shí)現(xiàn)20個實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計(jì)算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 32
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色婷婷婷婷 | 俺来俺也去www色在线观看 | 免费无码又爽又黄又刺激网站 | 中文av字幕 | 中国黄色1级片 |