奥比中光网络深度摄像头——人脸活体检测

        最近一直在研发一个新的项目:基于深度摄像头的人脸活体识别,采用的是奥比中光的Astra Pro相机。

基于奥比中光官方SDK进行开发

得到如下文件

1.第一步,在彩色图中添加OpenCV人脸检测代码,得到人脸框的位置坐标

2.第二步,根据人脸框的位置坐标对应到深度图中,标识出来(深度图和彩色图的大小一样,但是他们并没有对齐,这里只做效果)

3.第三步,计算深度图中标识出来的人脸框中所有像素点的均值和标准差,真人的深度图像素标准查明显大于照片中的像素标准差,可以自己设置一个阈值。

彩色图OpenCV人脸检测代码片段如下:

//更新彩色流
void update_color(astra::Frame& frame)
{
	const astra::ColorFrame colorFrame = frame.get<astra::ColorFrame>();
	if (!colorFrame.is_valid())
	{
		clear_view(colorView_);
		colorView_.texture_.update(&colorView_.buffer_[0]);			
		return;
	}
	const int colorWidth = colorFrame.width();
	const int colorHeight = colorFrame.height();
	init_texture(colorWidth, colorHeight, colorView_);
	if (isPaused_) { return; }
	const astra::RgbPixel* color = colorFrame.data();
	uint8_t* buffer = &colorView_.buffer_[0];

	{
		const astra::RgbPixel* colorT = color;
		cv::Mat frame_copy(colorHeight, colorWidth, CV_8UC3);//定义Mat

		for (int j = 0; j<colorHeight; j++)
		{
			for (int i = 0; i<colorWidth; i++)
			{
				frame_copy.at<cv::Vec3b>(j, i)[0] = colorT->b;//image.at<cv::Vec3b>(j, i)[0] / div * div + div / 2;
				frame_copy.at<cv::Vec3b>(j, i)[1] = colorT->g;
				frame_copy.at<cv::Vec3b>(j, i)[2] = colorT->r;
				colorT++;
			}
		}
		CascadeClassifier face_cascade;
		face_cascade.load("C:\\myfiles\\opencv-3.2.0\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml");
		std::vector<Rect> faces;
		Rect roi1;
		Mat frame_gray;
		cvtColor(frame_copy, frame_gray, COLOR_BGR2GRAY);//转换为灰度图
		equalizeHist(frame_gray, frame_gray);//直方图均衡化
		face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));//--人脸检测
		
		cv::Mat foo(colorHeight, colorWidth, CV_8UC3, (void*)color);
		rois.clear();
		for (size_t i = 0; i < faces.size(); i++)
		{
			Rect roi;
			roi.x = faces[static_cast<int>(i)].x;
			roi.y = faces[static_cast<int>(i)].y;
			roi.width = faces[static_cast<int>(i)].width;
			roi.height = faces[static_cast<int>(i)].height;
			rois.push_back(roi);
			cv::rectangle(foo, roi, cv::Scalar(255, 0, 0),3);//在彩色图中画出人脸
		}
		for (int i = 0; i < colorWidth * colorHeight; i++)
		{
			const int rgbaOffset = i * 4;
			buffer[rgbaOffset] = color[i].r;
			buffer[rgbaOffset + 1] = color[i].g;
			buffer[rgbaOffset + 2] = color[i].b;
			buffer[rgbaOffset + 3] = 255;
		}
	}	
	colorView_.texture_.update(&colorView_.buffer_[0]);
}

深度图人脸框标识和计算均值标准差的代码片段如下:

	//更新深度流
	void update_depth(astra::Frame& frame)
	{
		const astra::PointFrame pointFrame = frame.get<astra::PointFrame>();//获取点云帧

		if (!pointFrame.is_valid())
		{
			clear_view(depthView_);
			depthView_.texture_.update(&depthView_.buffer_[0]);
			return;
		}
		const int depthWidth = pointFrame.width();
		const int depthHeight = pointFrame.height();
		init_texture(depthWidth, depthHeight, depthView_);//数据纹理
		if (isPaused_) { return; }
		visualizer_.update(pointFrame);
		astra::RgbPixel* vizBuffer = visualizer_.get_output();
		uint8_t* buffer = &depthView_.buffer_[0];

		cv::Mat fool(depthHeight, depthWidth, CV_8UC3, (void*)vizBuffer);
		const astra::RgbPixel* colorT = vizBuffer;

		for (int i = 0; i < rois.size(); i++)
		{	
			Mat out = fool(Rect(rois[i].x, rois[i].y, rois[i].width, rois[i].height));//将人脸位置截取出来
			Mat means, stddev, covar;
			meanStdDev(out, means, stddev);//计算src图片的均值和标准差
			double stddev_sum = 0;
			double stddev_avg = 0;
			for (int row = 0; row < means.rows; row++)
			{
				stddev_sum = stddev_sum + stddev.at<double>(row);
			}
			stddev_avg = stddev_sum / means.rows;//计算平均标准差
			stringstream ss,sss;
			ss << "real_" << stddev_avg;
			sss << "unreal_" << stddev_avg;
			int font = cv::FONT_HERSHEY_COMPLEX;
			if (stddev_avg > 60)
			{
				printf("真人!标准差 = %.3f\n", stddev_avg);
				cv::rectangle(fool,rois[i], cv::Scalar(255, 0, 0),3);//在深度图中画出人脸
				cv::putText(fool, ss.str(), cvPoint(rois[i].x, rois[i].y),font,1.5, cv::Scalar(255, 0, 0),2);
			}
			else
			{
				printf("假人!标准差 = %.3f\n", stddev_avg);
				cv::rectangle(fool, rois[i], cv::Scalar(0, 255, 0),3);//在深度图中画出人脸
				cv::putText(fool, sss.str(), cvPoint(rois[i].x, rois[i].y), font, 1.5, cv::Scalar(0, 255, 0),2);
			}
		}
		
		for (int i = 0; i < depthWidth * depthHeight; i++)
		{
			const int rgbaOffset = i * 4;//4通道
			buffer[rgbaOffset] = vizBuffer[i].r;//第一个通道
			buffer[rgbaOffset + 1] = vizBuffer[i].g;//第二个通道
			buffer[rgbaOffset + 2] = vizBuffer[i].b;//第三个通道
			buffer[rgbaOffset + 3] = 255;//第四个通道
		}
		depthView_.texture_.update(&depthView_.buffer_[0]);
	}

效果如下:

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值