21 #include <opencv2/core/core.hpp>
22 #include <opencv2/dnn.hpp>
23 #include <opencv2/imgproc.hpp>
32 (TinyYOLOv3) (TinyYOLOv2) );
36 "classnames, configname, modelname, etc for the selected network. When "
37 "the selected model is Custom, those other parameters will be set instead "
38 "from the module's params.cfg config file.",
39 Model::Custom, Model_Values, ParamCateg);
42 JEVOIS_DECLARE_PARAMETER(classnames, std::string,
"Path to a text file with names of classes to label detected objects",
43 JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.classes", ParamCateg);
47 "Can have extension .prototxt (Caffe), .pbtxt (TensorFlow), or .cfg (Darknet).",
48 JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.prototxt", ParamCateg);
52 "Can have extension .caffemodel (Caffe), .pb (TensorFlow), .t7 or .net (Torch), "
53 "or .weights (Darknet).",
54 JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.caffemodel", ParamCateg);
57 JEVOIS_DECLARE_PARAMETER(netin, cv::Size,
"Width and height (in pixels) of the neural network input layer, or [0 0] "
58 "to make it match camera frame size. NOTE: for YOLO v3 sizes must be multiples of 32.",
59 cv::Size(160, 120), ParamCateg);
75 2.0
F / 255.0
F, ParamCateg);
79 cv::Scalar(127.5
F, 127.5
F, 127.5
F), ParamCateg);
87 "next time you load a different model.",
88 Target::OpenCL, Target_Values, ParamCateg);
172 public jevois::Parameter<model, classnames, configname, modelname, netin,
173 thresh, nms, rgb, scale, mean
217 classnames::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.classes");
218 modelname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.caffemodel");
219 configname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/opencv_face_detector.prototxt");
221 mean::set(cv::Scalar(104.0
F, 177.0
F, 123.0
F));
225 case Model::MobileNetSSDvoc:
226 classnames::set(JEVOIS_SHARE_PATH
"/darknet/yolo/data/voc.names");
227 modelname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/MobileNetSSD_deploy.caffemodel");
228 configname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/MobileNetSSD_deploy.prototxt");
231 case Model::MobileNetSSDcoco:
232 classnames::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/coco_tf.names");
233 modelname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/ssd_mobilenet_v1_coco_2017_11_17.pb");
234 configname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/ssd_mobilenet_v1_coco_2017_11_17.pbtxt");
238 case Model::MobileNet2SSDcoco:
239 classnames::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/coco_tf.names");
240 modelname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/ssd_mobilenet_v2_coco_2018_03_29.pb");
241 configname::set(JEVOIS_SHARE_PATH
"/opencv-dnn/detection/ssd_mobilenet_v2_coco_2018_03_29.pbtxt");
244 case Model::TinyYOLOv3:
245 classnames::set(JEVOIS_SHARE_PATH
"/darknet/yolo/data/coco.names");
246 modelname::set(JEVOIS_SHARE_PATH
"/darknet/yolo/weights/yolov3-tiny.weights");
247 configname::set(JEVOIS_SHARE_PATH
"/darknet/yolo/cfg/yolov3-tiny.cfg");
250 case Model::TinyYOLOv2:
251 classnames::set(JEVOIS_SHARE_PATH
"/darknet/yolo/data/voc.names");
252 modelname::set(JEVOIS_SHARE_PATH
"/darknet/yolo/weights/yolov2-tiny-voc.weights");
253 configname::set(JEVOIS_SHARE_PATH
"/darknet/yolo/cfg/yolov2-tiny-voc.cfg");
254 netin::set(cv::Size(320, 240));
258 if (val != Model::Custom)
279 std::ifstream ifs(classnames::get());
280 if (ifs.is_open() ==
false)
LFATAL(
"Class names file " << classnames::get() <<
" not found");
282 while (std::getline(ifs, line))
itsClasses.push_back(line);
285 itsNet = cv::dnn::readNet(modelname::get(), configname::get());
286 itsNet.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
288 switch(target::get())
290 case Target::CPU:
itsNet.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
break;
291 case Target::OpenCL:
itsNet.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL);
break;
292 case Target::OpenCL_FP16:
itsNet.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL_FP16);
break;
295 itsNet.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);
299 std::vector<cv::String> layersNames =
itsNet.getLayerNames();
310 float const confThreshold = thresh::get() * 0.01F;
311 float const nmsThreshold = nms::get() * 0.01F;
313 std::vector<int> classIds;
314 std::vector<float> confidences;
315 std::vector<cv::Rect> boxes;
316 if (
itsNet.getLayer(0)->outputNameToIndex(
"im_info") != -1)
320 if (outs.size() != 1)
LFATAL(
"Malformed output layers");
321 float* data = (
float*)outs[0].data;
322 for (
size_t i = 0; i < outs[0].total(); i += 7)
324 float confidence = data[i + 2];
325 if (confidence > confThreshold)
327 int left = (
int)data[i + 3];
328 int top = (
int)data[i + 4];
329 int right = (
int)data[i + 5];
330 int bottom = (
int)data[i + 6];
331 int width = right - left + 1;
332 int height = bottom - top + 1;
333 classIds.push_back((
int)(data[i + 1]) - 1);
334 boxes.push_back(cv::Rect(left, top, width, height));
335 confidences.push_back(confidence);
343 if (outs.size() != 1)
LFATAL(
"Malformed output layers");
344 float* data = (
float*)outs[0].data;
345 for (
size_t i = 0; i < outs[0].total(); i += 7)
347 float confidence = data[i + 2];
348 if (confidence > confThreshold)
350 int left = (
int)(data[i + 3] *
frame.cols);
351 int top = (
int)(data[i + 4] *
frame.rows);
352 int right = (
int)(data[i + 5] *
frame.cols);
353 int bottom = (
int)(data[i + 6] *
frame.rows);
354 int width = right - left + 1;
355 int height = bottom - top + 1;
356 classIds.push_back((
int)(data[i + 1]) - 1);
357 boxes.push_back(cv::Rect(left, top, width, height));
358 confidences.push_back(confidence);
364 for (
size_t i = 0; i < outs.size(); ++i)
368 float* data = (
float*)outs[i].data;
369 for (
int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
371 cv::Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
372 cv::Point classIdPoint;
374 minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
375 if (confidence > confThreshold)
377 int centerX = (
int)(data[0] *
frame.cols);
378 int centerY = (
int)(data[1] *
frame.rows);
379 int width = (
int)(data[2] *
frame.cols);
380 int height = (
int)(data[3] *
frame.rows);
381 int left = centerX - width / 2;
382 int top = centerY - height / 2;
384 classIds.push_back(classIdPoint.x);
385 confidences.push_back((
float)confidence);
386 boxes.push_back(cv::Rect(left, top, width, height));
394 std::vector<int> indices;
395 cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
398 for (
size_t i = 0; i < indices.size(); ++i)
400 int idx = indices[i];
401 cv::Rect
const & box = boxes[idx];
402 std::vector<jevois::ObjReco> data;
403 float const conf = confidences[idx] * 100.0F;
438 cv::dnn::blobFromImage(cvimg,
blob, scale::get(), netin::get(), mean::get(), rgb::get(),
false);
462 inimg.
require(
"input",
w,
h, V4L2_PIX_FMT_YUYV);
467 outimg = outframe.get();
481 cv::dnn::blobFromImage(cvimg,
blob, scale::get(), netin::get(), mean::get(), rgb::get(),
false);
497 std::vector<double> layersTimes;
498 double freq = cv::getTickFrequency() / 1000;
499 double t =
itsNet.getPerfProfile(layersTimes) / freq;
504 std::string
const & fpscpu = timer.
stop();