機器學習
機器學習的目的是把資料轉換成資訊。
機器學習通過從資料裡擷取規則或模式來把資料轉成資訊。
Face Service
Face Service通過級聯分類器對特徵的分級篩選來確定是否是人臉。
每個節點的正確識別率很高,但正確拒絕率很低。
任一節點判斷沒有人臉特徵則結束運算,宣布不是人臉。
全部節點通過,則宣布是人臉。
工業上,常用Face Service技術來識別物體。
對圖片進行識別 複製代碼 代碼如下:#include "opencv2/core/core.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
string face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "Face Service";
void detectAndDisplay( Mat frame );
int main( int argc, char** argv ){
Mat image;
image = imread( argv[1]);
if( argc != 2 || !image.data ){
printf("[error] 沒有圖片\n");
return -1;
}
if( !face_cascade.load( face_cascade_name ) ){
printf("[error] 無法載入級聯分類器檔案!\n");
return -1;
}
detectAndDisplay(image);
waitKey(0);
}
void detectAndDisplay( Mat frame ){
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, CV_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
for( int i = 0; i < faces.size(); i++ ){
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
}
imshow( window_name, frame );
}
CascadeClassifier類
class CascadeClassifier
用於檢測物體的級聯分類器類。
CascadeClassifier::CascadeClassifier
從一個檔案讀取分類器。
C++: CascadeClassifier::CascadeClassifier(const string& filename)
參數 filename – 所要讀取分類器檔案的檔案名稱
| 參數 |
filename – 所要讀取分類器檔案的檔案名稱 |
CascadeClassifier::empty
檢查分類器是否已經載入。
C++: bool CascadeClassifier::empty() const
CascadeClassifier::load
從一個檔案讀取分類器。
C++: bool CascadeClassifier::load(const string& filename)
參數 filename – 所要讀取分類器檔案的檔案名稱。檔案可以是舊版的HAAR分類器模型也可以是新版的分類器模型。
| 參數 |
filename – 所要讀取分類器檔案的檔案名稱。檔案可以是舊版的HAAR分類器模型也可以是新版的分類器模型。 |
CascadeClassifier::read
讀取一個檔案儲存體節點的分類器。
C++: bool CascadeClassifier::read(const FileNode& node)
CascadeClassifier::detectMultiScale
對不同大小的輸入映像進行物體識別,並返回一個識別到的物體的矩陣列表。
C++: void CascadeClassifier::detectMultiScale(const Mat& image, vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size())
| 參數 |
- image – 需要檢測的 CV_8U 輸入矩陣。
- objects – 輸出vector載體容器用於儲存被識別的物體矩陣。
- scaleFactor – 指定每張圖片的縮小比例的參數。
- minNeighbors – 指定每個候選矩陣至少包含的鄰近元素個數。
- flags – 與舊版級聯分類器模型函數cvHaarDetectObjects的flags相同. 此參數不被用於新版模型。
- minSize – 最小可能的對象的大小,小於的對象將被忽略。
- maxSize – 最大可能的對象的大小,大於的對象將被忽略。
|
CascadeClassifier::setImage
設定被用於檢測的映像。
C++: bool CascadeClassifier::setImage(Ptr<FeatureEvaluator>& feval, const Mat& image)
| 參數 |
- feval – 用於特徵計算的特徵求值程式的指標。
- image – 需要進行特徵檢測的 CV_8U 輸入矩陣。
|
這個函數將在每張圖片中被 CascadeClassifier::detectMultiScale() 自動調用。 但如果你想在不同位置手動使用 CascadeClassifier::runAt(),你需要先調用該函數,使得映像被積分計算。
CascadeClassifier::runAt
在指定點運行檢測。
C++: int CascadeClassifier::runAt(Ptr<FeatureEvaluator>& feval, Point pt, double& weight)
| 參數 |
feval – 用於特徵計算的特徵求值程式。 pt – 指定檢測視窗左上方的點。視窗的大小和檢測的圖片大小一致。 |
如果級聯分類器檢測到給定的位置中的一個對象,該函數返回1。否則,它會返回已被否決的候選地區在哪個階段的否定的指數。
使用CascadeClassifier::setImage() 設定映像的檢測工作。
代碼注釋:
複製代碼 代碼如下://需要載入的級聯分類器檔案
string face_cascade_name = "haarcascade_frontalface_alt.xml";
//級聯分類器類
CascadeClassifier face_cascade;
//……
//載入級聯分類器,並判斷是否載入成功,如果不成功則列印提示
if( !face_cascade.load( face_cascade_name ) ){
printf("[error] 無法載入級聯分類器檔案!\n");
return -1;
}
//……
//對圖片frame進行識別檢測
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
轉換成灰階圖
由於CascadeClassifier類只支援CV_8U矩陣資料,所以我們需要將圖片變成灰階圖。
cvtColor API:
將圖片從一個色彩空間轉到另一個色彩空間。
C++: void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )
| 參數 |
- src – 輸入映像:8位無符號,16位無符號(CV_16UC...),或單精確度浮點數據類型。
- dst – 輸出映像,與輸入映像相同大小、深度。
- code – 色彩空間轉換代碼。
- dstCn – 靶心圖表像的通道數,當該參數為0時,則通道樹由src和code自動得出。
|
該函數將輸入圖片從一個色彩空間轉到另一個色彩空間。當從RGB色彩空間進行變換時,應明確指定的通道的順序(RGB或BGR)。值得注意,在OpenCV的預設顏色格式中,通常被稱為作為RGB,但實際上是BGR(位元組是相反的)。因此,在一個標準的(24位)的彩色映像的第一個位元組是一個8位的藍色分量,第二個位元組將是綠色的,第三個位元組將是紅色的。而第四,第五,和第六位元組,則是第二像素(藍,然後綠色,然後紅色),依此類推。
R、G和B 通道通常通道值範圍:
CV_8U:0 — 255
CV_16U:0 — 65535
CV_32F:0 — 1
線性變換的情況下,有沒有範圍是無所謂的。但是,在一個非線性變換的情況下,輸入的RGB映像應被歸為適當的值範圍內,以得到正確的結果。例如,如果你有一個32位浮點映像直接轉換成一個8位的映像而沒有任何縮放,那麼它將有0到255的數值範圍,而這並不能準確0..1所有浮點數的值。所以,你需要之前調用cvtColor,進行映像縮放。
代碼注釋: 複製代碼 代碼如下://將frame轉換成灰階圖,輸出到frame_gray
cvtColor( frame, frame_gray, CV_BGR2GRAY );
長條圖均衡化
長條圖是映像中像素強度分布的圖形表達方式。
它統計了每一個強度值所具有的像素個數。
長條圖均衡化是通過展開像素強度分布範圍來增強映像對比的一種方法。
說得更清楚一些, 以上面的長條圖為例, 你可以看到像素主要集中在中間的一些強度值上. 長條圖均衡化要做的就是 展開 這個範圍. 見下面左圖: 綠圈圈出了 少有像素分布其上的 強度值. 對其應用均衡化後, 得到了中間圖所示的長條圖. 均衡化的映像見下面右圖.
我們利用長條圖均衡化對圖片增強對比,方便級聯分類器分析。
equalizeHist API:
對灰階映像進行長條圖均衡。
C++: void equalizeHist(InputArray src, OutputArray dst)
table4
長條圖均衡函數使用了下列的算髮:
計算源檔案的長條圖 。
調整長條圖,使得其方格總個數為255。
對長條圖進行積分:
使用變換圖片,其映射函數為:。
該演算法歸一化亮度並增加了映像的對比。