CameraDemo.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include <fstream>
  2. #include <opencv2/opencv.hpp>
  3. // libcommon
  4. #include "Logger.h"
  5. #include "OSTime.h"
  6. #include "SysUtils.h"
  7. #include "Semaphore.h"
  8. // libmascommon
  9. #include "MemPool.h"
  10. // deps
  11. #include "DetUtils.h"
  12. #include "ilogger.hpp"
  13. #include "trt_infer.hpp"
  14. // libyolocrowddetector
  15. #include "DetectorAPI.h"
  16. #include "YoloCrowdDetector.h"
  17. // libheadcountstrategy
  18. #include "StrategyAPI.h"
  19. #include "HeadCountStrategy.h"
  20. #define RUN_TEXT_DRAWING 0
  21. struct CallbackContext
  22. {
  23. masd::Strategy* strategy;
  24. cv::Mat* img;
  25. cv::VideoWriter* videoWriter;
  26. };
  27. tzc::Semaphore SEMA;
  28. void SaveDetectorInfo(const char* info)
  29. {
  30. std::ofstream outFile("detector_info.json", std::ios::out | std::ios::app);
  31. if (outFile.is_open())
  32. {
  33. outFile << "{\n\t\"Detector Information\": \"" << info << "\"\n}" << std::endl;
  34. outFile.close();
  35. TZLogInfo("Detector information saved to detector_info.json~~~");
  36. }
  37. else
  38. {
  39. TZLogError("Failed to open file for writing!!!");
  40. }
  41. }
  42. TZ_INT DetectionCallback(SPtr<masd::StreamInfo>& media, void* ctx)
  43. {
  44. TZLogInfo("Detection callback triggered!~~~");
  45. // Retrieve the context
  46. CallbackContext* callbackContext = reinterpret_cast<CallbackContext*>(ctx);
  47. if (!callbackContext || !callbackContext->img || callbackContext->strategy == nullptr)
  48. {
  49. TZLogError("Error: Invalid context or image pointer!!!");
  50. return -1;
  51. }
  52. cv::Mat* img = callbackContext->img;
  53. masd::Strategy* strategy = callbackContext->strategy;
  54. if (img->empty())
  55. {
  56. TZLogError("Error: Invalid image pointer!!!");
  57. return -1;
  58. }
  59. auto allDetRst = media->GetAllDetRst();
  60. int imgWidth = img->cols, imgHeight = img->rows;
  61. for (auto it = allDetRst.begin(); it != allDetRst.end(); ++it)
  62. {
  63. const std::string& detKey = it->first;
  64. const SPtr<masd::DetProducing>& detProducing = it->second;
  65. TZLogInfo("Detection Key: %s~~~", detKey.c_str());
  66. std::cout << "Detection Result: " << detProducing->Result << std::endl;
  67. if (!detProducing->Draw.Rects.empty())
  68. {
  69. TZLogInfo("Processing Draw Info...~~~");
  70. for (const auto& rect : detProducing->Draw.Rects)
  71. {
  72. TZLogInfo("Rect: LTX: %.2f, LTY: %.2f, "
  73. "RBX: %.2f, RBY: %.2f, Color: %s, Thickness: %d~~~",
  74. rect.LTX, rect.LTY, rect.RBX, rect.RBY,
  75. rect.Color.c_str(), rect.Thickness);
  76. if (!rect.Text.Text.empty())
  77. {
  78. TZLogInfo("Text: %s~~~", rect.Text.Text.c_str());
  79. }
  80. cv::Scalar color;
  81. {
  82. std::stringstream colorStream(rect.Color);
  83. int r, g, b;
  84. char comma;
  85. colorStream >> r >> comma >> g >> comma >> b;
  86. color = cv::Scalar(b, g, r);
  87. }
  88. cv::Point topLeft(rect.LTX * imgWidth, rect.LTY * imgHeight);
  89. cv::Point bottomRight(rect.RBX * imgWidth, rect.RBY * imgHeight);
  90. cv::rectangle(*img, topLeft, bottomRight, color, rect.Thickness);
  91. #if RUN_TEXT_DRAWING
  92. if (!rect.Text.Text.empty())
  93. {
  94. cv::putText(*img, rect.Text.Text,
  95. cv::Point(topLeft.x, topLeft.y - 10),
  96. cv::FONT_HERSHEY_SIMPLEX, 0.8, color, 2);
  97. }
  98. #endif
  99. }
  100. }
  101. else
  102. {
  103. TZLogInfo("No Draw Info available.~~~");
  104. }
  105. if (detProducing->DetMedia)
  106. {
  107. const auto& media = detProducing->DetMedia;
  108. TZLogInfo("Media Length: %d~~~", media->Length);
  109. TZLogInfo("Media DataType: %d~~~", media->DataType);
  110. TZLogInfo("Media Height: %d, Width: %d~~~", media->Height, media->Width);
  111. }
  112. }
  113. // Process the strategy inside the callback
  114. TZ_INT strategyResult = strategy->DoStrategy(media);
  115. if (strategyResult != masd::MEC_OK)
  116. {
  117. TZLogError("Headcount strategy failed to process the stream info!!!");
  118. return -1;
  119. }
  120. TZLogInfo("Headcount strategy processed the stream info successfully~~~");
  121. SPtr<masd::StraProducing> straProducing = media->GetStraProducing();
  122. if (straProducing)
  123. {
  124. std::string headcountResult = straProducing->Result.RstName;
  125. TZLogInfo("Detected headcount: %s", headcountResult.c_str());
  126. int fontFace = cv::FONT_HERSHEY_SIMPLEX;
  127. double fontScale = 0.8;
  128. int thickness = 2;
  129. cv::Scalar textColor(0, 255, 0);
  130. cv::Point textPosition(10, 30);
  131. cv::putText(*img, headcountResult, textPosition, fontFace, fontScale, textColor, thickness);
  132. }
  133. else
  134. {
  135. TZLogWarn("No headcount result found in the stream info.");
  136. }
  137. cv::imshow("Detection Result", *img);
  138. cv::waitKey(1);
  139. callbackContext->videoWriter->write(*img);
  140. SEMA.Signal();
  141. return 0;
  142. }
  143. int main()
  144. {
  145. // Initialize log
  146. INITIALIZE_LOGGER_NORMAL("test", "./test.log", 1, 100, 6, 1, 1);
  147. // Initialize memory pool
  148. masd::MemPool *pool = masd::MEMPOOL;
  149. if (pool->Initialize() != masd::MEC_OK)
  150. {
  151. TZLogError("Memory pool initialization failed!!!");
  152. return -1;
  153. }
  154. /* Calling libyolocrowddetector and libheadcountstrategy */
  155. // Step 1:
  156. // Initialize the SDK
  157. TZ_INT initResult = Initialize();
  158. if (initResult != masd::MEC_OK)
  159. {
  160. TZLogError("Failed to initialize the SDK!!!");
  161. return -1;
  162. }
  163. TZLogInfo("SDK Initialized Successfully~~~");
  164. // Step 2:
  165. // Build yolo-crowd detector
  166. masd::Detector* detector = BuildDetector();
  167. if (detector == nullptr)
  168. {
  169. TZLogError("Failed to build yolo-crowd detector!!!");
  170. Dispose();
  171. return -1;
  172. }
  173. TZLogInfo("Yolo-crowd detector built successfully~~~");
  174. // Build headcount strategy
  175. masd::Strategy* strategy = BuildStrategy();
  176. if(strategy == nullptr)
  177. {
  178. TZLogError("Failed to build headcount strategy!!!");
  179. Dispose();
  180. return -1;
  181. }
  182. TZLogInfo("Headcount strategy built successfully~~~");
  183. // Step 3:
  184. // Initialize the yolo-crowd detector with configuration parameters
  185. std::string initParam =
  186. "{\"gpu_id\": 0, \"max_objects\": 1024, "
  187. "\"confidence_threshold\": 0.2, \"nms_threshold\": 0.5, "
  188. "\"model_path\": \"../../models/yolo-crowd.trt\"}";
  189. TZ_INT initDetResult = detector->Initialize(initParam);
  190. if (initDetResult != masd::MEC_OK)
  191. {
  192. TZLogError("Failed to initialize the yolo-crowd detector!!!");
  193. DestroyDetector(detector);
  194. DestroyStrategy(strategy);
  195. Dispose();
  196. return -1;
  197. }
  198. TZLogInfo("Yolo-crowd detector initialized successfully~~~");
  199. // Initialize the headcount strategy
  200. TZ_INT initStraResult = strategy->Initialize();
  201. if (initStraResult != masd::MEC_OK)
  202. {
  203. TZLogError("Failed to initialize the headcount detector!!!");
  204. DestroyDetector(detector);
  205. DestroyStrategy(strategy);
  206. Dispose();
  207. return -1;
  208. }
  209. TZLogInfo("Headcount strategy initialized successfully~~~");
  210. // Step 4:
  211. // Set yolo-crowd detection configuration (optional)
  212. std::string detectConfig = R"({
  213. "freq": 0,
  214. "target": {
  215. "target_class": [0],
  216. "target_threshold": [0.25]
  217. },
  218. "focusArea": [
  219. { "LTX": 0.0, "LTY": 0.0, "RBX": 1.0, "RBY": 1.0 }
  220. ],
  221. "ignoreArea": [
  222. { "LTX": 0.0, "LTY": 0.0, "RBX": 0.0, "RBY": 0.0 }
  223. ]
  224. })";
  225. TZ_INT setDetCfgResult = detector->SetDetectCfg(detectConfig);
  226. if (setDetCfgResult != masd::MEC_OK)
  227. {
  228. TZLogError("Failed to set yolo-crowd detection configuration!!!");
  229. DestroyDetector(detector);
  230. DestroyStrategy(strategy);
  231. Dispose();
  232. return -1;
  233. }
  234. TZLogInfo("Yolo-crowd detection configuration set successfully~~~");
  235. // Set headcount strategy configuration (optional)
  236. std::string headcountConfig = R"({
  237. "TimeThreshold": 5
  238. })";
  239. TZ_INT setStraCfgResult = strategy->SetStrategyCfg(headcountConfig);
  240. if (setStraCfgResult != masd::MEC_OK)
  241. {
  242. TZLogError("Failed to set headcount strategy configuration!!!");
  243. DestroyDetector(detector);
  244. DestroyStrategy(strategy);
  245. Dispose();
  246. return -1;
  247. }
  248. TZLogInfo("Headcount strategy configuration set successfully~~~");
  249. // Step 5:
  250. // Access the camera (default camera is index 0)
  251. cv::VideoCapture videoCapture(0); // Use the default webcam (0)
  252. if (!videoCapture.isOpened())
  253. {
  254. TZLogError("Failed to access camera!!!");
  255. DestroyDetector(detector);
  256. DestroyStrategy(strategy);
  257. Dispose();
  258. return -1;
  259. }
  260. TZ_INT videoWidth = static_cast<TZ_INT>(videoCapture.get(cv::CAP_PROP_FRAME_WIDTH));
  261. TZ_INT videoHeight = static_cast<TZ_INT>(videoCapture.get(cv::CAP_PROP_FRAME_HEIGHT));
  262. TZ_INT videoFPS = static_cast<TZ_INT>(videoCapture.get(cv::CAP_PROP_FPS));
  263. cv::VideoWriter videoWriter("output_video.mp4",
  264. cv::VideoWriter::fourcc('X', '2', '6', '4'),
  265. videoFPS, cv::Size(videoWidth, videoHeight));
  266. if (!videoWriter.isOpened())
  267. {
  268. TZLogError("Failed to open video writer!!!");
  269. DestroyDetector(detector);
  270. DestroyStrategy(strategy);
  271. Dispose();
  272. return -1;
  273. }
  274. cv::Mat frame;
  275. while(videoCapture.read(frame))
  276. {
  277. if(frame.empty())
  278. {
  279. TZLogError("Failed to read frame from video!!!");
  280. break;
  281. }
  282. TZ_INT length = frame.total() * frame.elemSize();
  283. SPtr<masd::Media> mediaResource = std::make_shared<masd::Media>(length);
  284. mediaResource->Width = frame.cols;
  285. mediaResource->Height = frame.rows;
  286. mediaResource->DataType = frame.type();
  287. mediaResource->Mem = frame.data;
  288. SPtr<masd::StreamInfo> streamInfo = std::make_shared<masd::StreamInfo>();
  289. streamInfo->SetMediaRsc(mediaResource);
  290. CallbackContext callbackContext{strategy, &frame, &videoWriter};
  291. detector->DoDetect(streamInfo, DetectionCallback, &callbackContext);
  292. SEMA.Wait();
  293. }
  294. // Step 6:
  295. // Print DetGetInformation
  296. char detectorInfo[4096];
  297. TZ_INT infoResult = GetInformation(detectorInfo);
  298. if (infoResult != masd::MEC_OK)
  299. {
  300. TZLogError("Failed to get detector information!!!");
  301. Dispose();
  302. return -1;
  303. }
  304. SaveDetectorInfo(detectorInfo);
  305. // Step 7:
  306. // Destroy the detector
  307. DestroyDetector(detector);
  308. TZLogInfo("Detector destroyed successfully~~~");
  309. // Destroy the strategy
  310. DestroyStrategy(strategy);
  311. TZLogInfo("Detector strategy successfully~~~");
  312. // Step 8:
  313. // Dispose the SDK
  314. TZ_INT disposeResult = Dispose();
  315. if (disposeResult != masd::MEC_OK)
  316. {
  317. TZLogError("Failed to dispose the SDK!!!");
  318. return -1;
  319. }
  320. TZLogInfo("SDK disposed successfully~~~");
  321. return 0;
  322. }