首頁 > 軟體

如何利用opencv訓練自己的模型實現特定物體的識別

2022-11-01 14:03:08

1.說明

opencv安裝包中有訓練好的分類器檔案,可以實現人臉的識別。當然,我們也可以訓練自己的分類器檔案,實現對特定物體的識別。本文章就詳細介紹下如何訓練自己的分類器檔案。

2.效果

我訓練的是檢測蘋果的的分類器檔案,可以實現對蘋果的識別。

3.準備

3.1 程式準備

  • 訓練自己的分類器檔案,需要用到兩個程式 : opencv_createsamples.exe和opencv_traincascade.exe
  • opencv最新的安裝包中沒有這兩個程式,我們可以下載 3.4.14這個版本的安裝包進行安裝。
  • 安裝完成後,在這個目錄下就會有這兩個程式檔案 opencvbuildx64vc15bin

3.2 樣本資料準備

正樣本資料 : 也就是我們需要檢測的物體圖片,可以自己用手機拍攝下你要檢測的物體的圖片,多拍攝一些不同角度的圖片。

我的正樣本資料在這個目錄下 imagepositiveimg,大概有50多張圖片

然後在imagepositive目錄下新建一個info.dat檔案,在其中記錄正樣本圖片資訊

引數介紹

  • img/1.jpg : 檔案路徑和檔名
  • 1:表示圖片中有幾個目標物體,一般一個就行了
  • 0,0:目標物體起始座標
  • 1280,1706:目標物體大小

負樣本資料:不包含我們要檢測物體的圖片,可以拍攝一些風景之類的圖片,儘量多一些。

我的負樣本資料在這個目錄下 imagenegitiveimg

然後在imagenegitive目錄下新建一個bg.txt檔案,在其中記錄負樣本圖片資訊

負樣本圖片資訊我們只需記錄路徑和檔名就行了,但是這裡要注意,路徑名要寫絕對路徑,後面會說為什麼。

3.3 正樣本VEC檔案建立

  • 訓練樣本之前先要生成vec檔案,要用到opencv_createsamples.exe程式
  • opencv_createsamples.exe部分引數介紹
  [-info <collection_file_name>]  # 記錄樣本資料的檔案(就是我們剛才建立的info.data檔案)
  [-img <image_file_name>]    
  [-vec <vec_file_name>]   # 輸出檔案,內含用於訓練的正樣本。 
  [-bg <background_file_name>]  # 背景影象的描述檔案
  [-num <number_of_samples = 1000>]   #樣本數量(預設為1000)
  [-bgcolor <background_color = 0>]    #指定背景顏色
  [-w <sample_width = 24>]#輸出樣本的寬度(以畫素為單位)
  [-h <sample_height = 24>]#輸出樣本的高度(以畫素為單位)

參考

在安裝包的這個目錄下opencvbuildx64vc15bin可以找到opencv_createsamples.exe程式,我們生成下vec檔案

D:opencv3.4.12opencvbuildx64vc15binopencv_createsamples.exe -info C:UserslngDesktopimagepositiveinfo.dat -vec C:UserslngDesktopimagesample.vec -num 58 -bgcolor 0 -bgthresh 0 -w 24 -h 24

在image目錄下就生成了vec檔案

4.樣本資料訓練

  • 完成上面的準備工作,就可以開始訓練樣本。訓練樣本需要用到opencv_traincascaded.exe程式
  • opencv_traincascaded.exe程式部分引數介紹
 -data <cascade_dir_name>     #目錄名,如不存在訓練程式會建立它,用於存放訓練好的分類器
 -vec <vec_file_name>              #包含正樣本的vec檔名
 -bg <background_file_name>   #背景描述檔案
 [-numPos <number_of_positive_samples = 2000>]   #每級分類器訓練時所用的正樣本數目
 [-numNeg <number_of_negative_samples = 1000>]   #每級分類器訓練時所用的負樣本數目
 [-numStages <number_of_stages = 20>]   #訓練的分類器的級數
--cascadeParams--
 [-featureType <{HAAR(default), LBP, HOG}>]  # 特徵的型別: HAAR - 類Haar特徵; LBP - 區域性紋理模式特徵
 [-w <sampleWidth = 24>] #訓練樣本的尺寸(單位為畫素)
 [-h <sampleHeight = 24>] #訓練樣本的尺寸(單位為畫素)
--boostParams--
 [-minHitRate <min_hit_rate> = 0.995>] #分類器的每一級希望得到的最小檢測率
 [-maxFalseAlarmRate <max_false_alarm_rate = 0.5>] #分類器的每一級希望得到的最大誤檢率

參考

  • 在安裝包的這個目錄下opencvbuildx64vc15bin可以找到opencv_traincascade.exe程式,開始訓練樣本
  • 這裡注意下
    • 指定-bg引數時,檔名前不能加路徑,所以需要把剛才在imagenegitive下建立的bg.txt檔案拷貝到opencv_traincascade.exe程式所在目錄下,所以要在bg.txt寫負樣本圖片的絕對路徑。
    • 指定numPos引數時,因為每個階段訓練時有些正樣本可能會被識別為負樣本,故每個訓練階段後都會消耗一定的正樣本。因此,此處使用的正樣本數量絕對不能等於或超過positive資料夾下的正樣本個數,一般留有一定的餘量
    • 指定-numNeg引數時,可以多於negitive目錄下的負樣本數量
D:opencv3.4.12opencvbuildx64vc15binopencv_traincascade.exe -data C:UserslngDesktopimage -vec C:UserslngDesktopimagesample.vec -bg bg.txt -numPos 50 -numNeg 500 -numStages 12 -feattureType HAAR -w 24 -h 24 -minHitRate 0.995 -maxFalseAlarmRate 0.5

執行結果

PARAMETERS:
cascadeDirName: C:UserslngDesktopimage
vecFileName: C:UserslngDesktopimagesample.vec
bgFileName: bg.txt
numPos: 50
numNeg: 500
numStages: 12
precalcValBufSize[Mb] : 1024
precalcIdxBufSize[Mb] : 1024
acceptanceRatioBreakValue : -1
stageType: BOOST
featureType: HAAR
sampleWidth: 24
sampleHeight: 24
boostType: GAB
minHitRate: 0.995
maxFalseAlarmRate: 0.5
weightTrimRate: 0.95
maxDepth: 1
maxWeakCount: 100
mode: BASIC
Number of unique features given windowSize [24,24] : 162336

===== TRAINING 0-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 1
Precalculation time: 0.581
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|     0.05|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 1 seconds.

===== TRAINING 1-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 0.084832
Precalculation time: 0.576
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|    0.146|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 3 seconds.

===== TRAINING 2-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 0.0149993
Precalculation time: 0.592
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|    0.186|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 5 seconds.

===== TRAINING 3-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 0.00288033
Precalculation time: 0.652
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|    0.298|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 7 seconds.

===== TRAINING 4-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 0.000768845
Precalculation time: 0.615
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|        1|
+----+---------+---------+
|   3|        1|    0.366|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 11 seconds.

===== TRAINING 5-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    500 : 0.000375057
Precalculation time: 0.61
+----+---------+---------+
|  N |    HR   |    FA   |
+----+---------+---------+
|   1|        1|        1|
+----+---------+---------+
|   2|        1|        1|
+----+---------+---------+
|   3|        1|    0.366|
+----+---------+---------+
END>
Training until now has taken 0 days 0 hours 0 minutes 15 seconds.

===== TRAINING 6-stage =====
<BEGIN
POS count : consumed   50 : 50
NEG count : acceptanceRatio    2 : 0.00016276
Required leaf false alarm rate achieved. Branch training t

訓練完成後,在img目錄下就會生成以下檔案。

cascade.xml就是我們需要的分類器檔案,其他都是過程檔案。

5.測試程式碼

main.cpp

#include <iostream>
#include <opencv2/opencv.hpp>

char* face_cascade_name = "C:\Users\lng\Desktop\image\cascade.xml";

void faceRecongize(cv::CascadeClassifier faceCascade, cv::Mat frame);

int main(){
    cv::VideoCapture *videoCap = new cv::VideoCapture;

	cv::CascadeClassifier faceCascade;

    // 載入蘋果分類器檔案
	if (!faceCascade.load(face_cascade_name)) {
		std::cout << "load face_cascade_name failed. " << std::endl;
		return -1;
	}

    // 開啟攝像機
	videoCap->open(0);


	if (!videoCap->isOpened()) {
		videoCap->release();
		std::cout << "open camera failed"<< std::endl;
        return -1;
	}

	std::cout << "open camera success"<< std::endl;

    while(1){
		cv::Mat frame;
		//讀取視訊幀
		videoCap->read(frame);

		if (frame.empty()) {
			videoCap->release();
			return -1;
		}

        //進行蘋果識別
		faceRecongize(faceCascade, frame);

        //視窗進行展示
        imshow("face", frame);

        //等待確認鍵按下退出程式
		if (cv::waitKey(30) == 13) {
			cv::destroyAllWindows();
			return 0;
		}
    }

    system("pause");
    return 0;
}

void faceRecongize(cv::CascadeClassifier faceCascade, cv::CascadeClassifier eyesCascade, cv::CascadeClassifier mouthCascade, cv::Mat frame) {
	std::vector<cv::Rect> faces;

    // 檢測蘋果
	faceCascade.detectMultiScale(frame, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
	for (int i = 0; i < faces.size(); i++) {
		
        // 用橢圓畫出蘋果部分
        cv::Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
		ellipse(frame, center, cv::Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, cv::Scalar(255, 0, 255), 4, 8, 0);
		
		cv::Mat faceROI = frame(faces[i]);
		std::vector<cv::Rect> eyes;

        // 蘋果上方區域寫字進行標識
		cv::Point centerText(faces[i].x + faces[i].width / 2 - 40, faces[i].y - 20);
		cv::putText(frame, "apple", centerText, cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);

	}
}

CMakeLists

cmake_minimum_required (VERSION 3.5)
project (faceRecongize2015)

MESSAGE(STATUS "PROJECT_SOURCE_DIR " ${PROJECT_SOURCE_DIR})
SET(SRC_LISTS ${PROJECT_SOURCE_DIR}/src/main.cpp)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

#set(CMAKE_AUTOMOC ON)
#set(CMAKE_AUTOUIC ON)
#set(CMAKE_AUTORCC ON)

# 設定標頭檔案目錄
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories("D:\opencv3.4.12\opencv\build\include")
include_directories("D:\opencv3.4.12\opencv\build\include\opencv2")

# 設定不顯示命令框
if(MSVC)
	#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
endif()

# 新增庫檔案
set(PRO_OPENCV_LIB "D:\opencv3.4.12\opencv\build\x64\vc15\lib\opencv_world3412.lib" "D:\opencv3.4.12\opencv\build\x64\vc15\lib\opencv_world3412d.lib")

IF(WIN32)
    # 生成可執行程式
	ADD_EXECUTABLE(faceRecongize2015 ${SRC_LISTS})
	# 連結庫檔案
    TARGET_LINK_LIBRARIES(faceRecongize2015 ${PRO_OPENCV_LIB})
ENDIF()

6.編譯說明

我的opencv 3.4.12的安裝路徑是 D:opencv3.4.12

目錄結構

- src
  - mian.cpp
- build_x64
- CMakeLists

編譯命令, 在build_x64目錄下執行

cmake -G "Visual Studio 14 2015 Win64" ..
cmake --build ./ --config Release

編譯完成後拷貝D:opencv3.4.12opencvbuildx64vc15bin目錄下的opencv_world3412.dll和opencv_world3412d.dll到可執行程式目錄下。

備註

經過測試,自己訓練的樣本,準確度還是比較差的。可能是正樣本資料太少,且圖片背景佔據位置較多。要提高準確度,首先增加正樣本圖片數量,還要就是儘量讓你的目標物體佔滿整個圖片,不要留有太多的背景。而且也要有儘可能多的負樣本資料。

總結

到此這篇關於如何利用opencv訓練自己的模型實現特定物體的識別的文章就介紹到這了,更多相關opencv實現特定物體的識別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com