奥比中光
最近一直在研发一个新的项目:基于深度摄像头的人脸活体识别,采用的是奥比中光的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] / p * p + p / 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]);
}
效果如下:
相关阅读
一个录屏软件的流程基本就是: 图像采集 图像编码 将解码好的图像封装成视频 图像的采集: FFmpeg中有一个和多媒体设备
最近,一款名叫恋爱圈的社交产品获得了一笔千万的融资,作者对这款产品深度体验后进行了如下分析。最近,36Kr报道了一款名叫恋爱圈的社
国内证券业发展至今已有二十多年,受国内市场环境和金融监管影响已形成独具特色的商业模式。而今,随着科技快速发展和社会结构的演变
网红营销模式的成功,直接加剧了优质网红资源的竞争,一类公司选择收拢网红资源,做中间商赚差价;另一类公司选择前期孵化,中后期营销变现
Android USBCamera,UVCCamera开发通用库,我试用了普通的
Android直播开发之旅(10):AndroidUSBCamera,UVCCamera开发通用库