0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenCV編程:OpenCV3.X訓(xùn)練自己的分類器

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 09:31 ? 次閱讀

一、環(huán)境介紹

操作系統(tǒng): windows10 64位

QT版本: 5.12.6 (我的程序里主要是QT+OpenCV實(shí)現(xiàn)圖像處理顯示的)

OpenCV版本: OpenCV3.4.7

二、下載安裝OpenCV

windows下不用下載源碼,可以直接在官網(wǎng)下載編譯好的文件解壓即可使用。

OpenCV官網(wǎng)下載地址: https://opencv.org/releases/ 下載之后解壓到指定目錄即可,我這里是直接解壓到C盤的。

img

因?yàn)樵诠倬W(wǎng)下載的版本是VC版本,而我的QT使用的是MinGW編譯器,上面下在官網(wǎng)下載的安裝包里的庫用不了,需要再下載一個(gè)MinGW版本。 下載地址:https://github.com/huihut/OpenCV-MinGW-Build

img

為什么需要下載兩個(gè)版本? 其實(shí)主要是MinGW版本的OpenCV里帶的兩個(gè)訓(xùn)練分類器(opencv_traincascade.exe)的文件在我電腦上無法使用,可能庫沖突,具體問題沒有深究,就干脆再下載了一個(gè)VC版本是OpenCV,VC版本里opencv_traincascade.exe文件是可以正常使用。 其實(shí)下載的VC版本OpenCV主要是為了用這兩個(gè)文件(opencv_traincascade.exe、opencv_createsamples.exe)

img

三、測試OpenCV自帶的分類器

3.1 自帶的分類器文件介紹

OpenCV的官方已經(jīng)提供了很多訓(xùn)練好的分類器文件,在OpenCV的安裝目錄下有。

img

上面文件中提供了常見的 人臉檢測、眼睛檢測、貓臉檢測、行人檢測等,看XML文件的命名即可得知。

下面編寫QT程序,調(diào)用OpenCV的級(jí)聯(lián)分類器進(jìn)行測試。

3.2 QT的示例代碼

下面的QT界面很簡單,主要是為了測試分類器文件。

xxx.cpp文件代碼:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    dir="C:/";

    ui->label_source->setAlignment(Qt::AlignVCenter);
    ui->label_2->setAlignment(Qt::AlignVCenter);
}

Widget::~Widget()
{
    delete ui;
}
QImage Widget::Mat2QImage(const Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        return QImage();
    }
}

//打開本地圖片
void Widget::on_pushButton_open_clicked()
{
    filename=QFileDialog::getOpenFileName(this,"選擇打開的文件",dir,tr("*.bmp *.jpg *.png"));
    if(filename.isEmpty())return;
    QFileInfo info(filename);
    dir=info.path(); //保存當(dāng)前路徑
}

//人臉檢測代碼
void Widget::opencv_face(QImage qImage)
{
    QTime time;
    time.start();

    //定義級(jí)聯(lián)分類器
    CascadeClassifier face_cascade;
    //加載分類文件
    //
    if( !face_cascade.load("C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/etc/haarcascades/haarcascade_frontalcatface.xml") )
    {
        qDebug()<<"haarcascade_frontalface_alt.xml 分類器加載錯(cuò)誤";
        return;
    }
    Mat frame=QImage2cvMat(qImage);
    cvtColor( frame, frame, COLOR_BGR2GRAY );//轉(zhuǎn)換成灰度圖像

    std::vector faces;
    //正臉檢測
    face_cascade.detectMultiScale(frame,faces);
    qDebug()<("耗時(shí):%1>

xxx.h文件代碼:

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include "opencv2/core/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

#include 
#include 
#include 

using namespace cv;

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    QImage Mat2QImage(const Mat& mat);
    void opencv_face(QImage qImage);
    Mat QImage2cvMat(QImage image);
    QString dir;
    QString filename;
private slots:
    void on_pushButton_open_clicked();

    void on_pushButton_start_clicked();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

xxx.pro文件

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

#linu平臺(tái)的路徑設(shè)置
linux {
message('運(yùn)行l(wèi)inu版本')
#添加opencv頭文件的路徑,需要根據(jù)自己的頭文件路徑進(jìn)行修改
INCLUDEPATH+=/home/wbyq/work_pc/opencv-3.4.9/_install/install/include\
             /home/wbyq/work_pc/opencv-3.4.9/_install/install/include/opencv\
             /home/wbyq/work_pc/opencv-3.4.9/_install/install/include/opencv2

LIBS+=/home/wbyq/work_pc/opencv-3.4.9/_install/install/lib/libopencv_*
}

win32
{
    message('運(yùn)行win32版本')
    #添加opencv頭文件的路徑,需要根據(jù)自己的頭文件路徑進(jìn)行修改
    INCLUDEPATH+=C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include \
                 C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv \
                 C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv2
    LIBS+=C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/x86/mingw/bin/libopencv_*.dll
}

xxx.ui文件:

img

3.3 測試人臉分類器效果

把代碼中的分類器文件換成:haarcascade_frontalface_alt2.xml

imgimgimg

這份QT代碼只是為了簡單的測試,就沒有開線程去識(shí)別,如果識(shí)別耗時(shí)比較久的話,識(shí)別過程中UI界面會(huì)卡住,等一會(huì)即可。

3.4 測試貓臉分類器效果

把代碼中的分類器文件換成:haarcascade_frontalcatface.xml

img

3.5 測試行人檢測分類器效果

把代碼中的分類器文件換成:haarcascade_fullbody.xml

img

四、訓(xùn)練自己的分類器

4.1 前言

如果自己實(shí)際要檢測的物體在OpenCV自帶的分類器里沒有,或者OpenCV自帶的分類器識(shí)別精度不滿足要求,就可以使用OpenCV自帶的分類器程序自己訓(xùn)練。訓(xùn)練的方法網(wǎng)上的教程非常多,下面就重復(fù)造輪子簡單的敘述一下訓(xùn)練過程。

說明: 因?yàn)橄旅娴膬?nèi)容主要是簡單的敘述一下訓(xùn)練過程,所以我準(zhǔn)備的樣本數(shù)量都較少,如果實(shí)際訓(xùn)練需要看下面說明增加樣本數(shù)量。

4.1 準(zhǔn)備訓(xùn)練的正負(fù)樣本素材說明

想要讓計(jì)算器識(shí)別指定的物體,那么首先得讓計(jì)算器知道你要識(shí)別的物體長什么樣,需要提前學(xué)習(xí)一番。學(xué)習(xí)過程中,需要準(zhǔn)備一份正樣本和一份負(fù)樣本。 正樣本就是要識(shí)別的物體;負(fù)樣就是用來與正樣本比較的,負(fù)樣本里不包含正樣本里圖片或者相似的圖片,但是也不能亂選,最好與正樣本的取景在一個(gè)環(huán)境下,這樣效果最好,減少誤識(shí)別。

樣本圖片最好使用灰度圖(也就是黑白圖);樣本數(shù)量越多越好,盡量高于1000,樣本間差異性越大越好,正負(fù)樣本比例可以為1:3,訓(xùn)練樣本官方推薦最佳尺寸為20x20,樣本圖片的命名不要出現(xiàn)特殊字符,使用正常點(diǎn)的名字即可。

正樣本的所有的圖片尺寸必須一致,如果不一致的或者尺寸較大的,可以先將所有樣本統(tǒng)一縮放到20*20。

尺寸大小決定的是訓(xùn)練的時(shí)間長短,大尺寸也可以訓(xùn)練,如果圖片太小也會(huì)損失很多細(xì)節(jié),尺寸可以根據(jù)實(shí)際情況權(quán)衡,但是太大的圖片樣本訓(xùn)練可能會(huì)導(dǎo)致內(nèi)存不夠用的情況,具體情況可以根據(jù)訓(xùn)練效果和情況進(jìn)行調(diào)整。

注意,為了提高訓(xùn)練準(zhǔn)確率,負(fù)樣本不能亂選。

比如: 檢測的正樣本是車輪,那么負(fù)樣本就最好是車身,馬路、護(hù)欄、等等環(huán)境。

4.2 正樣本圖片示例

下面是識(shí)別汽車的正樣本圖片,正樣本圖片可以創(chuàng)建一個(gè)PositiveSample文件夾存放。

img

4.3 負(fù)樣本圖片示例

負(fù)樣本圖片可以創(chuàng)建一個(gè)NegativeSample文件夾存放。
負(fù)樣本圖片不要求樣本的尺寸,但要大于等于正樣本的大??;且負(fù)樣本不能重復(fù),要增大負(fù)樣本的差異性。
負(fù)樣本也要灰度化,同正樣本操作相同。

img

4.4 創(chuàng)建工作目錄

在電腦任意目錄,創(chuàng)建一個(gè)工作目錄OpenCV_TrainingData,將存放正負(fù)樣本的目錄拷貝到OpenCV_TrainingData目錄下,再創(chuàng)建一個(gè)XML目錄,用于存放生成的訓(xùn)練文件。

img

3.2 創(chuàng)建正樣本描述文件

打開電腦命令行終端。

img

使用cd命令進(jìn)入到正樣本的目錄下。

img

執(zhí)行命令如下:

命令1-進(jìn)入到正樣本目錄下:cd /d D:\linux-share-dir\OpenCV_TrainingData\PositiveSample

命令2-將目錄下所有圖片名字和路徑輸出到pos.txt文件:dir /b/s/p/w *.jpg > pos.txt

打開生成的pos.txt文件內(nèi)容如下。

img

將文件的內(nèi)容稍作修改,加上檢測目標(biāo)個(gè)數(shù)、目標(biāo)圖片左上位置坐標(biāo)、圖片寬高參數(shù)

我這里準(zhǔn)備的樣本圖片尺寸都是40x40,所以填寫的代碼:1 0 0 40 40

修改效果如下:

img

如果圖片數(shù)量很大,手動(dòng)修改比較麻煩, 直接使用文本編輯器,搜索替換即可。

****

img

3.3 創(chuàng)建負(fù)樣本描述文件

負(fù)樣本描述文件創(chuàng)建方法與正樣本描述文件一樣,進(jìn)入到負(fù)樣本圖片的目錄下,生成neg.txt文件,代碼如下:

命令1:cd /d D:\linux-share-dir\OpenCV_TrainingData\NegativeSample

命令2:dir /b/s/p/w *.jpg > neg.txt

注意:負(fù)樣本neg.txt文件不需要做任何修改,以下就是最終文件。

img

3.4 生成正樣本的.vec文件

為了方便填路徑,將生成的正負(fù)樣本描述文件pos.txt和neg.txt拷貝到上層目錄下。

img

正樣本的.vec文件生成,執(zhí)行命令如下:

命令1:cd /d D:\linux-share-dir\OpenCV_TrainingData

命令2:C:\OpenCV_3.4.7\opencv-vc-3.4.7\build\x64\vc15\bin\opencv_createsamples.exe -vec pos.vec -info pos.txt -num 54 -w 40 -h 40

參數(shù)介紹:

opencv_createsamples.exe: 生成樣本描述文件的可執(zhí)行程序(opencv自帶),前面是我電腦上的路徑。

-vec pos.vec 指定生成的vec文件

-info pos.txt 指定源樣本的描述文件

-num 54 指定標(biāo)定目標(biāo)樣本總數(shù)量,就是樣本描述文件里所有第2列的數(shù)字之和。

-w 40 指定樣本縮放后的寬,如果之前圖片不是40,那么這里就會(huì)縮放成40,有了這個(gè)參數(shù)就可以省去之前的圖片處理過程。

-h 40 指定樣本縮放后的高,如果之前圖片不是40,那么這里就會(huì)縮放成40,有了這個(gè)參數(shù)就可以省去之前的圖片處理過程。

我電腦上OpenCV的安裝路徑:

img

生成結(jié)果如下:

****

img

執(zhí)行成功之后在當(dāng)前目錄下生成pos.vec文件。

img


說明: 負(fù)樣本不需要生成vec文件。

3.5 開始訓(xùn)練樣本

命令1:cd /d D:\linux-share-dir\OpenCV_TrainingData
命令2:C:\OpenCV_3.4.7\opencv-vc-3.4.7\build\x64\vc15\bin\opencv_traincascade.exe -data XML -vec pos.vec -bg neg.txt -numPos 50 -numNeg 133 -numStages 20 -w 40 -h 40 -mode ALL

參數(shù)介紹:

-data 指定輸出目錄,訓(xùn)練生成的xml文件就放在這個(gè)目錄下

-vec 指定正樣本生成的 vec 文件

-bg 指定負(fù)樣本數(shù)據(jù)文件,即前面生成的neg.txt文件

-numPos 指定正樣本數(shù)目,這個(gè)數(shù)值一定要比準(zhǔn)備正樣本時(shí)的數(shù)目少,不然會(huì)報(bào) can not get new positive sample。

參考理由:minHitRate:影響每個(gè)強(qiáng)分類器閾值,當(dāng)設(shè)置為0.95時(shí)如果正訓(xùn)練樣本個(gè)數(shù)為10000個(gè),那么其中的500個(gè)就很可能背叛別為負(fù)樣本,第二次選擇的時(shí)候必須多選擇后面的500個(gè),按照這種規(guī)律我們?yōu)楹竺娴拿考?jí)多增加numPos*minHitRate個(gè)正樣本,根據(jù)訓(xùn)練的級(jí)數(shù)可以得到如下公式

numPos+(numStages-1)numPos(1-minHitRate)《=準(zhǔn)備的訓(xùn)練樣本

以上式子也只是根據(jù)訓(xùn)練級(jí)數(shù)和準(zhǔn)備的正樣本總和設(shè)置一個(gè)參與訓(xùn)練的正樣本個(gè)數(shù),只能作為估算,小于計(jì)算出來的數(shù)可能沒有問題,但是大于那個(gè)數(shù)肯定有問題

現(xiàn)在解釋下”可能有問題“是如何理解的:因?yàn)槲覀兛偸悄J(rèn)每次添加固定個(gè)數(shù)的正訓(xùn)練樣本,但是有時(shí)候后面的固定個(gè)數(shù)的正訓(xùn)練樣本中也可能存在不滿足條件的樣本,這些樣本跟我們排除的樣本類似,所以比如我們打算添加500個(gè)樣本就夠了,但是實(shí)際需要添加600個(gè),這時(shí)候就出現(xiàn)問題了。

從上面例子的結(jié)果中可以看出,每級(jí)我們?cè)试S丟掉12000*0.001個(gè)正樣本=12,需要注意的是萬一第11個(gè)或者第10個(gè)跟第12個(gè)的閾值是一樣的,那么我們之丟掉了前面的10個(gè)或者9個(gè)而已,因此每次增加的個(gè)數(shù)可能要小于12個(gè),大于12個(gè)的情況就是上面所說的”可能有問題“。

-numStages 指定訓(xùn)練級(jí)數(shù)

-numNeg 指定負(fù)樣本數(shù)目

-w 40 -h 40 指定樣本圖尺寸

-mode 指定haar特征的種類,basio僅僅使用垂直特征,al1表示使用垂直以及45度旋轉(zhuǎn)特征

開始訓(xùn)練:

img

訓(xùn)練成功之后在XML目錄下會(huì)生成cascade.xml文件,這個(gè)文件就是最終訓(xùn)練成功的文件,可以替換到到上面代碼里測試。

img

審核編輯:湯梓紅("耗時(shí):%1>
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 分類器
    +關(guān)注

    關(guān)注

    0

    文章

    152

    瀏覽量

    13149
  • OpenCV
    +關(guān)注

    關(guān)注

    29

    文章

    622

    瀏覽量

    41089
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    OpenCV開發(fā)環(huán)境的配置

    OpenCV3編程入門》書本配套源代碼:OpenCV開發(fā)環(huán)境的配置
    發(fā)表于 06-06 15:20 ?8次下載

    xml和YAML文件的寫入_OpenCV3編程入門

    OpenCV3編程入門》書本配套源代碼:xml和YAML文件的寫入
    發(fā)表于 06-06 15:20 ?6次下載

    OpenCV進(jìn)行基本繪圖_《OpenCV3編程入門》書本配套源

    OpenCV3編程入門》書本配套源代碼:用OpenCV進(jìn)行基本繪圖
    發(fā)表于 05-11 16:46 ?36次下載

    用迭代訪問像素_《OpenCV3編程入門》書本配套源代碼

    OpenCV3編程入門》書本配套源代碼:用迭代訪問像素
    發(fā)表于 06-06 15:52 ?2次下載

    OpenCV3編程入門-源碼例程全集-OpenCV開發(fā)環(huán)境的配置

    OpenCV3編程入門-源碼例程全集-OpenCV開發(fā)環(huán)境的配置,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 09-18 16:27 ?20次下載

    OpenCV3編程入門-源碼例程全集-HoughCircles函

    OpenCV3編程入門-源碼例程全集-HoughCircles函數(shù)用法示例
    發(fā)表于 09-18 16:38 ?2次下載

    OpenCV3編程入門-源碼例程全集-HoughLinesP函數(shù)

    OpenCV3編程入門-源碼例程全集-HoughLinesP函數(shù)用法示例
    發(fā)表于 09-18 16:38 ?10次下載

    OpenCV3編程入門-源碼例程全集-GaussianBlur函

    OpenCV3編程入門-源碼例程全集-GaussianBlur函數(shù)用法示例
    發(fā)表于 09-18 16:38 ?1次下載

    OpenCV3編程入門-源碼例程全集-xm<x>l和YAML文件的寫入

    OpenCV3編程入門-源碼例程全集-xml和YAML文件的寫入
    發(fā)表于 09-18 16:38 ?0次下載

    OpenCV3編程入門-源碼例程全集-點(diǎn)追蹤

    OpenCV3編程入門-源碼例程全集-點(diǎn)追蹤
    發(fā)表于 09-18 16:38 ?0次下載

    OpenCV3編程入門-源碼例程全集-播放視頻

    OpenCV3編程入門-源碼例程全集-播放視頻
    發(fā)表于 09-17 22:54 ?18次下載

    OpenCV3編程入門-源碼例程全集-人臉識(shí)別

    OpenCV3編程入門-源碼例程全集-人臉識(shí)別
    發(fā)表于 09-17 22:55 ?2次下載

    OpenCV3編程入門-源碼例程全集-模板匹配

    OpenCV3編程入門-源碼例程全集-模板匹配
    發(fā)表于 09-17 22:55 ?4次下載

    OpenCV進(jìn)行基本繪圖_OpenCV3編程入門-源碼例程

    OpenCV3編程入門-源碼例程全集-用OpenCV進(jìn)行基本繪圖,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 09-18 17:02 ?3次下載

    opencv-python和opencv一樣嗎

    的。以下是對(duì)OpenCVOpenCV-Python的比較: 編程語言: OpenCV是一個(gè)跨平臺(tái)的庫,支持多種編程語言,如C++、Java
    的頭像 發(fā)表于 07-16 10:38 ?442次閱讀