最近一直在研发一个新的项目:基于深度摄像头的人脸活体识别,采用的是奥比中光的Astra Pro相机。
基于奥比中光的官方SDK进行开发
得到如下文件
1.第一步,在彩色图中添加OpenCV人脸检测代码,得到人脸框的位置坐标
2.第二步,根据人脸框的位置坐标对应到深度图中,标识出来(深度图和彩色图的大小一样,但是他们并没有对齐,这里只做效果)
3.第三步,计算深度图中标识出来的人脸框中所有像素点的均值和标准差,真人的深度图像素标准查明显大于照片中的像素标准差,可以自己设置一个阈值。
彩色图OpenCV人脸检测代码片段如下:
//更新彩色流
void update_color(astra::Frame& frame)
{
const astra::ColorFrame colorFrame = frame.get();
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(j, i)[0] = colorT->b;//image.at(j, i)[0] / div * div + div / 2;
frame_copy.at(j, i)[1] = colorT->g;
frame_copy.at(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 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(i)].x;
roi.y = faces[static_cast(i)].y;
roi.width = faces[static_cast(i)].width;
roi.height = faces[static_cast(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();//获取点云帧
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(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]);
}
效果如下: