oak_basic_infer.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <sstream>
  4. #include <opencv2/imgproc.hpp>
  5. #include <opencv2/imgcodecs.hpp>
  6. #include <opencv2/gapi.hpp>
  7. #include <opencv2/gapi/core.hpp>
  8. #include <opencv2/gapi/imgproc.hpp>
  9. #include <opencv2/gapi/infer.hpp>
  10. #include <opencv2/gapi/infer/parsers.hpp>
  11. #include <opencv2/gapi/render.hpp>
  12. #include <opencv2/gapi/cpu/gcpukernel.hpp>
  13. #include <opencv2/highgui.hpp>
  14. #include <opencv2/gapi/oak/oak.hpp>
  15. #include <opencv2/gapi/oak/infer.hpp>
  16. const std::string keys =
  17. "{ h help | | Print this help message }"
  18. "{ detector | | Path to compiled .blob face detector model }"
  19. "{ duration | 100 | Number of frames to pull from camera and run inference on }";
  20. namespace custom {
  21. G_API_NET(FaceDetector, <cv::GMat(cv::GFrame)>, "sample.custom.face-detector");
  22. using GDetections = cv::GArray<cv::Rect>;
  23. using GSize = cv::GOpaque<cv::Size>;
  24. using GPrims = cv::GArray<cv::gapi::wip::draw::Prim>;
  25. G_API_OP(BBoxes, <GPrims(GDetections)>, "sample.custom.b-boxes") {
  26. static cv::GArrayDesc outMeta(const cv::GArrayDesc &) {
  27. return cv::empty_array_desc();
  28. }
  29. };
  30. GAPI_OCV_KERNEL(OCVBBoxes, BBoxes) {
  31. // This kernel converts the rectangles into G-API's
  32. // rendering primitives
  33. static void run(const std::vector<cv::Rect> &in_face_rcs,
  34. std::vector<cv::gapi::wip::draw::Prim> &out_prims) {
  35. out_prims.clear();
  36. const auto cvt = [](const cv::Rect &rc, const cv::Scalar &clr) {
  37. return cv::gapi::wip::draw::Rect(rc, clr, 2);
  38. };
  39. for (auto &&rc : in_face_rcs) {
  40. out_prims.emplace_back(cvt(rc, CV_RGB(0,255,0))); // green
  41. }
  42. }
  43. };
  44. } // namespace custom
  45. int main(int argc, char *argv[]) {
  46. cv::CommandLineParser cmd(argc, argv, keys);
  47. if (cmd.has("help")) {
  48. cmd.printMessage();
  49. return 0;
  50. }
  51. const auto det_name = cmd.get<std::string>("detector");
  52. const auto duration = cmd.get<int>("duration");
  53. if (det_name.empty()) {
  54. std::cerr << "FATAL: path to detection model is not provided for the sample."
  55. << "Please specify it with --detector options."
  56. << std::endl;
  57. return 1;
  58. }
  59. // Prepare G-API kernels and networks packages:
  60. auto detector = cv::gapi::oak::Params<custom::FaceDetector>(det_name);
  61. auto networks = cv::gapi::networks(detector);
  62. auto kernels = cv::gapi::combine(
  63. cv::gapi::kernels<custom::OCVBBoxes>(),
  64. cv::gapi::oak::kernels());
  65. auto args = cv::compile_args(kernels, networks);
  66. // Initialize graph structure
  67. cv::GFrame in;
  68. cv::GFrame copy = cv::gapi::oak::copy(in); // NV12 transfered to host + passthrough copy for infer
  69. cv::GOpaque<cv::Size> sz = cv::gapi::streaming::size(copy);
  70. // infer is not affected by the actual copy here
  71. cv::GMat blob = cv::gapi::infer<custom::FaceDetector>(copy);
  72. // FIXME: OAK infer detects faces slightly out of frame bounds
  73. cv::GArray<cv::Rect> rcs = cv::gapi::parseSSD(blob, sz, 0.5f, true, false);
  74. auto rendered = cv::gapi::wip::draw::renderFrame(copy, custom::BBoxes::on(rcs));
  75. // on-the-fly conversion NV12->BGR
  76. cv::GMat out = cv::gapi::streaming::BGR(rendered);
  77. auto pipeline = cv::GComputation(cv::GIn(in), cv::GOut(out, rcs))
  78. .compileStreaming(std::move(args));
  79. // Graph execution
  80. pipeline.setSource(cv::gapi::wip::make_src<cv::gapi::oak::ColorCamera>());
  81. pipeline.start();
  82. cv::Mat out_mat;
  83. std::vector<cv::Rect> out_dets;
  84. int frames = 0;
  85. while (pipeline.pull(cv::gout(out_mat, out_dets))) {
  86. std::string name = "oak_infer_frame_" + std::to_string(frames) + ".png";
  87. cv::imwrite(name, out_mat);
  88. if (!out_dets.empty()) {
  89. std::cout << "Got " << out_dets.size() << " detections on frame #" << frames << std::endl;
  90. }
  91. ++frames;
  92. if (frames == duration) {
  93. pipeline.stop();
  94. break;
  95. }
  96. }
  97. std::cout << "Pipeline finished. Processed " << frames << " frames" << std::endl;
  98. return 0;
  99. }