人脸检测基于opencv-CascadeClassifier, 特征提取使用的是自己insightface的mxnet转化为ncnn的模型。
,cpp 文件:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <time.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "net.h"
using namespace std;
//print tensor
void pretty_print(const ncnn::Mat& m)
{
int count = 0;
for (int q=0; q<m.c; q++)
{
const float* ptr = m.channel(q);
for (int y=0; y<m.h; y++)
{
for (int x=0; x<m.w; x++)
{
printf("%f ", ptr[x]);
count++;
}
ptr += m.w;
printf("\n");
}
printf("------------------------\n");
printf("%d\n",count);
}
}
//main
int main(int argc, char** argv){
// 定义输入格式
if (argc != 2) {
fprintf(stderr, "input error\n");
return -2;
}
//string path = argv[1];
//定义级联分类器
cv::CascadeClassifier face_detector;
//加在分类器
face_detector.load("haarcascade_frontalface_alt2.xml");
//判断分类器是否加载成功
if (face_detector.empty())
{
std::cerr << "load detector failed!!!" << std::endl;
return -1;
}
cv::Size original_size = face_detector.getOriginalWindowSize();
// 导入模型
ncnn::Net net;
printf("net init\n");
//net.opt.num_threads=1;
net.load_param("model-symbol.param");
printf("load model param\n");
net.load_model("model-symbol.bin");
printf("load model bin\n");
clock_t start, finish;
string img_path = argv[1];
cv::Mat img = cv::imread(img_path, cv::IMREAD_COLOR);
cv::Mat image_gray;
cv::cvtColor(img, image_gray, cv::COLOR_BGR2GRAY);
//用于保存检测到的目标窗口
std::vector<cv::Rect> dets;
//进行多尺度人脸检测
face_detector.detectMultiScale(image_gray, dets, 1.1, 3, 0 | cv::CASCADE_SCALE_IMAGE, original_size);
// 获取所有人脸
/**
for (size_t i = 0; i < faces.size(); i++)
{
cv::rectangle(image, faces[i], cv::Scalar(0, 0, 255), 2, 8, 0);
}
**/
// 获取最大人脸
cv::Rect R;
int Max = 0;
int area = 0;
for (size_t t = 0; t < dets.size(); ++t)
{
if (area < dets[t].width * dets[t].height)
{
area = dets[t].width * dets[t].height;
Max = t;
}
}
R.x = dets[Max].x;
R.y = dets[Max].y;
R.width = dets[Max].width;
R.height = dets[Max].height;
// max_face 最大人脸
cv::Mat max_face = img(R);
// 显示出来最大人脸
// cv::imshow("detect result", max_face);
// cv::waitKey(0);
// resize图片为模型指定的输入
cv::Mat img2;
int input_width = 112;//转onnx时指定的输入大小
int input_height = 112;
// resize
printf("---1111---\n");
cv::resize(max_face, img2, cv::Size(input_width, input_height));
printf("---cv ok---\n");
// load model
// 把opencv的mat转换成ncnn的mat
ncnn::Mat input = ncnn::Mat::from_pixels(img2.data, ncnn::Mat::PIXEL_BGR, img2.cols, img2.rows);
printf("convert ncnn\n");
// ncnn froward
// 模型前向传播
printf("net forward\n");
for(int i=0; i<1000; i++){
start = clock();
ncnn::Extractor extractor = net.create_extractor();
extractor.input("data", input);
ncnn::Mat output0;//取决于模型的输出有几个
extractor.extract("fc1", output0);
finish = clock();
double duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "%.4f seconds\n", duration );
//pretty_print(output0);
}
printf("get output0\n");
// 打印 tensor
// pretty_print(output1);
cout<<"done"<<endl;
return 0;
}
CMakeLists.txt 配置(将dlib相关的删除,没有依赖dlib)
macro(ncnn_add_example name)
add_executable(${name} ${name}.cpp)
# add_library(${name} SHARED ${name}.cpp)
target_include_directories(${name} PRIVATE ${OpenCV_INCLUDE_DIRS} ${dlib_INCLUDE_DIRS} )
target_link_libraries(${name} PRIVATE ncnn ${OpenCV_LIBS} ${dlib_LIBRARIES})
# target_include_directories(${name} PRIVATE ${dlib_INCLUDE_DIRS})
# target_link_libraries(${name} PRIVATE ncnn ${dlib_LIBRARIES} )
# add test to a virtual project group
# set_target_properties(dlib PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_property(TARGET ${name} PROPERTY FOLDER "examples")
endmacro()
# find_package(dlib REQUIRED)
# include_directories(${dlib_INCLUDE_DIRS})
# add_executable(${PROJECT_NAME} ${SRC_LIST})
# target_link_libraries(${PROJECT_NAME} ${dlib_LIBRARIES})
# add_subdirectory(/home/zb/zhangr/opencv-2.4.9 ${PROJECT_NAME}/opencv_build)
add_subdirectory(/home/zb/zhangr/dlib dlib_build)
#add_executable(dlib1 dlib1.cpp)
# Finally, you need to tell CMake that this program, assignment_learning_ex,
# depends on dlib. You do that with this statement:
#target_link_libraries(dlib1 dlib::dlib)
#set_property(TARGET dlib1 PROPERTY FOLDER "examples")
#add_executable(dlib2 dlib2.cpp)
#target_link_libraries(dlib2 dlib::dlib)
#set_property(TARGET dlib2 PROPERTY FOLDER "examples")
find_package(OpenCV QUIET COMPONENTS opencv_world objdetect)
find_package(dlib REQUIRED)
#add_executable(main2 main2.cpp)
#target_include_directories(main2 PRIVATE ${OpenCV_INCLUDE_DIRS})
#target_link_libraries(main2 ncnn ${OpenCV_LIBS} dlib::dlib)
#set_property(TARGET main2 PROPERTY FOLDER "examples")
# for opencv 2.4 on ubuntu 16.04, there is no opencv_world but OpenCV_FOUND will be TRUE
if("${OpenCV_LIBS}" STREQUAL "")
set(OpenCV_FOUND FALSE)
endif()
if(NOT OpenCV_FOUND)
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs videoio)
endif()
if(NOT OpenCV_FOUND)
find_package(OpenCV QUIET COMPONENTS core highgui imgproc)
endif()
if(OpenCV_FOUND)
message(STATUS "OpenCV library: ${OpenCV_INSTALL_PATH}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
if(${OpenCV_VERSION_MAJOR} GREATER 3)
set(CMAKE_CXX_STANDARD 11)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)
ncnn_add_example(squeezenet)
ncnn_add_example(squeezenet_c_api)
ncnn_add_example(fasterrcnn)
ncnn_add_example(rfcn)
ncnn_add_example(yolov2)
ncnn_add_example(yolov3)
ncnn_add_example(yolov4)
ncnn_add_example(mobilenetv2ssdlite)
ncnn_add_example(mobilenetssd)
ncnn_add_example(squeezenetssd)
ncnn_add_example(shufflenetv2)
ncnn_add_example(peleenetssd_seg)
ncnn_add_example(simplepose)
ncnn_add_example(retinaface)
ncnn_add_example(yolact)
ncnn_add_example(main)
ncnn_add_example(main1)
ncnn_add_example(main2)
ncnn_add_example(main3)
ncnn_add_example(Harr)
ncnn_add_example(only_opencv)
else()
message(WARNING "OpenCV not found, examples won't be built")
endif()