步驟:
1、利用Opencv自帶的分類器檢測人臉
預備知識:Haar特徵分類器
Haar特徵分類器就是一個XML文件,該文件中會描述人體各個部位的Haar特徵值。包括人臉、眼睛、嘴脣等等。
Haar特徵分類器存放地址:
(找自己的安裝目錄)
1、D:\opencv\opencv4.0\opencv4.0.0\sources\data\haarcascades
2、D:\opencv\opencv4.0\opencv4.0.0\build\etc\haarcascades
總覽一下:
haarcascade_eye.xml ;僅可以檢測睜開的眼睛
haarcascade_eye_tree_eyeglasses.xml;僅在帶被檢測者戴眼鏡時方可檢測
haarcascade_frontalcatface.xml
haarcascade_frontalcatface_extended.xml
haarcascade_frontalface_alt.xml
haarcascade_frontalface_alt_tree.xml
haarcascade_frontalface_alt2.xml;個人感覺這個好用點
haarcascade_frontalface_default.xml
haarcascade_fullbody.xml
haarcascade_lefteye_2splits.xml
haarcascade_licence_plate_rus_16stages.xml
haarcascade_lowerbody.xml
haarcascade_profileface.xml
haarcascade_righteye_2splits.xml
haarcascade_russian_plate_number.xml
haarcascade_smile.xml
haarcascade_upperbody.xml
detectMultiScale函數詳解
void detectMultiScale(
const Mat& image,
CV_OUT vector<Rect>& objects,
double scaleFactor = 1.1,
int minNeighbors = 3,
int flags = 0,
Size minSize = Size(),
Size maxSize = Size()
);
函數介紹:
參數1:image–待檢測圖片,一般爲灰度圖像加快檢測速度;
參數2:objects–被檢測物體的矩形框向量組;
參數3:scaleFactor–表示在前後兩次相繼的掃描中,搜索窗口的比例係數。默認爲1.1即每次搜索窗口依次擴大10%;
參數4:minNeighbors–表示構成檢測目標的相鄰矩形的最小個數(默認爲3個)。
如果組成檢測目標的小矩形的個數和小於 min_neighbors - 1 都會被排除。
如果min_neighbors 爲 0, 則函數不做任何操作就返回所有的被檢候選矩形框,
這種設定值一般用在用戶自定義對檢測結果的組合程序上;
參數5:flags–要麼使用默認值,要麼使用CV_HAAR_DO_CANNY_PRUNING,如果設置爲
CV_HAAR_DO_CANNY_PRUNING,那麼函數將會使用Canny邊緣檢測來排除邊緣過多或過少的區域,
因此這些區域通常不會是人臉所在區域;
參數6、7:minSize和maxSize用來限制得到的目標區域的範圍。
代碼實現:
#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include "My_ImageProssing_base.h"
using namespace cv;
using namespace std;
//訓練文件路徑
string xmlPath = "D:\\opencv\\opencv4.0\\opencv4.0.0\\build\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml";
int main(int argc, char** atgv) {
Mat img = imread("D:\\opencv_picture_test\\beauty\\裴佳欣.png",0);
//Mat img = imread("D:\\opencv_picture_test\\新垣結衣\\test2.jpg");
imshow("input image", img);
//【1】加載分類器
CascadeClassifier detector;
detector.load(xmlPath);
if (!detector.load(xmlPath)) //加載訓練文件
{
cout << "不能加載指定的xml文件" << endl;
return -1;
}
//【2】檢測人臉,將信息存儲到矩形類faces中
vector<Rect> faces;
//OpenCV的Rect矩形類用法
//如果創建一個Rect對象rect那麼rect會有以下幾個功能:
//rect.area(); //返回rect的面積
//rect.size(); //返回rect的尺寸
//rect.tl(); //返回rect的左上頂點的座標
//rect.br(); //返回rect的右下頂點的座標
//rect.width(); //返回rect的寬度
//rect.height(); //返回rect的高度
//rect.contains(Point(x, y)); //返回布爾變量,判斷rect是否包含Point(x, y)點
detector.detectMultiScale(img,faces, 1.1, 3, 0);//分類器對象調用
//【3】框出人臉
for (size_t t = 0; t < faces.size(); t++) {
rectangle(img, faces[t], Scalar(0, 0, 255), 2, 8);
//faces[t]表示第t個的face的矩形類
//2代表線條寬度8是線型,默認取8
}
namedWindow("Result", WINDOW_NORMAL); //定義窗口顯示屬性
imshow("Result", img);
waitKey(0);
return 0;
}
2、對人臉矩形框內進行一些處理(這裏只對灰度圖進行處理)
1、打馬賽克(這裏我們使用均值濾波)
//打馬賽克函數
void mosaic(Mat& srcImage, Mat& dstImage, int times)
{
blur(srcImage,dstImage, Size(times*2+1, times * 2 + 1));
}
2、換成其他圖片(使用resize,根據人臉區域進行大小改變)//變身喬碧蘿
void paste(Mat& srcImage, Mat& dstImage)
{
resize(srcImage,dstImage, dstImage.size());
}
3、美顏磨皮(雙邊濾波)
void clearFreckle(Mat& srcImage, Mat& dstImage, int times)
{
bilateralFilter(srcImage, dstImage,times, times*2, times/2);
}
4、視頻處理
(模板)
VideoCapture capture(0);
//VideoCapture capture("D:\\opencv_picture_test\\videos\\臉.avi");
while (1)
{
Mat img;
capture >> img; //讀取當前幀
//imshow("原視頻", img); //顯示當前幀
cvtColor(img,img, COLOR_BGR2GRAY); //轉化爲灰度圖
Mat dstImage = img.clone();
//【2】檢測人臉,將信息存儲到矩形類faces中
vector<Rect> faces;
detector.detectMultiScale(img, faces, 1.1, 3, 0);//分類器對象調用
//【3】修改區域信息
.......
//修改完畢
imshow("處理後的視頻", dstImage); //顯示當前幀
if(waitKey(10) >=0 ) break; //延時10ms
}
完整的代碼(視頻+貼圖):
#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include "My_ImageProssing_base.h"
using namespace cv;
using namespace std;
//訓練文件路徑
string xmlPath = "D:\\opencv\\opencv4.0\\opencv4.0.0\\build\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml";
//打馬賽克函數
void mosaic(Mat& srcImage, Mat& dstImage, int times)
{
blur(srcImage,dstImage, Size(times*2+1, times * 2 + 1));
}
void clearFreckle(Mat& srcImage, Mat& dstImage, int times)
{
bilateralFilter(srcImage, dstImage,times, times*2, times/2);
}
void paste(Mat& srcImage, Mat& dstImage)
{
resize(srcImage,dstImage, dstImage.size());
}
int main()
{
//Mat img = imread("D:\\opencv_picture_test\\beauty\\裴佳欣.png",0);
Mat img2 = imread("D:\\opencv_picture_test\\趣圖景圖\\小豬.jpg",0);
//imshow("input image", img);
//【1】加載分類器
CascadeClassifier detector;
detector.load(xmlPath);
if (!detector.load(xmlPath)) //加載訓練文件
{
cout << "不能加載指定的xml文件" << endl;
return -1;
}
//調用攝像頭
VideoCapture capture(0); //類似於 int a=1;
//VideoCapture capture("D:\\opencv_picture_test\\videos\\臉.avi"); //類似於 int a=1;
while (1)
{
Mat img;
capture >> img; //讀取當前幀
//imshow("原視頻", img); //顯示當前幀
cvtColor(img,img, COLOR_BGR2GRAY); //轉化爲灰度圖
Mat dstImage = img.clone();
//【2】檢測人臉,將信息存儲到矩形類faces中
vector<Rect> faces;
detector.detectMultiScale(img, faces, 1.1, 3, 0);//分類器對象調用
//【3】修改區域信息
for (size_t t = 0; t < faces.size(); t++)
{
int rows = faces[t].height;
int cols = faces[t].width;
int start_y = faces[t].y;
int start_x = faces[t].x;
Mat ROI(rows, cols, CV_8UC1, Scalar(0));
Mat dstROI(rows, cols, CV_8UC1, Scalar(0));
for (int j = 0;j < rows;j++) //行循環
{
for (int i = 0;i < cols;i++) //列循環
{
//-------【開始處理每個像素】---------------
ROI.at<uchar>(j, i) = img.at<uchar>(j + start_y, i + start_x);
//-------【處理結束】---------------
}
}
//馬賽克化
//mosaic(ROI,dstROI,10);
//貼圖
paste(img2,dstROI);
//去雀斑(磨皮)
//clearFreckle(ROI, dstROI, 10);
for (int j = 0;j < rows;j++) //行循環
{
for (int i = 0;i < cols;i++) //列循環
{
//-------【開始處理每個像素】---------------
dstImage.at<uchar>(j + start_y, i + start_x) = dstROI.at<uchar>(j, i);
//-------【處理結束】---------------
}
}
}
imshow("處理後的視頻", dstImage); //顯示當前幀
if(waitKey(10) >=0 ) break; //延時10ms
}
return 0;
}
效果展示
1、馬賽克效果
2、磨皮效果(臉蛋更加白淨!!!)
3、變身喬碧蘿
視頻放不上來,就放gif動態圖了。
參考鏈接
haarcascade_eye.xml、eye_tree_eyeglasses.xml、haarcascade_lefteye_2splits.xml區別使用
OpenCV人臉識別–detectMultiScale函數