利用Tensorflow構建自己的物體識別模型(一)
原料
windows10+python3.5+pycharm
安裝tensorflow
利用Tensorflow訓練搭建自己的物體訓練模型,萬里長征第一步,先安裝tensorflow。
tensorflow分為cpu版和gpu版,gpu版的執行速度是cpu的50倍,但是gpu版的坑太多,要安裝許多開發套件,對windows的支援不夠友好;更為致命的是,它需要Nvida的中高階顯示卡,我的電腦系統是windows10,顯示卡是入門級顯示卡,開始我還想掙扎一下,安裝個gpu版,大概試了一個晚上,到底是沒有成功,識時務者為俊傑,那就安裝cpu版的吧。
pip insatll tensorflow
假如沒有報錯,做個測試,執行以下程式碼
import tensorflow as tf #指定一個常數張量 first_blood = tf.constant('double kill') #建立一個會話,方便檢視結果 sess = tf.Session() print(str(sess.run(first_blood)))
執行結果如下
E:\python\python.exe "E:/pycharm src/TF/__init__.py" 2018-12-01 23:33:25.181550: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 double kill Process finished with exit code 0
如果出現警告:
Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
翻譯過來的大致意思是:
你的CPU支援AVX擴充套件,但是你安裝的TensorFlow版本無法編譯使用
此時需要在第一行程式碼前加上兩行程式碼:
import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' import tensorflow as tf # 指定一個常數張量 first_blood = tf.constant('double kill') # 建立一個會話,方便檢視結果 sess = tf.Session() print(str(sess.run(first_blood)))
下載Tensorflow object detection API
如果有git的話,右鍵 git bash
,使用命令下載:
git clone ofollow,noindex">https://github.com/tensorflow/models.git
或者直接開啟網站:
https://github.com/tensorflow/models
點選綠色按鈕->downlaod zip
下載好之後,把檔案解壓,注意解壓路徑不要包含中文,比如我的解壓後的路徑是:
C:\Users\lenovo\Desktop\note\gitclone\models
如果下載速度很慢,可以參考: https://blog.csdn.net/ygdxt/article/details/82825013
下載並配置protoc
在 https://github.com/google/protobuf/releases 中選擇windows版本:

1.png
只有win32,也就是windows32位的,64位是相容32位的。
下載好之後,解壓,把bin目錄下的 protoc.exe
複製到 ..\models\research
資料夾下。
接著就是配置protoc了,在開啟cmd下切換到 ..\models\research
目錄,
執行命令 protoc object_detection\protos\*.proto --python_out=.
如果報以下的錯(其實很大可能性會報錯,無論是不是在管理員模式下):
object_detection\protos*.proto: No such file or directory
則需要對指令做修改,指令 protoc object_detection\protos\*.proto --python_out=.
中的 *.proto
表示是對 research
目錄下的所有後綴名為 proto
的檔案做操作,那乾脆我們把指令中的 *.proto
這部分改成所有後綴名為 proto
的檔案,每執行一次,就會生成一個 .py
檔案,由於檔案太多,我已經把指令寫成指令碼:
import os path_url = os.path.join(os.getcwd(),r"object_detection\protos") print("proto path:",path_url) for file in os.listdir(path_url): cmd = "protoc object_detection\protos\{} --python_out=." if file.endswith(".proto"): command = cmd.format(file) print("excuting command:",command) os.popen(command)
在 ..\research
目錄下新建一個檔案 excuter.py
,把以上程式碼複製進去,儲存執行,稍等一會兒就可以看到 ..\research\object_detection\protos
目錄下生成了許多 .py
檔案,說明protoc配置成功。
models環境變數配置
配置環境變數
依次開啟: 我的電腦
---> 高階系統設定
---> 環境變數
,新建一個系統變數:

2.png

3.png
系統變數名只要不和已有的重複,符合命令規範,沒有其他要求,我這裡是 tensorflow
系統變數名下有兩個值, ..\research
和 ..\research\slim
的絕對路徑。
測試
在 ..\research
下開啟cmd,執行以下命令,
python object_detection/builders/model_builder_test.py
如果出現錯誤:

4.png
報錯原因是你的models路徑太長,python無法找指定模組,
解決辦法是在你的 python
安裝路徑下新建一個 tensorflow_model.pth
檔案
(比如我的是 E:\python\Lib\site-packages
)
把寫到環境變數裡的那兩個路徑複製到該檔案中。

5.png
再執行命令 python object_detection/builders/model_builder_test.py

6.png
說明配置成功
利用tensorflow自帶模型測試
測試的圖片是在
C:\Users\lenovo\Desktop\note\gitclone\models\research\object_detection\test_images
我們看到這裡有現成的兩張圖片,當然也可以換成自己的。
測試的指令碼是
C:\Users\lenovo\Desktop\note\gitclone\models\research\object_detection\object_detection_tutorial.ipynb
這是一個需要用 jupyter notebook
開啟的檔案,不過好像在 jupyter notebook
執行會有許多毛病
我已經把這個 ipynb
檔案改寫成 py
檔案,並修復了一些未知問題,檔案內容如下:
import numpy as np import os import six.moves.urllib as urllib import sys import tarfile import tensorflow as tf import zipfile from distutils.version import StrictVersion from collections import defaultdict from io import StringIO from matplotlib import pyplot as plt from PIL import Image # This is needed since the notebook is stored in the object_detection folder. sys.path.append("..") from object_detection.utils import ops as utils_ops if StrictVersion(tf.__version__) < StrictVersion('1.9.0'): raise ImportError('Please upgrade your TensorFlow installation to v1.9.* or later!') import numpy as np import os import six.moves.urllib as urllib import sys import tarfile import tensorflow as tf import zipfile from distutils.version import StrictVersion from collections import defaultdict from io import StringIO from matplotlib import pyplot as plt from PIL import Image # This is needed since the notebook is stored in the object_detection folder. sys.path.append("..") from object_detection.utils import ops as utils_ops if StrictVersion(tf.__version__) < StrictVersion('1.9.0'): raise ImportError('Please upgrade your TensorFlow installation to v1.9.* or later!') from utils import label_map_util from utils import visualization_utils as vis_util # 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_FROZEN_GRAPH = 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('data', 'mscoco_label_map.pbtxt') 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()) detection_graph = tf.Graph() with detection_graph.as_default(): od_graph_def = tf.GraphDef() with tf.gfile.GFile(PATH_TO_FROZEN_GRAPH, 'rb') as fid: serialized_graph = fid.read() od_graph_def.ParseFromString(serialized_graph) tf.import_graph_def(od_graph_def, name='') category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True) 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) # 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 = 'test_images' 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) output_num = 1 output_img_dic = r'\output_images' def run_inference_for_single_image(image, graph): with graph.as_default(): with tf.Session() as sess: # Get handles to input and output tensors ops = tf.get_default_graph().get_operations() all_tensor_names = {output.name for op in ops for output in op.outputs} tensor_dict = {} for key in [ 'num_detections', 'detection_boxes', 'detection_scores', 'detection_classes', 'detection_masks' ]: tensor_name = key + ':0' if tensor_name in all_tensor_names: tensor_dict[key] = tf.get_default_graph().get_tensor_by_name( tensor_name) if 'detection_masks' in tensor_dict: # The following processing is only for single image detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0]) detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0]) # Reframe is required to translate mask from box coordinates to image coordinates and fit the image size. real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32) detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1]) detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1]) detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks( detection_masks, detection_boxes, image.shape[0], image.shape[1]) detection_masks_reframed = tf.cast( tf.greater(detection_masks_reframed, 0.5), tf.uint8) # Follow the convention by adding back the batch dimension tensor_dict['detection_masks'] = tf.expand_dims( detection_masks_reframed, 0) image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0') # Run inference output_dict = sess.run(tensor_dict, feed_dict={image_tensor: np.expand_dims(image, 0)}) # all outputs are float32 numpy arrays, so convert types as appropriate output_dict['num_detections'] = int(output_dict['num_detections'][0]) output_dict['detection_classes'] = output_dict[ 'detection_classes'][0].astype(np.uint8) output_dict['detection_boxes'] = output_dict['detection_boxes'][0] output_dict['detection_scores'] = output_dict['detection_scores'][0] if 'detection_masks' in output_dict: output_dict['detection_masks'] = output_dict['detection_masks'][0] return output_dict 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. output_dict = run_inference_for_single_image(image_np, detection_graph) # Visualization of the results of a detection. vis_util.visualize_boxes_and_labels_on_image_array( image_np, output_dict['detection_boxes'], output_dict['detection_classes'], output_dict['detection_scores'], category_index, instance_masks=output_dict.get('detection_masks'), use_normalized_coordinates=True, line_thickness=8) plt.figure(figsize=IMAGE_SIZE) print(1,image_np) plt.imshow(image_np) plt.show() global output_num global output_img_dic if not os.path.exists(output_img_dic): os.mkdir(output_img_dic) output_img_path = os.path.join(output_img_dic,str(output_num)+".png") plt.savefig(output_img_path)
執行上述程式碼需要安裝 matplotlib
庫,直接 pip install matplotlib
安裝失敗的可以去官網安裝與python版本對應的whl檔案。安裝 matplotlib.whl
時需要先出pycharm。
同時由於需要下載模型檔案,需要在網路好的情況下進行測試。否則就會報 HTTP ERROR
執行效果圖

7.png

8.png
宣告
以上就是本次教程的所有內容,後續還會有系列教程,原創作品,轉載請聯絡 [email protected]
歡迎大家多多上機操作,指出本教程的不足之處,如有問題,可加群交流,群號碼: 861016679