實戰三:手把手教你實現物體識別

                             實戰三:手把手教你實現物體識別

一、基於Haad+Adaboost實現人臉識別

1.原理介紹(參考下面的博客文章)

http://www.cnblogs.com/ello/archive/2012/04/28/2475419.html

Haar分類器 = Haar-like特徵+積分圖方法+AdaBoost+級聯

Haar分類器算法的要點如下:

a.使用Haar-like特徵做檢測

b.使用積分圖(Integral Image)對Haar-like特徵求值進行加速

c.使用AdaBoost算法訓練區分人臉和非人臉的強分類器

d.使用篩選式級聯把強分類器級聯到一起,提高準確率

(1)Haar-like特徵是何方神聖呢?

a.什麼是特徵呢?

假設在人臉檢測時我們需要有這麼一個子窗口在待檢測的圖片窗口中不斷的移位滑動,子窗口每到一個位置,就會計算出該區域的特徵,然後用我們訓練好的級聯分類器對該特徵進行篩選,一旦該特徵通過所有強分類器的篩選,則判定該區域人臉。

b.Haar-like特徵的表示

下面是Viola牛們提出的Haar-like特徵。

下面是Lienhart等牛們提出的Haar-like特徵。

 

這些所謂的特徵不就是一堆堆帶條紋的矩陣麼,到底是幹什麼用的呢?

解釋:將上面的任意一個矩形放到人臉區域上,然後,將白色區域的像素和減去黑色區域的像素和,得到的值暫且稱之爲人臉特徵值,如果你把這個矩形放到一個非人臉區域,那麼計算出的特徵值和人臉特徵值是不一樣的,所以這些方塊的目的就是把人臉特徵量化,以區分人臉和費人臉。

爲了增加區分度,可以對多個矩形特徵計算得到一個區分度更大的特徵值,那麼什麼樣的矩形特徵怎麼樣的組合到一塊可以更好的區分出人臉和非人臉呢,這就是AdaBoost算法要做的事情了。

 

(2)AdaBoost你給我如實道來!

AdaBoost是一種具有一般性的分類器提升算法,它使用的分類器並不侷限某一特定的算法。利用AdaBoost可以幫助我們選擇更好的矩陣特徵組合。

 

(3)積分圖是一個加速器

積分圖就是隻遍歷一次圖像就可以求出圖像中所有區域像素和的快速算法,大大的提高了圖像特徵值計算的效率。

 

2.基於Haad+Adaboost實現人臉識別

(1)前期準備

準備一張人臉照片face.jpg,並獲取opencv自帶的人臉檢測器以及眼睛檢測器模塊。

(2)整體步驟

a.加載xml文件

b.加載jpg圖片

c.jpg圖片轉灰度圖

d.檢測人臉

e.在圖片中將人臉用矩形框起來

f.展示圖片

(3)程序源碼

import cv2
import numpy as np
# xml文件的引入
face_xml = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_xml = cv2.CascadeClassifier('haarcascade_eye.xml')

# load jpg
img = cv2.imread('face.jpg')
cv2.imshow('src',img)

# haar  gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# dect
# 1 人臉灰度圖片數據 2 縮放係數 3 目標大小
faces = face_xml.detectMultiScale(gray,1.3,5)

print('face=',len(faces))
# draw
for (x,y,w,h) in faces:
	cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
	# 眼睛識別代碼
	roi_gray = gray[y:y+h,x:x+w]
	roi_img = img[y:y+h,x:x+w]
	eyes = eye_xml.detectMultiScale(roi_gray)
	print('eyes=',len(eyes))
	for (e_x,e_y,e_w,e_h) in eyes:
		cv2.rectangle(roi_img,(e_x,e_y),(e_x+e_w,e_y+e_h),(0,255,0),2)

cv2.imshow('dst',img)
cv2.waitKey(0)

(4)結果展示

二、基於SVM的男女識別

1.原理

還是先從原理入手,從網上看到的劉強西救愛人的故事:

https://www.sohu.com/a/128747589_614807

總之,上述故事的球稱作[data](數據源),棍子稱作[classifier](分類器),最大間隙trick稱作[optimization](最優化),拍桌子稱作[kernelling](建立核函數),那張紙稱作[hyperplane](超平面)

 

2.基於SVM的男女識別

提供男女的身高和體重的數據,進行訓練,然後再給出數據,預測男女。

有標籤的訓練稱之爲監督學習,樣本分爲負樣本和正樣本。

(1)前期準備

女生數據[155,48],[159,50],[164,53],[168,56],[172,60]

男生數據[152,53],[156,55],[160,56],[172,64],[176,65]

預測數據 女[167,55], 男[162,57]

標籤 0女 1男

(2)整體步驟

a.準備data數據

b.準備label標籤

c.訓練SVM

d.數據的預測

(3)源碼

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 1 準備data
rand1 = np.array([[155,48],[159,50],[164,53],[168,56],[172,60]])
rand2 = np.array([[152,53],[156,55],[160,56],[172,64],[176,65]])
data = np.vstack((rand1,rand2))
data = np.array(data,dtype='float32')


# 2 label 標籤
label = np.array([[0],[0],[0],[0],[0],[1],[1],[1],[1],[1]])


# 3 訓練SVM
# m1 機器學習模塊 SVM_create()創建向量機
svm = cv2.ml.SVM_create()
# 屬性設置
svm.setType(cv2.ml.SVM_C_SVC) # svm type
svm.setKernel(cv2.ml.SVM_LINEAR) # line 線性分類器
svm.setC(0.01)
# 訓練
svm.train(data,cv2.ml.ROW_SAMPLE,label)

# 4 完成數據的預測
pt_data = np.vstack([[167,55],[162,57]]) # 0 女生 1 男生
pt_data = np.array(pt_data,dtype='float32')
# 開始預測
(par1,par2) = svm.predict(pt_data)
print(par2) 

(4)結果展示

三、基於Hog+SVM實現小獅子的識別

1.Hog原理

參考文章

https://www.cnblogs.com/hustdc/p/6563891.html

https://blog.csdn.net/datase/article/details/71374471

hog特徵是histogram of gradient的縮寫,我們觀察圖像時,信息更多來自目標邊沿的突變。我們計算一塊區域內的所有像素處的梯度信息,即突變的方向和大小,然後對360度進行劃分,得到多個bin,統計該區域內所有像素所在的bin,就得到了一個histogram,就是說hog特徵。

2.基於Hog+SVM實現小獅子的識別

(1)前期準備

樣本的準備,正樣本和負樣本的準備,正樣本是包含需要檢測的物體,負樣本是不包含需要檢測的物體。

這裏的樣本數據提供一種方法,從視頻中獲取圖片,直接給出代碼。

# 視頻分解成圖片
# 1 load加載視頻 2 讀取info 3 解碼 單幀視頻parse 4 展示 imshow
import cv2
# 獲取一個視頻打開cap
cap = cv2.VideoCapture('1.mp4')
# 判斷是否打開
isOpened = cap.isOpened
print(isOpened)
#幀率
fps = cap.get(cv2.CAP_PROP_FPS)
#寬度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
#高度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(fps,width,height)

i = 0
while(isOpened):
	if i == 100:
		break
	else:
		i = i+1
	(flag,frame) = cap.read() # 讀取每一張 flag讀取是否成功 frame內容
	fileName = 'image'+ str(i) + '.jpg'
	print(fileName)
	if flag == True:
		#寫入圖片
		cv2.imwrite(fileName,frame,[cv2.IMWRITE_JPEG_QUALITY,100])
print('end!')

將視頻生成的圖片尺寸轉換成64*128的照片

# 540 * 960 ==>64*128
import cv2

for i in range(0,100):
	fileName = 'imgs\\'+str(i+1)+'.jpg'
	print(fileName)
	img = cv2.imread(fileName)
	imgInfo = img.shape
	height = imgInfo[0]
	width = imgInfo[1]
	mode = imgInfo[2]
	dstHeight = 128
	dstWidth = 64
	dst = cv2.resize(img,(dstWidth,dstHeight))
	cv2.imwrite(fileName,dst)

 

 

(2)總體步驟

a.全局變量的賦值

b.hog對象的創建

c.SVM分類的創建

d.計算hog以及label標籤

e.訓練

f.檢測

 

(3)代碼

# 1 準備樣本 2 訓練 3 預測
# 1 樣本
#   pos是正樣本,包含需要檢測的物體 neg是負樣本,不包含需要檢測的物體
#   圖片大小是64*128
#   如何獲取樣本? 1 來源於網絡 2 源自公司內部 3 自己收集
#   一個好的樣本 遠勝過一個複雜的神經網絡
#   正樣本:儘可能的多樣 環境多樣 干擾多樣 820 負樣本 1931  1:2或者1:3之間

# 2 訓練

# 1.參數 2 hog 3.SVM 4.computer hog 5.label 6.train 7.predicr 8.draw
import cv2
import numpy as np
import matplotlib.pyplot as plt

#1 設置全局變量 在一個windows窗體中有105個block,每個block下有4個cell,每個cell下有9個bin,總共3780維
PosNum = 820 # 正樣本的個數
NegNum = 1931 # 負樣本的個數
winSize = (64,128) # 窗體大小
blockSize = (16,16) # 105個block
blockStride = (8,8) # block的步長
cellSize = (8,8)
nBin = 9

#2 hog對象的創建
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nBin)

#3 SVM分類器的創建
svm = cv2.ml.SVM_create()

#4 5 計算hog label
featureNum = int(((128-16)/8+1)*((64-16)/8+1)*4*9)  # 3780
featureArray = np.zeros(((PosNum+NegNum),featureNum),np.float32)
labelArray = np.zeros(((PosNum+NegNum),1),np.int32)
# SVM 監督學習 樣本和標籤 SVM學習的是image的hog特徵
for i in range(0,PosNum):
	fileName = 'pos\\'+str(i+1)+'.jpg'
	img = cv2.imread(fileName)
	hist = hog.compute(img,(8,8)) # 當前hog的計算 3780維的數據
	for j in range(0,featureNum):
		featureArray[i,j] = hist[j] # hog特徵的裝載
	labelArray[i,0] = 1 # 正樣本標籤爲1

for i in range(0,NegNum):
	fileName = 'neg\\'+str(i+1)+'.jpg'
	hist = hog.compute(img,(8,8))
	for j in range(0,featureNum):
		featureArray[i+PosNum,j] = hist[j]
	labelArray[i+PosNum,0] = -1 # 負樣本標籤爲-1

# 設置SVM的屬性
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(0.01)

# 6 train
ret = svm.train(featureArray,cv2.ml.ROW_SAMPLE,labelArray)

# 7 檢測(創建myHog--->myDect參數得到-->來源於resultArray(公式得到) rho(訓練得到))

# rho
alpha = np.zeros((1),np.float32)
rho = svm.getDecisionFunction(0,alpha)
print(rho)
print(alpha)

# resultArray
alphaArray = np.zeros((1,1),np.float32)
supportVArray = np.zeros((1,featureNum),np.float32)
resultArray = np.zeros((1,featureNum),np.float32)
alphaArray[0,0] = alpha
resultArray = -1*alphaArray*supportVArray #計算公式

# mydect參數
myDetect = np.zeros((3781),np.float32)
for i in range(0,3780):
	myDetect[i] = resultArray[0,i]
myDetect[3780] = rho[0]

# 構建好myHog
myHog = cv2.HOGDescriptor()
myHog.setSVMDetector(myDetect)

# 待檢測圖片的加載
imageSrc = cv2.imread('Test.jpg',1)
# 檢測小獅子 (8,8)winds的滑動步長 1.05 縮放係數 (32,32)窗口大小
objs = myHog.detectMultiScale(imageSrc,0,(8,8),(32,32),1.05,2)
# 起始位置、寬和高 objs三維信息
x = int(objs[0][0][0])
y = int(objs[0][0][1])
w = int(objs[0][0][2])
h = int(objs[0][0][3])

# 目標的繪製 圖片 起始位置 終止位置 顏色
cv2.rectangle(imageSrc,(x,y),(x+w,y+h),(255,0,0))
# 目標的展示
cv2.imshow('dst',imageSrc)
cv2.waitKey(0)

(4)結果展示

 四、項目地址

鏈接:https://pan.baidu.com/s/14O4NbkxZ3G9AWMOtyX9xXg

提取碼:24hb

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章