基于OpenCV_C++人脸检测打码技术

 人脸检测并打码的关键,首先需要定位人脸区域,再修改人脸区域像素灰度值。

一 定义马赛克函数

定义生成马赛克函数 Generate_Mosaic,对图形 Mat& src 做操作,将需要操作的块(faces)存入数组 vector& faces 中(表示用矩形区域描述)。

src:代表马赛克效果的图片;        faces:显示马赛克的区域;        Rect:矩形区域(x,y,w,h)

马赛克函数思想过程:定义马赛克大小为10像素,int step = 10。for (int t = 0; t < faces.size(); t++) 对每一张脸进行马赛克操作。再确定 faces 所在区域(x, y, w, h),然后针对 faces 所在进行马赛克处理。10像素的矩形遍历人脸矩形框区域像素,再将矩形框细分成若干个小方块,依次修改每个方块的像素,相同方块赋予相同灰度值。

src.at (k, m)[c] (原图的颜色, 位置(k, m),[C]颜色值)

bool Generate_Mosaic(Mat& src, vector& faces)
{
	if (faces.empty())return false;

	int step = 10;//步长

	for (int t = 0; t < faces.size(); t++)
	{
		int x = faces[t].tl().x; //人脸矩形框起点x坐标
		int y = faces[t].tl().y;//人脸矩形框起点y坐标
		int width = faces[t].width;//人脸矩形框宽
		int height = faces[t].height;//人脸矩形框高

		//仅对人脸区域进行像素修改。遍历人脸矩形框区域像素,并对其进行修改
		for (int i = y; i < (y + height); i += step)
		{
			for (int j = x; j < (x + width); j += step)
			{
				//将人脸矩形框再细分为若干个小方块,依次对每个方块修改像素(相同方块赋予相同灰度值)
				for (int k = i; k < (step + i); k++)
				{
					for (int m = j; m < (step + j); m++)
					{
						//对矩形区域像素值进行修改,rgb三通道
						for (int c = 0; c < 3; c++)
						{
							src.at(k, m)[c] = src.at(i, j)[c];
						}
					}
				}
			}
		}
	}

	return true;
}

二 单张图片做打码处理

定义单张图片打码函数  Picture_Demo,将图片 Mat src 传入函数。首先加载人脸检测配置文件。在 OpenCV 中,人脸检测用的是 harr 或 LBP 特征,分类算法用的是 adaboost 算法。这种算法需要提前训练大量的图片,非常耗时,因此 OpenCV 已经训练好了,把训练结果存放在一些 xml 文件里面。然后创建人脸检测器并存储人脸检测的结果,人脸检测主要用到的是 CascadeClassifier 这个类,以及该类下的 detectMultiScale 函数。

detector.detectMultiScale(src, faces, 1.1, 5),src 检测的图片,faces 存储的结果,1.1 缩放尺寸

bool Picture_Demo(Mat src)
{
	//人脸检测配置文件
	string harr_file = "haarcascade_frontalface_default.xml";

	//创建人脸检测器
	CascadeClassifier detector;
	detector.load(harr_file);

	//人脸检测,存储人脸检测的结果
	vectorfaces;
	detector.detectMultiScale(src, faces, 1.1, 5);

	if (!Generate_Mosaic(src, faces))return false;

	imshow("test", src);
	waitKey(0);
	return true;
}

三 视频打码操作

视频主要涉及视频的读取以及视频的保存

//把视频转图像操作
void VideoToImg()
{
	VideoCapture cap = VideoCapture("视频路径");   //创建一个对象cap,打开一个视频,若参数设为0则为打开默认摄像头
		if(!cap.isOpened())
		{
			cout << "打开失败。。。" << endl;
			return;

	}
// 如果成功开打,视频的每一帧都在对象cap中
		Mat img;  //定义图片
		int i = 1;
		while (true)    //用流的方式将图片导出来
		{
			cap >> img;  //拿出一帧
			if (img.empty())
				break;
			imshow("img", img);   //显示图片
			string URL = "data/img" + to_string(i) + ".jpg";   //定义图片存储路径 data/img0.jpg
			imwrite(URL, img);         //把图片写入文件
			waitKey(30); //延迟30ms
			i++;
		}
		return;
}

打开摄像头,获取每一帧图片并显示在窗口上。 

//打开摄像头
void VideoToImg()
{
	VideoCapture cap = VideoCapture(0);   //创建一个对象cap,打开一个视频,若参数设为0则为打开默认摄像头
	if (!cap.isOpened())
	{
		cout << "打开失败。。。" << endl;
		return;

	}
	// 如果成功开打,视频的每一帧都在对象cap中
	Mat img;  //定义图片
	while (true)    //用流的方式将图片导出来
	{
		cap >> img;  //拿出一帧
		if (img.empty())
			break;
		imshow("img", img);   //显示图片
		char userKey = waitKey(10);
			if (userKey == 27)      //如果userkey为esc键,退出循环
				break;
	}
	return;
}

 将摄像头捕获的视频分成每一帧,将每帧保存为一张图片,再使用马赛克函数完成打码操作。

其中加载人脸检测配置文件、创建人脸检测器及保存人脸检测结果与单张图片做马赛克相同。

flip(frame, frame, 1) 用filp切割视频,一帧一帧的拿出来

bool Video_Demo()
{
	//人脸检测配置文件
	string harr_file = "haarcascade_frontalface_default.xml";

	//创建人脸检测器
	CascadeClassifier detector;
	detector.load(harr_file);

	VideoCapture cap;
	cap.open(0);
	if (!cap.isOpened())
	{
		cout << "can not open the camera!" << endl;
	}

	Mat frame;
	while (cap.read(frame))
	{
		flip(frame, frame, 1);   //函数的方式取出帧

		//人脸检测
		vectorfaces;
		detector.detectMultiScale(frame, faces, 1.1, 5);

		if (Generate_Mosaic(frame, faces))
		{
			imshow("Demo", frame);
		}
		char key = waitKey(10);
		if (key == 27)break;
	}

	cap.release();

	return true;
}

四 源码

#include
#include
using namespace std;
using namespace cv;

bool Generate_Mosaic(Mat& src, vector& faces)
{
	if (faces.empty())return false;

	int step = 10;//步长

	for (int t = 0; t < faces.size(); t++)
	{
		int x = faces[t].tl().x; //人脸矩形框起点x坐标
		int y = faces[t].tl().y;//人脸矩形框起点y坐标
		int width = faces[t].width;//人脸矩形框宽
		int height = faces[t].height;//人脸矩形框高

		//仅对人脸区域进行像素修改。遍历人脸矩形框区域像素,并对其进行修改
		for (int i = y; i < (y + height); i += step)
		{
			for (int j = x; j < (x + width); j += step)
			{
				//将人脸矩形框再细分为若干个小方块,依次对每个方块修改像素(相同方块赋予相同灰度值)
				for (int k = i; k < (step + i); k++)
				{
					for (int m = j; m < (step + j); m++)
					{
						//对矩形区域像素值进行修改,rgb三通道
						for (int c = 0; c < 3; c++)
						{
							src.at(k, m)[c] = src.at(i, j)[c];
						}
					}
				}
			}
		}
	}

	return true;
}

/*
void TestMosaic(Mat& src)
{
	vector faces;
	faces.push_back(Rect(100, 100, 200, 200));
	faces.push_back(Rect(300, 300, 200, 200));
	Generate_Mosaic(src, faces);
}
*/


//对单张图片打马赛克
bool Picture_Demo(Mat src)
{
	//人脸检测配置文件
	string harr_file = "haarcascade_frontalface_default.xml";

	//创建人脸检测器
	CascadeClassifier detector;
	detector.load(harr_file);

	//人脸检测,存储人脸检测的结果
	vectorfaces;
	detector.detectMultiScale(src, faces, 1.1, 5);

	if (!Generate_Mosaic(src, faces))return false;

	imshow("test", src);
	waitKey(0);
	return true;
}

//把视频转图像操作
void VideoToImg()
{
	VideoCapture cap = VideoCapture("视频路径");   //创建一个对象cap,打开一个视频,若参数设为0则为打开默认摄像头
		if(!cap.isOpened())
		{
			cout << "打开失败。。。" << endl;
			return;

	}
// 如果成功开打,视频的每一帧都在对象cap中
		Mat img;  //定义图片
		int i = 1;
		while (true)    //用流的方式将图片导出来
		{
			cap >> img;  //拿出一帧
			if (img.empty())
				break;
			imshow("img", img);   //显示图片
			string URL = "data/img" + to_string(i) + ".jpg";   //定义图片存储路径 data/img0.jpg
			imwrite(URL, img);         //把图片写入文件
			waitKey(30); //延迟30ms
			i++;
		}
		return;
}
/*
//打开摄像头,并在窗口上显示每一帧图片
void VideoToImg()
{
	VideoCapture cap = VideoCapture(0);   //创建一个对象cap,打开一个视频,若参数设为0则为打开默认摄像头
	if (!cap.isOpened())
	{
		cout << "打开失败。。。" << endl;
		return;

	}
	// 如果成功开打,视频的每一帧都在对象cap中
	Mat img;  //定义图片
	while (true)    //用流的方式将图片导出来
	{
		cap >> img;  //拿出一帧
		if (img.empty())
			break;
		imshow("img", img);   //显示图片
		char userKey = waitKey(10);
			if (userKey == 27)      //如果userkey为esc键,退出循环
				break;
	}
	return;
}
*/


//对视频打马赛克
bool Video_Demo()
{
	//人脸检测配置文件
	string harr_file = "haarcascade_frontalface_default.xml";

	//创建人脸检测器
	CascadeClassifier detector;
	detector.load(harr_file);

	VideoCapture cap;
	cap.open(0);
	if (!cap.isOpened())
	{
		cout << "can not open the camera!" << endl;
	}

	Mat frame;
	while (cap.read(frame))
	{
		flip(frame, frame, 1);

		//人脸检测
		vectorfaces;
		detector.detectMultiScale(frame, faces, 1.1, 5);

		if (Generate_Mosaic(frame, faces))
		{
			imshow("Demo", frame);
		}
		char key = waitKey(10);
		if (key == 27)break;
	}

	cap.release();

	return true;
}

int main()
{
	Mat src = imread("图片路径");
	if (src.empty())
	{
		cout << "No Image!" << endl;
		system("pause");
		return -1;
	}
	//TestMosaic(src);
	Picture_Demo(src);

	//Video_Demo();

	system("pause");
	return 0;
}

五 运行效果

基于OpenCV_C++人脸检测打码技术_第1张图片

 

你可能感兴趣的:(opencv,人工智能,计算机视觉)