作者:小月月牙
编辑:王萌(深度学习冲鸭公众号)
著作权归作者所有,本文仅作学术分享,若侵权,请联系后台删文处理
Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件
imshow("grayimage", img);//显示img的图像(它是灰度图)
反过来,一个Mat数据,也可以写入文件,这样就把图片给存起来了。举个例子,读取Lena的照片文件,然后存到一个叫out的文件里。
imwrite("image.jpg", M);//显示M的图像
Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件
imwrite("grayimage.jpg", img);//显示img的图像(它是灰度图)
一个人脸检测的例子
这个例子,需要引用3个OpenCV的头文件:
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
当然,也可以一步到位,把所有的OpenCv库都引了
#include "opencv2/opencv.hpp"
应用iostream库,并使用命名空间来减少代码里面文字的输入量
#include
using namespace std;
using namespace cv;
定义两个分类器,分别用来检测脸和眼睛
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
加载已经训练好的分类器,其中face_cascade_name和eyes_cascade_name是xml格式的分类器文件名。(OpenCV的Github里有已经训练好的模型,可以免费下载)
face_cascade.load( face_cascade_name );
eyes_cascade.load( eyes_cascade_name );
定义一个检测人脸并显示检测结果的函数,函数的输入变量是Mat图像。
void detectAndDisplay( Mat frame )
输入的Mat变量frame是彩色的,色彩信息对检测没什么用。所以我们把它转成灰度图,并标准化。
Mat frame_gray;
cvtColor( frame, frame_gray, COLOR_BGR2GRAY );//转灰度
equalizeHist( frame_gray, frame_gray );//标准化
一张图里有可能会检测到多个人脸,我们可以把检测结果用一个叫faces的向量来存储。用分类器进行多尺度检测的函数叫detectMultiScale,这个函数有两个变量,第一个是输入的图像frame_gray,第二个是输出的结果faces。
std::vector
face_cascade.detectMultiScale( frame_gray, faces );//检测
由于faces是把检测结果存成了一个向量,所以我们可以用size()函数得到这个向量的长度。下面这个代码循环遍历了每个结果,计算了每张脸的位置。
for ( size_t i = 0; i
{
Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );//获得每张脸部中心的xy像素坐标
ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );//给每个脸画个圈圈框起来
}
上面这个循环里,还可以把检测到个每个脸的区域单独提取出来,再检测一下眼睛。然后嵌入一个用圈圈框出眼睛的循环。这一步,依然使用detectMultiScale函数进行检测。
Mat faceROI = frame_gray( faces[i] );//提取脸部区域
std::vector
eyes_cascade.detectMultiScale( faceROI, eyes );//检测眼睛
for ( size_t j = 0; j
{
Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );//获得每个眼睛的中心
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );//把每个眼睛用圈圈框起来
}
接下来,我们把上面的内容整合一下,这个人脸检测并显示检测结果的函数
detectAndDisplay可以写成这样
void detectAndDisplay( Mat frame )
{
Mat frame_gray;
cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
std::vector
face_cascade.detectMultiScale( frame_gray, faces );
for ( size_t i = 0; i
{
Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );
Mat faceROI = frame_gray( faces[i] );
//-- In each face, detect eyes
std::vector
eyes_cascade.detectMultiScale( faceROI, eyes );
for ( size_t j = 0; j
{
Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );
}
}
//-- Show what you got
imshow( "Capture - Face detection", frame );
}
实际中,循环读摄像头并用这个detectAndDisplay函数进行检测的代码可以这么写。
Mat frame;//存放摄像头捕获图像的frame变量,它是个Mat数据
while ( capture.read(frame) )//循环把摄像头图像放入frame变量
{
detectAndDisplay( frame );//检测人脸并显示结果
}
最后,我们来写一下主函数,把上面那个摄像头读取和人脸检测功能加上。
int main( int argc, const char** argv )
{
CommandLineParser parser(argc, argv,
"{help h||}"
"{face_cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}"
"{eyes_cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}"
"{camera|0|Camera device number.}");
parser.about( "\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n"
"You can use Haar or LBP features.\n\n" );
parser.printMessage();
String face_cascade_name = parser.get
String eyes_cascade_name = parser.get
//-- 1. Load the cascades
if( !face_cascade.load( face_cascade_name ) )
{
cout <<"--(!)Error loading face cascade\n";
return -1;
};
if( !eyes_cascade.load( eyes_cascade_name ) )
{
cout <<"--(!)Error loading eyes cascade\n";
return -1;
};
int camera_device &#61; parser.get
VideoCapture capture;
//-- 2. Read the video stream
capture.open( camera_device );
if ( ! capture.isOpened() )
{
cout <<"--(!)Error opening video capture\n";
return -1;
}
Mat frame;
while ( capture.read(frame) )
{
if( frame.empty() )
{
cout <<"--(!) No captured frame -- Break!\n";
break;
}
//-- 3. Apply the classifier to the frame
detectAndDisplay( frame );
if( waitKey(10) &#61;&#61; 27 )
{
break; // escape
}
}
return 0;
}
人脸检测完整的代码可去下方下载
https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp
已经训练好的分类器可去下方下载
https://github.com/opencv/opencv/tree/master/data/haarcascades
每天进步一丢丢
简要介绍下Tensorflow的计算图
Tensorflow是一个通过计算图的形式来表述计算的编程系统&#xff0c;计算图也叫数据流图&#xff0c;可以把计算图看做是一种有向图&#xff0c;Tensorflow中的每一个计算都是计算图上的一个节点&#xff0c;而节点之间的边描述了计算之间的依赖关系。