Python影像辨識筆記(六):使用Open CV自定義辨識物件

Yanwei Liu
8 min readMay 2, 2019

成果

成功辨識出貓
人類不會辨識出來
手機也不會

本文分為兩部分:

Part1是圖片的取得與資料建立

Part2是辨識模型的訓練

Part1

下載ImageNet圖片到neg資料夾

# (本案例下載1131張)

import urllib.request
import cv2
import os

# 創建圖片保存目錄
if not os.path.exists('neg'):
os.makedirs('neg')

neg_img_url = ['http://image-net.org/api/text/imagenet.synset.geturls?wnid=n02123159']

urls = ''
for img_url in neg_img_url:
urls += urllib.request.urlopen(img_url).read().decode()

img_index = 1
for url in urls.split('\n'):
try:
print(url)
urllib.request.urlretrieve(url, 'neg/'+str(img_index)+'.jpg')
# 把圖片轉為灰度圖片
gray_img = cv2.imread('neg/'+str(img_index)+'.jpg', cv2.IMREAD_GRAYSCALE)
# 更改圖像大小
image = cv2.resize(gray_img, (150, 150))
# 保存圖片
cv2.imwrite('neg/'+str(img_index)+'.jpg', image)
img_index += 1
except Exception as e:
print(e)

# 判斷兩張圖片是否完全一樣
def is_same_image(img_file1, img_file2):
img1 = cv2.imread(img_file1)
img2 = cv2.imread(img_file2)
if img1.shape == img2.shape and not (np.bitwise_xor(img1, img2).any()):
return True
else:
return False

# 去除重複圖片
"""
file_list = os.listdir('neg')
try:
for img1 in file_list:
for img2 in file_list:
if img1 != img2:
if is_same_image('neg/'+img1, 'neg/'+img2) is True:
print(img1, img2)
os.remove('neg/'+img1)
file_list.remove(img1)
except Exception as e:
print(e)
"""

建立圖片列表文件(neg.txt)

import os
import numpy as np

with open('neg.txt', 'w') as f:
for img in os.listdir('neg'):
line = 'neg/'+img+'\n'
f.write(line)

Part2

安裝OpenCV(3.4.6)

https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download#解壓縮至相關目錄(目錄名稱為opencv)

複製Part1下載的圖片及文件

將neg資料夾、neg.txt、目標物圖片(例如:cat.jpg)移動到X:\opencv\build\x64\vc14\bin#在該資料夾中同時會看到
opencv_createsamples.exe和opencv_traincascade.exe

建立pos.txt文件

#開啟CMD,輸入以下指令,建立pos.txt文件opencv_createsamples -img object.jpg -bg neg.txt -info pos.txt -maxxangle 0.5 -maxyangle -0.5 -maxzangle 0.5 -num 5000#預設值為1000

建立pos.vec文件

#開啟CMD,輸入以下指令,建立pos.vec文件
opencv_createsamples -info pos.txt -num 5000 -w 20 -h 30 -vec pos.vec
#若pos.txt為2000,則這邊的num也為同樣2000,依照pos.txt的值而訂

開始訓練辨識模型

#開啟CMD,輸入以下指令,先建立資料夾再訓練模型mkdir dataopencv_traincascade -data data -vec pos.vec -bg neg.txt -numPos 1000 -numNeg 500 -numStages 20 -w 20 -h 30  # numPos通常為numNeg的兩倍
# numPos和numNeg必須小於提供的neg照片數量
# Stages越少,訓練時間越短
# 此步驟需花上較常時間進行訓練
本次花了36分27秒在訓練模型上

測試分類器

import cv2cat_haar = cv2.CascadeClassifier(r"D:\opencv\build\x64\vc14\bin\data\cascade.xml")# 讀取圖片
img = cv2.imread('s.jpg')
# 轉成灰階圖片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cat = cat_haar.detectMultiScale(gray, 1.06, 1,minSize=(50, 50))
# 繪製貓的方框
for (x, y, w, h) in cat:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 顯示成果
cv2.namedWindow('img', cv2.WINDOW_NORMAL) #正常視窗大小
cv2.imshow('img', img) #秀出圖片
cv2.waitKey(0) #等待按下任一按鍵
cv2.destroyAllWindows() #關閉視窗

--

--