From 31e0d0c171b4d6a7dc9b9697e69e165651d3fe93 Mon Sep 17 00:00:00 2001
From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期三, 28 十二月 2016 18:32:20 +0800
Subject: [PATCH] face detect ok
---
RtspFace/make.sh | 19 +++
RtspFace/PL_H264Decoder.cpp | 13 +
RtspFace/main.cpp | 38 ++++--
RtspFace/PL_H264Encoder.cpp | 34 +++++-
RtspFace/PL_SensetimeFaceDetect.h | 11 ++
RtspFace/PL_AVFrameYUV420.cpp | 12 +-
RtspFace/PL_SensetimeFaceDetect.cpp | 155 +++++++++++++++++++++++++++---
7 files changed, 230 insertions(+), 52 deletions(-)
diff --git a/RtspFace/PL_AVFrameYUV420.cpp b/RtspFace/PL_AVFrameYUV420.cpp
index 5462ba9..495a852 100644
--- a/RtspFace/PL_AVFrameYUV420.cpp
+++ b/RtspFace/PL_AVFrameYUV420.cpp
@@ -113,12 +113,12 @@
in->lastFrame.pts = frame->pts;
//#test
- static size_t f=0;
- char fname[50];
- sprintf(fname, "%u.yuv420", ++f);
- FILE * pFile = fopen (fname,"wb");
- fwrite (in->buffer , sizeof(char), in->buffSize, pFile);
- fclose(pFile);
+ //static size_t f=0;
+ //char fname[50];
+ //sprintf(fname, "%u.yuv420", ++f);
+ //FILE * pFile = fopen (fname,"wb");
+ //fwrite (in->buffer , sizeof(char), in->buffSize, pFile);
+ //fclose(pFile);
return true;
}
diff --git a/RtspFace/PL_H264Decoder.cpp b/RtspFace/PL_H264Decoder.cpp
index 7a3b705..11ae388 100644
--- a/RtspFace/PL_H264Decoder.cpp
+++ b/RtspFace/PL_H264Decoder.cpp
@@ -162,7 +162,7 @@
return true;
}
-bool decodeH264(H264Decoder_Internal* in, uint8_t* buffer, size_t buffSize)
+bool decodeH264(H264Decoder_Internal* in, uint8_t* buffer, size_t buffSize, timeval pts)
{
AVPacket packet = {0};
int gotPicture = buffSize; // frameFinished
@@ -171,7 +171,9 @@
{
printf("av_packet_from_data error\n");
return false;
- }
+ }
+
+ packet.pts = packet.dts = (pts.tv_sec * 1000 * 1000 + pts.tv_usec) / 90000;
// decode
avcodec_decode_video2(in->pAVCodecContext, in->pAVFrame, &gotPicture, &packet);
@@ -222,12 +224,15 @@
bool ret = false;
if (pm.type == PipeMaterial::PMT_BYTES)
- ret = decodeH264(in, pm.buffer, pm.buffSize);
+ {
+ timeval pts = {0};
+ ret = decodeH264(in, pm.buffer, pm.buffSize, pts);
+ }
else if (pm.type == PipeMaterial::PMT_FRAME)
{
MB_Frame* frame = (MB_Frame*)pm.buffer;
- ret = decodeH264(in, frame->buffer, frame->buffSize);
+ ret = decodeH264(in, frame->buffer, frame->buffSize, frame->pts);
if (ret)
{
in->lastFrame.type = MB_Frame::MBFT_PTR_AVFRAME;
diff --git a/RtspFace/PL_H264Encoder.cpp b/RtspFace/PL_H264Encoder.cpp
index 5547256..33ffc40 100644
--- a/RtspFace/PL_H264Encoder.cpp
+++ b/RtspFace/PL_H264Encoder.cpp
@@ -5,8 +5,9 @@
{
#include <libavcodec/avcodec.h>
#include <libavutil/frame.h>
- #include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
+ #include <libavutil/opt.h>
+ #include <libavformat/avformat.h>
#include <libyuv.h>
}
@@ -104,11 +105,12 @@
in->pAVCodecContext->height = 600;//#todo from config
in->pAVCodecContext->time_base.num=1;
in->pAVCodecContext->time_base.den=25;
- in->pAVCodecContext->gop_size = 25;
+ in->pAVCodecContext->gop_size = 2;
in->pAVCodecContext->max_b_frames = 0;
+ //in->pAVCodecContext->profile = FF_PROFILE_H264_MAIN;
in->pAVCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
- //av_opt_set(c->priv_data, "preset", "superfast", 0);
+ av_opt_set(in->pAVCodecContext->priv_data, "preset", "superfast", 0);
//av_opt_set(c->priv_data, "tune", "zerolatency", 0);
if(avcodec_open2(in->pAVCodecContext, avCodec, NULL) >= 0)
@@ -261,6 +263,17 @@
return !(in->payError);
}
+bool encodeH264(H264Encoder_Internal* in, uint8_t* buffer, timeval pts)
+{
+ AVFrame avFrame;
+ avFrame.width = 1920;//#todo
+ avFrame.height = 1080;
+ avFrame.data[0] = buffer;
+ avFrame.data[1] = buffer + 1920*1080;
+ avFrame.data[2] = buffer + 1920*1080 + 1920*1080/4;
+ return encodeH264(in, &avFrame, pts);
+}
+
bool PL_H264Encoder::pay(const PipeMaterial& pm)
{
H264Encoder_Internal* in = (H264Encoder_Internal*)internal;
@@ -289,13 +302,20 @@
return false;
MB_Frame* frame = (MB_Frame*)pm.buffer;
- if (frame->type != MB_Frame::MBFT_PTR_AVFRAME)
+
+ bool ret;
+
+ if (frame->type == MB_Frame::MBFT_PTR_AVFRAME)
+ ret = encodeH264(in, (AVFrame*)(frame->buffer), frame->pts);
+ else if (frame->type == MB_Frame::MBFT_YUV420)
+ ret = encodeH264(in, (uint8_t*)(frame->buffer), frame->pts);
+ else
{
- printf("PL_H264Encoder::pay only support MBFT_PTR_AVFRAME\n");
+ printf("PL_H264Encoder::pay only support MBFT_PTR_AVFRAME / MBFT_YUV420\n");
+ in->payError = true;
return false;
}
-
- bool ret = encodeH264(in, (AVFrame*)(frame->buffer), frame->pts);
+
in->payError = !ret;
if (ret)
diff --git a/RtspFace/PL_SensetimeFaceDetect.cpp b/RtspFace/PL_SensetimeFaceDetect.cpp
index 5df118c..f6b22c1 100644
--- a/RtspFace/PL_SensetimeFaceDetect.cpp
+++ b/RtspFace/PL_SensetimeFaceDetect.cpp
@@ -1,20 +1,25 @@
#include "PL_SensetimeFaceDetect.h"
+#include "MaterialBuffer.h"
#include <opencv2/opencv.hpp>
#include <cv_face.h>
struct PL_SensetimeFaceDetect_Internal
{
- uint8_t buffer[1920*1080*4];
- size_t buffSize;
- size_t buffSizeMax;
+ //uint8_t buffer[1920*1080*4];
+ //size_t buffSize;
+ //size_t buffSizeMax;
MB_Frame lastFrame;
+ SensetimeFaceDetectConfig config;
bool payError;
+ cv_handle_t handle_track;
+
PL_SensetimeFaceDetect_Internal() :
- buffSize(0), buffSizeMax(sizeof(buffer)), lastFrame(),
- payError(true)
+ //buffSize(0), buffSizeMax(sizeof(buffer)),
+ lastFrame(), config(), payError(true),
+ handle_track(nullptr)
{
}
@@ -24,11 +29,15 @@
void reset()
{
- buffSize = 0;
+ //buffSize = 0;
payError = true;
MB_Frame _lastFrame;
lastFrame = _lastFrame;
+ SensetimeFaceDetectConfig _config;
+ config = _config;
+
+ handle_track = nullptr;
}
};
@@ -52,6 +61,37 @@
PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
in->reset();
+ SensetimeFaceDetectConfig* config = (SensetimeFaceDetectConfig*)args;
+ in->config = *config;
+ if (in->config.point_size == 21)
+ in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_21;
+ else if (in->config.point_size == 106)
+ in->config.point_size_config = CV_DETECT_ENABLE_ALIGN_106;
+ else
+ {
+ printf("alignment point size must be 21 or 106\n");
+ return false;
+ }
+
+ // init handle
+ cv_result_t cv_result = cv_face_create_tracker(&(in->handle_track), nullptr,
+ in->config.point_size_config | CV_FACE_TRACKING_TWO_THREAD);
+ if (cv_result != CV_OK)
+ {
+ printf("cv_face_create_tracker failed, error code %d\n", cv_result);
+ return false;
+ }
+
+ int val = 0;
+ cv_result = cv_face_track_set_detect_face_cnt_limit(in->handle_track, in->config.detect_face_cnt_limit, &val);
+ if (cv_result != CV_OK)
+ {
+ printf("cv_face_track_set_detect_face_cnt_limit failed, error : %d\n", cv_result);
+ return false;
+ }
+ else
+ printf("detect face count limit : %d\n", val);
+
return true;
}
@@ -59,6 +99,78 @@
{
PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
+ // destroy track handle
+ cv_face_destroy_tracker(in->handle_track);
+ in->handle_track = nullptr;
+}
+
+int doFaceDetect(PL_SensetimeFaceDetect_Internal* in,
+ uint8_t* buffer, size_t width, size_t height, size_t stride, cv_pixel_format cvPixFmt)
+{
+ //resize(bgr_frame, bgr_frame, Size(frame_width, frame_height), 0, 0, INTER_LINEAR);
+
+ int face_count = 0;
+ cv_result_t cv_result = CV_OK;
+ cv_face_t* p_face = nullptr;
+
+ // realtime track
+ cv_result = cv_face_track(in->handle_track, buffer, cvPixFmt,
+ width, height, stride,
+ CV_FACE_UP, &p_face, &face_count);
+ if (cv_result != CV_OK)
+ {
+ printf("cv_face_track failed, error : %d\n", cv_result);
+ cv_face_release_tracker_result(p_face, face_count);
+ return -1;
+ }
+
+ // draw the video
+ cv::Mat yuvMat(cv::Size(1920,1080), CV_8UC3, buffer);
+ cv::Mat yMat(cv::Size(1920,1080), CV_8UC1, buffer);
+ for (int i = 0; i < face_count; i++)
+ {
+ printf("face: %d-----[%d, %d, %d, %d]-----id: %d\n", i,
+ p_face[i].rect.left, p_face[i].rect.top,
+ p_face[i].rect.right, p_face[i].rect.bottom, p_face[i].ID);
+
+ printf("face pose: [yaw: %.2f, pitch: %.2f, roll: %.2f, eye distance: %.2f]\n",
+ p_face[i].yaw,
+ p_face[i].pitch, p_face[i].roll, p_face[i].eye_dist);
+
+ cv::Scalar scalar_color = CV_RGB(p_face[i].ID * 53 % 256,
+ p_face[i].ID * 93 % 256,
+ p_face[i].ID * 143 % 256);
+
+ //cv::rectangle(yMat, cv::Point2f(0, 0), cv::Point2f(50, 50), scalar_color, 2);
+ //cv::rectangle(yMat, cv::Point2f(500, 500), cv::Point2f(550, 550), scalar_color, 2);
+
+ cv::rectangle(yMat, cv::Point2f(static_cast<float>(p_face[i].rect.left),
+ static_cast<float>(p_face[i].rect.top)),
+ cv::Point2f(static_cast<float>(p_face[i].rect.right),
+ static_cast<float>(p_face[i].rect.bottom)), scalar_color, 2);
+
+ for (int j = 0; j < p_face[i].points_count; j++)
+ {
+ cv::circle(yMat, cv::Point2f(p_face[i].points_array[j].x,
+ p_face[i].points_array[j].y), 1, cv::Scalar(255, 255, 255));
+ }
+ }
+
+ //if (face_count > 0)
+ //{
+ // static size_t f=0;
+ // char fname[50];
+ // sprintf(fname, "face-%u.yuv420", ++f);
+ // FILE * pFile = fopen (fname,"wb");
+ // fwrite (yuvMat.data , sizeof(char), 1920*1080*1.5, pFile);
+ // printf("write face file %s\n", fname);
+ // fclose(pFile);
+ //}
+
+ // release the memory of face
+ cv_face_release_tracker_result(p_face, face_count);
+
+ return face_count;
}
bool PL_SensetimeFaceDetect::pay(const PipeMaterial& pm)
@@ -81,16 +193,21 @@
return false;
}
-
+ int face_count = doFaceDetect(in, frame->buffer, 1920, 1080, 1920, CV_PIX_FMT_YUV420P);
+ if (face_count < 0)
+ {
+ in->payError = true;
+ return false;
+ }
+ else
+ in->payError = false;
//in->buffer readly
- //static size_t f=0;
- //char fname[50];
- //sprintf(fname, "%u.bgra", ++f);
- //FILE * pFile = fopen (fname,"wb");
- //fwrite (in->buffer , sizeof(char), in->buffSize, pFile);
- //fclose(pFile);
+ in->lastFrame.type = MB_Frame::MBFT_YUV420;
+ in->lastFrame.buffer = frame->buffer;//#todo should copy
+ in->lastFrame.buffSize = frame->buffSize;
+ in->lastFrame.pts = frame->pts;
return true;
}
@@ -99,9 +216,13 @@
{
PL_SensetimeFaceDetect_Internal* in = (PL_SensetimeFaceDetect_Internal*)internal;
- pm.type = PipeMaterial::PMT_FRAME;
- pm.buffer = (uint8_t*)(&(in->lastFrame));
- pm.buffSize = sizeof(in->lastFrame);
+ if (!in->payError)
+ {
+ pm.type = PipeMaterial::PMT_FRAME;
+ pm.buffer = (uint8_t*)(&(in->lastFrame));
+ pm.buffSize = sizeof(in->lastFrame);
+ pm.former = this;
+ }
pm.former = this;
- return true;
+ return !in->payError;
}
diff --git a/RtspFace/PL_SensetimeFaceDetect.h b/RtspFace/PL_SensetimeFaceDetect.h
index f1cdbb1..0d876c0 100644
--- a/RtspFace/PL_SensetimeFaceDetect.h
+++ b/RtspFace/PL_SensetimeFaceDetect.h
@@ -3,6 +3,17 @@
#include "PipeLine.h"
+struct SensetimeFaceDetectConfig
+{
+ int point_size; // 21 / 106
+ int point_size_config; // CV_DETECT_ENABLE_ALIGN_21 / CV_DETECT_ENABLE_ALIGN_106
+ int detect_face_cnt_limit; // -1
+
+ SensetimeFaceDetectConfig() :
+ point_size(21), point_size_config(-1), detect_face_cnt_limit(-1)
+ { }
+};
+
class PL_SensetimeFaceDetect : public PipeLineElem
{
public:
diff --git a/RtspFace/main.cpp b/RtspFace/main.cpp
index b75f9ea..bf67254 100644
--- a/RtspFace/main.cpp
+++ b/RtspFace/main.cpp
@@ -7,6 +7,8 @@
#include "PL_AVFrameBGRA.h"
#include "PL_Queue.h"
+#include "PL_SensetimeFaceDetect.h"
+
#include <iostream>
using namespace std;
@@ -20,6 +22,8 @@
pipeLine.register_elem_creator("PL_AVFrameYUV420", create_PL_AVFrameYUV420);
pipeLine.register_elem_creator("PL_H264Encoder", create_PL_H264Encoder);
pipeLine.register_elem_creator("PL_Queue", create_PL_Queue);
+
+ pipeLine.register_elem_creator("PL_SensetimeFaceDetect", create_PL_SensetimeFaceDetect);
{
PL_RTSPClient* rtspClient = (PL_RTSPClient*)pipeLine.push_elem("PL_RTSPClient");
@@ -48,6 +52,12 @@
avFrameYUV420->init(nullptr);
}
+ {
+ SensetimeFaceDetectConfig config;
+ PL_SensetimeFaceDetect* stFaceDetect = (PL_SensetimeFaceDetect*)pipeLine.push_elem("PL_SensetimeFaceDetect");
+ stFaceDetect->init(&config);
+ }
+
//{//#todo queue should support deep copy
// PL_Queue_Config config;
// PL_Queue* queue1 = (PL_Queue*)pipeLine.push_elem("PL_Queue");
@@ -59,21 +69,21 @@
// }
//}
- //{
- // PL_H264Encoder* h264Encoder = (PL_H264Encoder*)pipeLine.push_elem("PL_H264Encoder");
- // h264Encoder->init(nullptr);
- //}
+ {
+ PL_H264Encoder* h264Encoder = (PL_H264Encoder*)pipeLine.push_elem("PL_H264Encoder");
+ h264Encoder->init(nullptr);
+ }
- //{
- // RTSPServerConfig config;
- // PL_RTSPServer* rtspServer = (PL_RTSPServer*)pipeLine.push_elem("PL_RTSPServer");
- // bool ret = rtspServer->init(&config);
- // if (!ret)
- // {
- // cout << "rtspServer.init error" << endl;
- // exit(EXIT_FAILURE);
- // }
- //}
+ {
+ RTSPServerConfig config;
+ PL_RTSPServer* rtspServer = (PL_RTSPServer*)pipeLine.push_elem("PL_RTSPServer");
+ bool ret = rtspServer->init(&config);
+ if (!ret)
+ {
+ cout << "rtspServer.init error" << endl;
+ exit(EXIT_FAILURE);
+ }
+ }
while(true)
{
diff --git a/RtspFace/make.sh b/RtspFace/make.sh
index 704fa7d..1fe8646 100644
--- a/RtspFace/make.sh
+++ b/RtspFace/make.sh
@@ -21,8 +21,16 @@
FFMPEGRTSPSERVER_BASE=./FFmpegRTSPServer
FFMPEGRTSPSERVER_OBJ="FFmpegH264Source.o LiveRTSPServer.o LiveServerMediaSubsession.o"
-CPPFLAGS+="-pthread $LIVEMEDIA_INC $FFMPEG_INC $LIBBASE64_INC $LIBYUV_INC"
-LDFLAGS+="-pthread $LIVEMEDIA_LIB $FFMPEG_LIB $LIBBASE64_LIB $LIBYUV_LIB $LIBX264_LIB"
+SENSETIMEFACESDK_BASE=/opt/SensetimeFaceSDK
+SENSETIMEFACESDK_INC="-I$SENSETIMEFACESDK_BASE/include"
+SENSETIMEFACESDK_LIB="-L$SENSETIMEFACESDK_BASE/libs/linux-x86_64 -lcvface_api"
+
+OPENCV_BASE=
+OPENCV_INC=
+OPENCV_LIB="-lopencv_core"
+
+CPPFLAGS+="-pthread $LIVEMEDIA_INC $FFMPEG_INC $LIBBASE64_INC $LIBYUV_INC $SENSETIMEFACESDK_INC"
+LDFLAGS+="-pthread $LIVEMEDIA_LIB $FFMPEG_LIB $LIBBASE64_LIB $LIBYUV_LIB $LIBX264_LIB $SENSETIMEFACESDK_LIB $OPENCV_LIB"
CFLAGS+="-D__STDC_CONSTANT_MACROS"
@@ -30,6 +38,8 @@
rm *.o
g++ -g -c -std=c++11 main.cpp $CFLAGS $CPPFLAGS
+g++ -g -c -std=c++11 PipeLine.cpp $CFLAGS $CPPFLAGS
+
g++ -g -c -std=c++11 PL_RTSPClient.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_RTSPServer.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_H264Decoder.cpp $CFLAGS $CPPFLAGS
@@ -37,7 +47,7 @@
g++ -g -c -std=c++11 PL_AVFrameYUV420.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_AVFrameBGRA.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 PL_Queue.cpp $CFLAGS $CPPFLAGS
-g++ -g -c -std=c++11 PipeLine.cpp $CFLAGS $CPPFLAGS
+g++ -g -c -std=c++11 PL_SensetimeFaceDetect.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 $FFMPEGRTSPSERVER_BASE/FFmpegH264Source.cpp $CFLAGS $CPPFLAGS
g++ -g -c -std=c++11 $FFMPEGRTSPSERVER_BASE/LiveRTSPServer.cpp $CFLAGS $CPPFLAGS
@@ -46,8 +56,9 @@
g++ -g -std=c++11 \
main.o PipeLine.o \
PL_RTSPClient.o PL_H264Decoder.o PL_H264Encoder.o PL_AVFrameYUV420.o PL_AVFrameBGRA.o PL_Queue.o \
+ PL_SensetimeFaceDetect.o \
$FFMPEGRTSPSERVER_OBJ PL_RTSPServer.o \
$LDFLAGS -o rtsp_face
-#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LIBX264_BASE/lib:$FFMPEG_BASE/lib
+#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LIBX264_BASE/lib:$FFMPEG_BASE/lib:$SENSETIMEFACESDK_BASE/libs/linux-x86_64
#./rtsp_face rtsp://admin:admin12345@192.168.1.64:554/h264/ch1/main/av_stream
--
Gitblit v1.8.0