667 lines
18 KiB
C++
667 lines
18 KiB
C++
#include "VideoProc.h"
|
|
#include "TypeDef.h"
|
|
#include "MatBase64.hpp"
|
|
#include "json.hpp"
|
|
#include "VideoSocketService.h"
|
|
#include "WebSocketService.h"
|
|
#include "TimeCount.h"
|
|
#include <shlobj.h>
|
|
VideoProc* VideoProc::getInstance()
|
|
{
|
|
static VideoProc _instance;
|
|
return &_instance;
|
|
}
|
|
|
|
|
|
|
|
VideoProc::VideoProc():m_bRun(false)
|
|
{
|
|
char UserPath[MAX_PATH + 1] = { 0 };
|
|
SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, UserPath);
|
|
m_tmp_path = std::string(UserPath) + std::string("\\AppData\\Local\\Temp\\");
|
|
std::thread(&VideoProc::onTimer, this).detach();
|
|
}
|
|
|
|
VideoProc::~VideoProc()
|
|
{
|
|
|
|
}
|
|
|
|
int VideoProc::openCam(int id)
|
|
{
|
|
if (m_bRun)
|
|
{//摄像头已经打开
|
|
return err_is_opened;
|
|
}
|
|
else
|
|
{
|
|
m_capture_rgb.release();
|
|
m_capture_rgb.set(cv::CAP_PROP_FOCUS, 0);
|
|
|
|
try {
|
|
//if (!m_capture_rgb.open(id, cv::CAP_DSHOW))
|
|
if(!m_capture_rgb.open(id, cv::CAP_ANY)) //!< Video For Windows (obsolete, removed)
|
|
{//打开摄像头失败
|
|
m_capture_rgb.release();
|
|
return err_open_cam;
|
|
}
|
|
std::thread(&VideoProc::videoFrameThread, this).detach();
|
|
}
|
|
catch (cv::Exception& e)
|
|
{
|
|
MessageBoxA(0, e.what(), "错误", MB_OK);
|
|
return err_open_cam;
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
|
|
return err_ok_open_cam;
|
|
}
|
|
|
|
}
|
|
|
|
int VideoProc::close()
|
|
{
|
|
if (m_bRun)
|
|
{
|
|
m_bRun = false;
|
|
}
|
|
m_take_photo_timer = 0;
|
|
m_compare_timer = 0;
|
|
return err_ok_close_cam;
|
|
}
|
|
|
|
int VideoProc::startCheckFace(std::string base64, int time_out)
|
|
{
|
|
cv::Mat idc_img = Base2Mat(base64);
|
|
nlohmann::json root;
|
|
root["action_code"] = action_start_check_face;
|
|
root["action"] = u8"face_image_compare";
|
|
if (idc_img.empty())
|
|
{
|
|
root["err_msg"] = u8"输入的人脸比对图片错误";
|
|
root["err_code"] = err_face_compare_input;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_input;
|
|
}
|
|
|
|
std::vector<FaceInfo> faceList;
|
|
FaceDetect(idc_img, faceList);
|
|
int face_num = faceList.size();
|
|
if (face_num > 0)
|
|
{
|
|
if (face_num == 1)
|
|
{
|
|
int ret = GetFaceFeature(idc_img, faceList[0].landmarks, m_idc_feature);
|
|
if (ret == 0)
|
|
{
|
|
m_compare_timer = time_out;
|
|
return err_ok;
|
|
}
|
|
else
|
|
{
|
|
root["err_msg"] = u8"输入的人脸图片提取特征失败";
|
|
root["err_code"] = err_face_compare_get_feature;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_get_feature;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
root["err_msg"] = u8"输入的人脸比对图片存在多张人脸";
|
|
root["err_code"] = err_face_compare_multiple_face;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_multiple_face;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
root["err_msg"] = u8"输入的人脸比对图片未检测到人脸";
|
|
root["err_code"] = err_face_compare_no_face;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_no_face;
|
|
}
|
|
|
|
}
|
|
|
|
void VideoProc::stopCheckFace()
|
|
{
|
|
m_compare_timer = 0;
|
|
}
|
|
|
|
void VideoProc::StartAutoTakePhoto(int timeOut)
|
|
{
|
|
if (!m_bRun)
|
|
{
|
|
nlohmann::json root;
|
|
root["action"] = u8"start_auto_take_photo";
|
|
root["action_code"] = action_start_auto_take_photo;
|
|
root["err_code"] = err_is_closed;
|
|
root["err_msg"] = u8"摄像头未开启";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
|
|
return;
|
|
}
|
|
m_take_photo_timer = timeOut;
|
|
}
|
|
|
|
|
|
void VideoProc::StopAutoTakePhoto()
|
|
{
|
|
m_take_photo_timer = 0;
|
|
}
|
|
|
|
|
|
void VideoProc::TakePhoto()
|
|
{
|
|
m_bTackPtoto = true;
|
|
}
|
|
|
|
void VideoProc::setFaceThreshold(float threshold)
|
|
{
|
|
|
|
}
|
|
|
|
void VideoProc::onTimer()
|
|
{
|
|
while (true)
|
|
{
|
|
if (m_compare_timer > 0)
|
|
{
|
|
m_compare_timer--;
|
|
//std::wstring msg = L"{\"event_id\":5,\"time_out\":" + std::to_wstring(m_compare_timer) + std::wstring(L",\"message\":\"人脸比对倒计时\"}");
|
|
nlohmann::json root;
|
|
root["action_code"] = action_time_auto_check_face;
|
|
root["action"] = u8"人脸核验倒计时";
|
|
root["time_out"] = (int)m_compare_timer;
|
|
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
else
|
|
{
|
|
//std::wstring msg = L"{\"event_id\":4,\"message\":\"停止人脸比对\"}";
|
|
if (m_compare_timer == 0)
|
|
{
|
|
m_compare_timer = -1;
|
|
nlohmann::json root;
|
|
root["action_code"] = action_stop_check_face;
|
|
root["action"] = u8"停止人脸核验";
|
|
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
if (m_take_photo_timer > 0)
|
|
{
|
|
nlohmann::json root;
|
|
root["action"] = u8"自动拍照倒计时";
|
|
root["action_code"] = action_time_auto_take_photo;
|
|
root["time_out"] = (int)m_take_photo_timer;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
m_take_photo_timer--;
|
|
}
|
|
else
|
|
{
|
|
if (m_take_photo_timer == 0)
|
|
{
|
|
m_take_photo_timer = -1;
|
|
nlohmann::json root;
|
|
root["action"] = u8"停止自动拍照";
|
|
root["action_code"] = action_stop_auto_take_photo;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
}
|
|
}
|
|
|
|
void VideoProc::videoFrameThread()
|
|
{
|
|
bool bLiveness = true;
|
|
|
|
if (!m_capture_rgb.isOpened())
|
|
{//RGB摄像头打开失败
|
|
nlohmann::json root;
|
|
root["err_code"] = err_open_cam;
|
|
root["err_msg"] = u8"打开RGB摄像头失败";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return;
|
|
}
|
|
|
|
cv::Scalar color(0, 0, 255);
|
|
m_bRun = true;
|
|
while (m_bRun)
|
|
{
|
|
cv::Mat frame_rgb;
|
|
m_capture_rgb >> frame_rgb;
|
|
if (frame_rgb.empty())
|
|
{
|
|
if (!m_capture_rgb.isOpened())
|
|
{
|
|
nlohmann::json root;
|
|
root["err_code"] = err_cam_closed;
|
|
root["err_msg"] = u8"摄像头异常停止工作";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
break;
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
}
|
|
cv::flip(frame_rgb, frame_rgb, 1);
|
|
|
|
//拍照
|
|
if (m_bTackPtoto)
|
|
{
|
|
std::string photo_path = m_tmp_path + std::string("photo.jpg");
|
|
cv::imwrite(photo_path, frame_rgb);
|
|
//m_tackPhotoData = Mat2Base64(frame_rgb, "jpg");
|
|
m_bTackPtoto = false;
|
|
nlohmann::json root;
|
|
root["action_code"] = action_take_photo;
|
|
root["action"] = u8"拍照";
|
|
root["err_code"] = err_ok_take_photo;
|
|
root["err_msg"] = u8"拍照成功";
|
|
root["photo"] = photo_path;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
|
|
if (m_take_photo_timer > 0 || m_compare_timer > 0 /*|| bLiveness*/)//需要进行活体检测
|
|
{
|
|
std::vector<FaceInfo> faceList;
|
|
FaceDetect(frame_rgb, faceList);
|
|
if (faceList.size() > 0)
|
|
{
|
|
float liveness_score = 0.f;
|
|
FaceInfo& _face_box = faceList[0];
|
|
FaceLivenesRgb(frame_rgb, _face_box.landmarks, liveness_score);
|
|
if (liveness_score < 0.5)
|
|
{//非活体
|
|
color = cv::Scalar(0, 0, 255);
|
|
cv::Rect _rt(cv::Point(_face_box.x1, _face_box.y1), cv::Point(_face_box.x2, _face_box.y2));
|
|
rectangleFace(frame_rgb, _rt, color);
|
|
//cv::putText(frame_rgb, std::string("non-liveness: ") + std::to_string(liveness_score), cv::Point(5, 50), 1, 2, color, 2);
|
|
|
|
static long st1 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
long st2 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
if (st2 - st1 > 1)
|
|
{
|
|
st1 = st2;
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_liveness_fail;
|
|
root["err_msg"] = u8"活体检测失败";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
color = cv::Scalar(0, 255, 0);
|
|
personCardCheck(frame_rgb);
|
|
//cv::putText(frame_rgb, std::string("liveness: ") + std::to_string(liveness_score), cv::Point(5, 50), 1, 2, color, 2);
|
|
//std::wstring msg = std::wstring(L"{\"code\":3,\"ret\":1,\"score\":") + std::to_wstring(liveness_score) + std::wstring(L",\"message\":\"活体检测成功\"}");
|
|
//PostMessageW(WM_MSG_JS, (WPARAM)msg.c_str(), msg.length());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_compare_timer > 0 || m_take_photo_timer > 0)
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_no_face;
|
|
root["err_msg"] = u8"未检测到人脸";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{//不做活体检测,检测人脸和身份证照片进行比对
|
|
personCardCheck(frame_rgb);
|
|
}
|
|
|
|
if (m_compare_timer > 0)
|
|
{
|
|
//绘制人脸比对倒计时
|
|
cv::putText(frame_rgb, std::to_string(m_compare_timer) + std::string("S"), cv::Point(frame_rgb.cols - 60, 30), 1, 2, cv::Scalar(0, 0, 255), 2);
|
|
|
|
}
|
|
else if (m_take_photo_timer > 0)
|
|
{
|
|
//绘制人脸比对倒计时
|
|
cv::putText(frame_rgb, std::to_string(m_take_photo_timer) + std::string("S"), cv::Point(frame_rgb.cols - 60, 30), 1, 2, cv::Scalar(0, 0, 255), 2);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
//cv::imshow("frame_rgb",frame_rgb);
|
|
VideoSocketService::getInstance()->PushImg(Mat2Base64(frame_rgb, "jpg"));
|
|
cv::waitKey(10);
|
|
}
|
|
m_compare_timer = 0;
|
|
m_capture_rgb.release();
|
|
//m_capture_ir.release();
|
|
m_cv.notify_one();
|
|
}
|
|
|
|
int VideoProc::personCardCheck(cv::Mat& rgb_img)
|
|
{
|
|
cv::Mat tmp_rgb_img = rgb_img.clone();
|
|
float qua = 0.f;
|
|
std::vector<FaceInfo> faceList;
|
|
FaceDetect(tmp_rgb_img, faceList);
|
|
|
|
if (faceList.size() > 0)
|
|
{
|
|
cv::Rect _rt(cv::Point(faceList[0].x1, faceList[0].y1), cv::Point(faceList[0].x2, faceList[0].y2));
|
|
|
|
GetFaceQuality(tmp_rgb_img, faceList[0].x1, faceList[0].y1, faceList[0].x2, faceList[0].y2, qua);
|
|
if (qua > 85)
|
|
{
|
|
if (m_take_photo_timer > 0)//自动拍照
|
|
{
|
|
if (qua > 90)
|
|
{
|
|
//std::string photoData = Mat2Base64(tmp_rgb_img, "jpg");
|
|
//std::string faceImg = getFaceImg(tmp_rgb_img, faceList[0]);
|
|
std::string photo_path = m_tmp_path + std::string("photo.jpg");
|
|
std::string face_img_path = m_tmp_path + std::string("faceImg.jpg");
|
|
cv::imwrite(photo_path, tmp_rgb_img);
|
|
cv::imwrite(face_img_path, getFaceMat(tmp_rgb_img, faceList[0]));
|
|
|
|
m_take_photo_timer = 0;
|
|
|
|
nlohmann::json root;
|
|
root["action_code"] = action_start_auto_take_photo;
|
|
root["action"] = u8"自动拍照";
|
|
root["err_code"] = err_ok_auto_take_photo;
|
|
root["err_msg"] = u8"自动拍照成功";
|
|
root["photo"] = photo_path;
|
|
root["face_img"] = face_img_path;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
else
|
|
{
|
|
static long st1 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
long st2 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
if (st2 - st1 > 1)
|
|
{
|
|
st1 = st2;
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_keep_face;
|
|
root["err_msg"] = u8"人脸质量太低,请正对着摄像头";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (m_compare_timer > 0)
|
|
{
|
|
float score = 0.f;
|
|
float feature[512] = { 0 };
|
|
int ret = GetFaceFeature(tmp_rgb_img, faceList[0].landmarks, feature);
|
|
if (ret == 0)
|
|
{
|
|
FaceFeatureCompare(feature, m_idc_feature, score);
|
|
if (score >= m_threshold)
|
|
{
|
|
m_compare_timer = 0;
|
|
|
|
std::string photo_path = m_tmp_path + std::string("photo.jpg");
|
|
std::string face_img_path = m_tmp_path + std::string("faceImg.jpg");
|
|
cv::imwrite(photo_path, tmp_rgb_img);
|
|
cv::imwrite(face_img_path, getFaceMat(tmp_rgb_img, faceList[0]));
|
|
|
|
nlohmann::json root;
|
|
root["action_code"] = action_start_check_face;
|
|
root["action"] = u8"人脸核验";
|
|
root["err_code"] = err_ok_face_compare;
|
|
root["err_msg"] = u8"人脸比对成功";
|
|
root["score"] = score;
|
|
root["photo"] = photo_path;
|
|
root["face_image"] = face_img_path;
|
|
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_ok_face_compare;
|
|
}
|
|
else
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_face_compare_fail;
|
|
root["err_msg"] = u8"人脸比对失败";
|
|
root["score"] = score;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_fail;
|
|
}
|
|
}
|
|
}
|
|
rectangleFace(rgb_img, _rt, cv::Scalar(0, 255, 0));
|
|
}
|
|
else
|
|
{
|
|
if (m_compare_timer > 0 || m_take_photo_timer > 0)
|
|
{
|
|
static long st1 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
long st2 = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now()).time_since_epoch().count();
|
|
if (st2 - st1 > 1)
|
|
{
|
|
st1 = st2;
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_keep_face;
|
|
root["err_msg"] = u8"人脸质量太低,请正对着摄像头";
|
|
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
rectangleFace(rgb_img, _rt, cv::Scalar(255, 0, 0));
|
|
}
|
|
//cv::putText(rgb_img, std::string("score: ") + std::to_string(score), cv::Point(5, 100), 1, 2, cv::Scalar(0, 0, 255), 2);
|
|
//cv::putText(rgb_img, std::string("qua: ") + std::to_string(qua), cv::Point(5, 130), 1, 2, cv::Scalar(0, 255, 0), 2);
|
|
}
|
|
else
|
|
{
|
|
if (m_compare_timer > 0 || m_take_photo_timer > 0)
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_event;
|
|
root["action"] = u8"事件通知";
|
|
root["err_code"] = err_no_face;
|
|
root["err_msg"] = u8"未检测到人脸";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int VideoProc::FaceCompare(std::string img1, std::string img2)
|
|
{
|
|
cv::Mat mat1 = Base2Mat(img1);
|
|
cv::Mat mat2 = Base2Mat(img2);
|
|
if (mat1.empty() || mat2.empty())
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_face_compare;
|
|
root["action"] = u8"face_image_compare";
|
|
root["err_code"] = err_face_compare_input;
|
|
root["err_msg"] = u8"输入的人脸图片错误";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_input;
|
|
}
|
|
|
|
std::vector<FaceInfo> faceList1, faceList2;
|
|
FaceDetect(mat1, faceList1);
|
|
FaceDetect(mat2, faceList2);
|
|
if (faceList1.size() > 1 || faceList2.size() > 1)
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_face_compare;
|
|
root["action"] = u8"face_image_compare";
|
|
root["err_code"] = err_face_compare_multiple_face;
|
|
root["err_msg"] = u8"输入的比对图片存在多张人脸";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_multiple_face;
|
|
}
|
|
|
|
if (faceList1.size() < 0 || faceList2.size() < 0)
|
|
{
|
|
nlohmann::json root;
|
|
root["action_code"] = action_face_compare;
|
|
root["action"] = u8"face_image_compare";
|
|
root["err_code"] = err_face_compare_no_face;
|
|
root["err_msg"] = u8"输入的比对图片未检测到人脸";
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_face_compare_no_face;
|
|
}
|
|
|
|
float f1[512] = { 0 };
|
|
float f2[512] = { 0 };
|
|
|
|
GetFaceFeature(mat1, faceList1[0].landmarks, f1);
|
|
GetFaceFeature(mat2, faceList2[0].landmarks, f2);
|
|
|
|
float score = 0.f;
|
|
FaceFeatureCompare(f1, f2, score);
|
|
|
|
nlohmann::json root;
|
|
root["action_code"] = action_face_compare;
|
|
root["action"] = u8"人脸图片比对";
|
|
root["err_code"] = err_ok_face_compare;
|
|
root["err_msg"] = u8"人脸图片比对完成";
|
|
root["score"] = score;
|
|
WebSocketService::getInstance()->SendMsg(root.dump());
|
|
return err_ok_face_compare;
|
|
}
|
|
|
|
std::string VideoProc::getFaceImg(cv::Mat& img, FaceInfo& face_info)
|
|
{
|
|
int ew = face_info.GetWidth() * 1.0 / 1.5;
|
|
int eh = face_info.GetHeight() * 1.0 / 2.8;
|
|
face_info.x1 -= ew;
|
|
face_info.y1 -= eh;
|
|
face_info.x2 += ew;
|
|
face_info.y2 += eh;
|
|
|
|
if (face_info.x1 < 0)
|
|
{
|
|
face_info.x1 = 0;
|
|
}
|
|
if (face_info.y1 < 0)
|
|
{
|
|
face_info.y1 = 0;
|
|
}
|
|
|
|
if (face_info.x2 >= img.cols)
|
|
{
|
|
face_info.x2 = img.cols - 5;
|
|
}
|
|
|
|
if (face_info.y2 >= img.rows)
|
|
{
|
|
face_info.y2 = img.rows - 5;
|
|
}
|
|
|
|
cv::Rect face_rect;
|
|
face_rect.x = face_info.x1;
|
|
face_rect.y = face_info.y1;
|
|
face_rect.width = face_info.GetWidth();
|
|
face_rect.height = face_info.GetHeight();
|
|
|
|
std::string base64;
|
|
try
|
|
{
|
|
cv::Mat faceImg = img(face_rect);
|
|
base64 = Mat2Base64(faceImg, "jpg");
|
|
}
|
|
catch (const cv::Exception& e)
|
|
{
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
return base64;
|
|
}
|
|
|
|
cv::Mat VideoProc::getFaceMat(cv::Mat& img, FaceInfo& face_info)
|
|
{
|
|
int ew = face_info.GetWidth() * 1.0 / 1.5;
|
|
int eh = face_info.GetHeight() * 1.0 / 2.8;
|
|
face_info.x1 -= ew;
|
|
face_info.y1 -= eh;
|
|
face_info.x2 += ew;
|
|
face_info.y2 += eh;
|
|
|
|
if (face_info.x1 < 0)
|
|
{
|
|
face_info.x1 = 0;
|
|
}
|
|
if (face_info.y1 < 0)
|
|
{
|
|
face_info.y1 = 0;
|
|
}
|
|
|
|
if (face_info.x2 >= img.cols)
|
|
{
|
|
face_info.x2 = img.cols - 5;
|
|
}
|
|
|
|
if (face_info.y2 >= img.rows)
|
|
{
|
|
face_info.y2 = img.rows - 5;
|
|
}
|
|
|
|
cv::Rect face_rect;
|
|
face_rect.x = face_info.x1;
|
|
face_rect.y = face_info.y1;
|
|
face_rect.width = face_info.GetWidth();
|
|
face_rect.height = face_info.GetHeight();
|
|
|
|
cv::Mat faceImg;
|
|
try
|
|
{
|
|
faceImg = img(face_rect);
|
|
}
|
|
catch (const cv::Exception& e)
|
|
{
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
return faceImg;
|
|
}
|
|
|
|
void VideoProc::rectangleFace(cv::Mat& img, cv::Rect face_rect, cv::Scalar color)
|
|
{
|
|
//cv::rectangle(img, face_rect, cv::Scalar(0,100,100));
|
|
int line_len = 15;
|
|
int thickness = 2;
|
|
cv::line(img, cv::Point(face_rect.x, face_rect.y), cv::Point(face_rect.x + line_len, face_rect.y), color, thickness);
|
|
cv::line(img, cv::Point(face_rect.x, face_rect.y), cv::Point(face_rect.x, face_rect.y + line_len), color, thickness);
|
|
|
|
cv::line(img, cv::Point(face_rect.x + face_rect.width - line_len, face_rect.y), cv::Point(face_rect.x + face_rect.width, face_rect.y), color, thickness);
|
|
cv::line(img, cv::Point(face_rect.x + face_rect.width, face_rect.y), cv::Point(face_rect.x + face_rect.width, face_rect.y + line_len), color, thickness);
|
|
|
|
cv::line(img, cv::Point(face_rect.x, face_rect.y + face_rect.height - line_len), cv::Point(face_rect.x, face_rect.y + face_rect.height), color, thickness);
|
|
cv::line(img, cv::Point(face_rect.x, face_rect.y + face_rect.height), cv::Point(face_rect.x + line_len, face_rect.y + face_rect.height), color, thickness);
|
|
|
|
cv::line(img, cv::Point(face_rect.x + face_rect.width, face_rect.y + face_rect.height - line_len), cv::Point(face_rect.x + face_rect.width, face_rect.y + face_rect.height), color, thickness);
|
|
cv::line(img, cv::Point(face_rect.x + face_rect.width - line_len, face_rect.y + face_rect.height), cv::Point(face_rect.x + face_rect.width, face_rect.y + face_rect.height), color, thickness);
|
|
} |