記事のディレクトリ
序文
libfacedetectionライブラリを使用すると、画像に対して顔認識を実行できます。次に、複数の画像を認識できます。つまり、ビデオでの顔認識です。
1. libfacedetectionの構成と基本的な紹介:
この記事で詳細な紹介をしました:https://blog.csdn.net/ivan_9/article/details/113336452
2、VideoCaptureクラス:
1.コンストラクタータイプ:
2.1.1、VideoCapture();
はじめに:VideoCapture();はVideoCaptureクラスのデフォルトコンストラクタです。
2.1.2、VideoCapture(const String&filename、int apiPreference = CAP_ANY);
簡単な分析:ビデオファイルまたはキャプチャデバイスまたはIPビデオストリームを開いて、ビデオキャプチャのAPIプリファレンスを使用します
。filenameこのパラメータは次のとおりです。
- ビデオファイルの名前(例
视频.avi
) - 画像シーケンス(たとえば、「img \ uu02d.jpg」、「img \ u 00.jpg、img \ u 01.jpg、img \ u 02.jpg、...」と表示されます)
- ビデオストリームのURL(例
协议://主机:端口/脚本名称?脚本|参数| auth
) - gstスタートアップツール形式のGStreamerパイプライン文字列。GStreamerがバックエンドとして使用されている場合、各ビデオストリームまたはIPカメラフィードには独自のURLスキームがあります。
- 使用するキャプチャAPIバックエンドが推奨されます。特定のリーダーを強制するために使用できます
2.1.3、VideoCapture(int index、int apiPreference = CAP_ANY);
簡単な分析:ビデオキャプチャのためにカメラをオンにします
- 開くビデオキャプチャデバイスのパラメータインデックスID。
- デフォルトのバックエンドでデフォルトのカメラを開くには、0を渡すだけです。他の外部カメラまたは他のカメラの場合は、1を渡すだけです。
- apippreferenceは、使用するキャプチャAPIバックエンドを優先しました。特定のリーダーを強制するために使用できます
- 利用可能な実装が複数ある場合:例:cv :: CAP_DSHOWまたはcv :: CAP_MSMFまたはcv :: CAP_V4L。
2.コンストラクターの特定の定義:
class CV_EXPORTS_W VideoCapture{
public:
CV_WRAP VideoCapture();
CV_WRAP explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY)
CV_WRAP explicit VideoCapture(int index, int apiPreference = CAP_ANY);
}
3. VideoCaptureクラスの機能:
1、open();関数
はじめに:ビデオキャプチャに使用されるビデオファイル、キャプチャデバイス、またはIPビデオストリームを開きます。
3.1.1。最初の使用:
VideoCapture capture;
captrue.open("有趣的灵魂.mp4");//可以是avi,可以是mp4格式的视频文件
3.1.2。2番目の使用法:
VideoCapture capture("有趣的灵魂.mp4");//利用构造函数直接获取
2. isOpened()関数:
簡単な分析:ビデオキャプチャが初期化されている場合は、trueを返し、読み取りが成功したかどうかを判断します
if (cap.isOpened()) {
cout << "恭喜你打开视频文件了!" << endl;
}
else {
cout << "对不起你没打开视频文件!" << endl;
return -1;
}
3. release()関数:
簡単な分析:ビデオファイルまたはキャプチャデバイスを閉じることはopen()関数に対応します。release()関数を見逃さないことが最善です。
VideoCapture capture;
captrue.open("有趣的灵魂.mp4");
cap.release();
4. Grab()関数とretrieve()関数:
簡単な分析:grab()関数は、ビデオファイルまたはカメラから次のフレームを取得し、trueを返します(成功例)。
この関数は、カメラごとにVideoCapture :: grab()を呼び出してから、低速のメソッドVideoCapture :: retrieve()を呼び出して、各カメラからフレームをデコードして取得します。この方法は、デモザイキングまたはモーションjpeg解凍のオーバーヘッドを排除し、さまざまなカメラからのフレームを復元して時間的に近づけます。
分析:retrieve()関数は、キャプチャされたビデオフレームをデコードして返します。
このメソッドは、取得したばかりのフレームをデコードして返します。フレームがキャプチャされていない場合(カメラが切断されている場合、またはビデオファイルにフレームがない場合)、メソッドはfalseを返します。この関数は空の画像を返します(%cv :: Matを使用し、Mat :: empty()を使用してテストします)
//这两个函数一般一起使用
cap.grab();
cap.retrieve(src);//src是每帧的图像对象
5. read()関数:
簡単な分析:取得、デコード、次のビデオフレームに戻る
cap.read(src);
6. Set()関数:
簡単な分析:VideoCaptureでプロパティを設定します
cap.set(3, 480)
//把视频流的帧(图片)的高度调成480帧的,宽度为5
6. get()関数:
簡単な分析:指定されたVideoCaptureプロパティを返します
cap.get(0)
//视频文件的当前位置(播放)以毫秒为单位
4、ビデオ顔認識
コードブロック:
//视频的人脸识别
#include <iostream>
#include <opencv2/opencv.hpp>
#include <facedetectcnn.h>
#include <stdlib.h>
#define DETECT_BUFFER_SIZE 0x20000 //定义缓冲区大小
#define FACEDETECTION_EXPORT
using namespace std;
using namespace cv;
int main() {
Mat src, dst, image;
VideoCapture cap;
int count = 1;
cap.open("D:\\Myfile\\素材照片\\视频图像截取\\视频1.avi");
if (cap.isOpened()) {
//pBuffer用来检测人脸
unsigned char* pBuffer = new unsigned char[DETECT_BUFFER_SIZE]; //multiple threads
//是多线程时,要分配内存空间
if (!pBuffer) {
//如果无法分配内存,就返回could not alloc buffer!
cout << "could not alloc buffer!" << endl;
return 0;
}
system("cls"); //清屏
while (true)
{
cap >> src;// cap.read(src);
if (!src.data) {
//若不存在就返回 could not load your image!
cout << "could not load your image!" << endl;
return 0;
}
dst = src.clone(); //将src原图像复制给dst
TickMeter myClock; //计时器
myClock.start();
int* pResults = NULL; //用来检测人脸
pResults = facedetect_cnn(pBuffer, (unsigned char*)(src.ptr(0)), src.cols, src.rows, src.step);
//利用facedetect_cnn函数来获取人脸,用于存储人脸检测结果的缓冲存储器!其大小必须为0x20000字节
//facedetect_cnn函数识别的图像必须为BGR三通道的图像,而非rgb图像
myClock.stop();
cout << "这帧图像的耗费时长:" << myClock.getTimeSec() << "s" ; //输出检测人脸耗费时长
for (int i = 0; i < (pResults ? (*pResults) : 0); i++) {
//如果pResult为NULL,即pResult没有检测到人脸,就返回0,for循环结束
short* p = ((short*)(pResults + 1)) + (142 * i);
//p指针用来指向
int confidence = p[0];
if (confidence < 88) {
cout << "------这帧图像没有人脸!!!\n\n";
continue;
}
else cout << "--这帧图像有人脸!!!\n";
int x = p[1];
int y = p[2];
int w = p[3];
int h = p[4];
//显示脸的分数。其范围为[0-100]
char sScore[256];
snprintf(sScore, 256, "%d", confidence);
/*从给定位置加载数据,转换为字符串等价版本,并将结果写入各种池。
1) 写结果到 stdout 。2) 写结果到文件流 stream 。3) 写结果到字符串 buffer 。
4) 写结果到字符串 buffer 。至多写 buf_size - 1 个字符。产生的字符串会以空字符终止,除非 buf_size 为零。
若buf_size为零,则不写入任何内容,且buffer可以是空指针,然而依旧计算返回值(会写入的字符数,不包含空终止符)并返回。
若调用 sprintf 或 snprintf 导致在重叠的对象间发生复制,则行为未定义。
(例如 sprintf(buf, "%s text", buf); )*/
putText(dst, sScore, Point(x, y - 3), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1);
//计算文本字符串的宽度和高度
//把脸用矩形画出来
rectangle(dst, Rect(x, y, w, h), Scalar(0, 255, 0), 2);
image = dst(Rect(x, y, w, h));
//画五个不同颜色的面部标志
circle(dst, Point(p[5], p[5 + 1]), 1, Scalar(255, 0, 0), 2);
circle(dst, Point(p[5 + 2], p[5 + 3]), 1, Scalar(0, 0, 255), 2);
circle(dst, Point(p[5 + 4], p[5 + 5]), 1, Scalar(0, 255, 0), 2);
circle(dst, Point(p[5 + 6], p[5 + 7]), 1, Scalar(255, 0, 255), 2);
circle(dst, Point(p[5 + 8], p[5 + 9]), 1, Scalar(0, 255, 255), 2);
//circle()绘制简单或粗椭圆弧或填充椭圆扇区。
/*
Point类的实例可以与C结构、CvPoint和CvPoint2D32f互换。
还有一个cast操作符将点坐标转换为指定的类型。
从浮点坐标到整数坐标的转换是通过舍入完成的。
通常,转换对每个坐标都使用此操作。
*/
printf("face %d: confidence=%d, [%d, %d, %d, %d] (%d,%d) (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n\n",
i, confidence, x, y, w, h, p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14]);
namedWindow("output_detect_image", WINDOW_AUTOSIZE);
imshow("output_detect_image", dst); //输出识别后的图像
string str = "D:\\Myfile\\素材照片\\视频图像截取\\" + to_string(count) + ".jpg"; //制定保存的命名规则
imwrite(str, image); //将人脸截取出来并保存起来
count++;
waitKey(4000); //让每一张图片停留4s
}
}
//release the buffer
delete pBuffer;
}
else cout << "could not load video!" << endl;
cap.release();
return 0;
}
演算結果:
総括する
この記事では、videoCaptureクラスの使用について簡単に説明し、ビデオの顔認識を実行します
参考資料
https://github.com/ShiqiYu/libfacedetection#cnn-based-face-detection-on-windows
ご不明な点がございましたら、メッセージを残してください!エラーが発生した場合は、アドバイスしてください!