Export.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include "Export.h"
  2. // 将图像转成所需的灰度图,且进行缩放
  3. bool ConvertImage(const char* srcImgData, int imgwidth, int imgheight, ColorType colorType,
  4. int newW, int newH, const char* dstImgData)
  5. {
  6. try
  7. {
  8. // 检查通道数
  9. if (colorType != Gray8 && colorType != Rgb && colorType != Bgr && colorType != Bgra && colorType != Rgba)
  10. {
  11. //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected colorType." });
  12. return false;
  13. }
  14. // 检查图像尺寸
  15. if (imgwidth <= 0 || imgheight <= 0)
  16. {
  17. //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected image size." });
  18. return false;
  19. }
  20. // 检查指针
  21. if (srcImgData == nullptr)
  22. {
  23. //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected image data pointer." });
  24. return false;
  25. }
  26. cv::Size imgSize = cv::Size(imgwidth, imgheight);
  27. cv::Mat img;
  28. cv::Mat imgGray = cv::Mat(imgSize, CV_8UC1);
  29. switch (colorType)
  30. {
  31. case Gray8:
  32. img = cv::Mat(imgSize, CV_8UC(1), (void*)srcImgData);
  33. imgGray = img.clone();
  34. break;
  35. case Rgb:
  36. img = cv::Mat(imgSize, CV_8UC(3), (void*)srcImgData);
  37. cvtColor(img, imgGray, cv::COLOR_RGB2GRAY);
  38. break;
  39. case Bgr:
  40. img = cv::Mat(imgSize, CV_8UC(3), (void*)srcImgData);
  41. cvtColor(img, imgGray, cv::COLOR_BGR2GRAY);
  42. break;
  43. case Rgba:
  44. img = cv::Mat(imgSize, CV_8UC(4), (void*)srcImgData);
  45. cvtColor(img, imgGray, cv::COLOR_RGBA2GRAY);
  46. break;
  47. case Bgra:
  48. img = cv::Mat(imgSize, CV_8UC(4), (void*)srcImgData);
  49. cvtColor(img, imgGray, cv::COLOR_BGRA2GRAY);
  50. break;
  51. }
  52. img.release();
  53. cv::Size newSize = cv::Size(newW, newH);//cvSize(120, 120);
  54. cv::Mat imgResized;
  55. cv::resize(imgGray, imgResized, newSize);
  56. imgGray.release();
  57. ;
  58. // 去除椒盐噪声
  59. cv::medianBlur(imgResized, imgResized, 5);
  60. memcpy((void*)dstImgData, imgResized.data, sizeof(char) * newW * newH);
  61. imgResized.release();
  62. return true;
  63. }
  64. catch (const std::exception& ex)
  65. {
  66. //ErrorMsg::SetErrorMsg(ConvertError, { ex.what() });
  67. return false;
  68. }
  69. }
  70. // 对图像进行canny运算,计算得到的边缘所占的比值
  71. bool ProcessOneImage(const char* imgData, int imgwidth, int imgheight, ColorType colorType, double& cannyRatio)
  72. {
  73. try
  74. {
  75. // 检查通道数
  76. if (colorType != Gray8 && colorType != Rgb && colorType != Bgr && colorType != Bgra && colorType != Rgba)
  77. {
  78. //ErrorMsg::SetErrorMsg(CannyError, { "unexpected colorType." });
  79. return false;
  80. }
  81. // 检查图像尺寸
  82. if (imgwidth <= 0 || imgheight <= 0)
  83. {
  84. //ErrorMsg::SetErrorMsg(CannyError, { "unexpected image size." });
  85. return false;
  86. }
  87. // 检查指针
  88. if (imgData == nullptr)
  89. {
  90. //ErrorMsg::SetErrorMsg(CannyError, { "unexpected image data pointer." });
  91. return false;
  92. }
  93. int channel = 1;
  94. switch (colorType)
  95. {
  96. case Gray8:
  97. channel = 1;
  98. break;
  99. case Rgb:
  100. case Bgr:
  101. channel = 3;
  102. break;
  103. case Rgba:
  104. case Bgra:
  105. channel = 4;
  106. break;
  107. }
  108. // 复制图像
  109. cv::Size imgSize = cv::Size(imgwidth, imgheight);
  110. cv::Mat img = cv::Mat(imgSize, CV_8UC(channel));
  111. memcpy(img.data, imgData, imgwidth * imgheight * channel);
  112. // 计算canny系数
  113. cannyProcess(img, cannyRatio);
  114. return true;
  115. }
  116. catch (const std::exception& ex)
  117. {
  118. //ErrorMsg::SetErrorMsg(CannyError, { ex.what() });
  119. return false;
  120. }
  121. }
  122. // 根据累积的一些信息,判断当前图像的状态
  123. CurrentVideoState JudgeImage(double* diffData, double* corrData, double* cannyData,
  124. int num, int movingDelayNum, int stationaryDelayNum, int movingDelayTriggerNum, int stationaryDelayTriggerNum, bool manuallyUnfreeze, ExtendState& state)
  125. {
  126. try
  127. {
  128. double diffVar = 0;
  129. double cannyVar = 0;
  130. CurrentVideoState tmp = Notjudged;
  131. std::vector<double> vDiffData;
  132. std::vector<double> vCannyData;
  133. for (int i = 0; i < num; i++)
  134. {
  135. vDiffData.push_back(diffData[i]);
  136. vCannyData.push_back(cannyData[i]);
  137. }
  138. if (vDiffData.size() > 1)
  139. {
  140. varVector(vDiffData, diffVar);
  141. cannyVector(vCannyData, cannyVar);
  142. if ((diffVar > 100 && cannyVar > 0.8) || cannyVar > 2.5)
  143. {
  144. tmp = Moving;
  145. }
  146. else if (diffVar < 20 || cannyVar < 0.5)
  147. {
  148. tmp = Stationary;
  149. }
  150. else
  151. {
  152. tmp = Notjudged;
  153. }
  154. }
  155. else
  156. {
  157. tmp = Stationary;
  158. }
  159. if (tmp != Notjudged)
  160. {
  161. if (tmp == Stationary)
  162. {
  163. // 如果之前是强制延长Stationary状态,现在已经是真实的判为是静置了,可以把状态量恢复了
  164. if (state.StationaryExtendedState)
  165. {
  166. state.StationaryExtendedNum = 0;
  167. state.StationaryExtendedState = false;
  168. }
  169. if (state.TrueMovingNum > movingDelayTriggerNum || manuallyUnfreeze)
  170. {
  171. state.MovingExtendedState = true;
  172. }
  173. if (state.MovingExtendedState)
  174. {
  175. if (state.MovingExtendedNum < movingDelayNum)
  176. {
  177. state.MovingExtendedNum++;
  178. return Moving;
  179. }
  180. // 延迟帧数已经超标,清空状态
  181. state.TrueMovingNum = 0;
  182. state.MovingExtendedNum = 0;
  183. state.MovingExtendedState = false;
  184. }
  185. // 如果之前不是静置,则TrueStationary的计数清零
  186. if (state.LastState)
  187. {
  188. state.TrueStationaryNum = 0;
  189. }
  190. state.TrueStationaryNum++;
  191. state.LastState = false;
  192. return Stationary;
  193. }
  194. else if (tmp == Moving)
  195. {
  196. // 如果之前是强制延长Moving状态,现在已经是真实的判为是扫查中了,可以把状态量恢复了
  197. if (state.MovingExtendedState)
  198. {
  199. state.MovingExtendedNum = 0;
  200. state.MovingExtendedState = false;
  201. }
  202. if (state.TrueStationaryNum > stationaryDelayTriggerNum)
  203. {
  204. state.StationaryExtendedState = true;
  205. }
  206. if (state.StationaryExtendedState)
  207. {
  208. if (state.StationaryExtendedNum < stationaryDelayNum)
  209. {
  210. state.StationaryExtendedNum++;
  211. return Stationary;
  212. }
  213. // 超过限定个数,清空
  214. state.TrueStationaryNum = 0;
  215. state.StationaryExtendedNum = 0;
  216. state.StationaryExtendedState = false;
  217. }
  218. // 如果之前不是运行,则TrueMoving的计数清零
  219. if (!state.LastState)
  220. {
  221. state.TrueMovingNum = 0;
  222. }
  223. state.TrueMovingNum++;
  224. state.LastState = true;
  225. return Moving;
  226. }
  227. }
  228. else
  229. {
  230. if (state.LastState)
  231. {
  232. return Moving;
  233. }
  234. else
  235. {
  236. return Stationary;
  237. }
  238. }
  239. }
  240. catch (const std::exception& ex)
  241. {
  242. //ErrorMsg::SetErrorMsg(JudgeError, { ex.what() });
  243. return HaveError;
  244. }
  245. }
  246. // 对两幅图像进行互相关计算
  247. double CompareTwoImage(const char* pSrc1, const char* pSrc2, int width, int height, int widthstep, double& corr, double& diff)
  248. {
  249. try
  250. {
  251. double ratio = 0;
  252. // 求两幅图的互相关系数
  253. calcorrcoef((uint8_t*)(pSrc1), (uint8_t*)(pSrc2), width, height, widthstep, corr);
  254. // corr大于该值,则认为两幅图可能一致,不计算diff(默认为0)
  255. // corr小于该值,可计算两幅图的差异
  256. if (corr < 0.999)
  257. {
  258. ratio = calDiff((uint8_t*)(pSrc1), (uint8_t*)(pSrc2), width, height, diff);
  259. }
  260. return ratio;
  261. }
  262. catch (const std::exception& ex)
  263. {
  264. //ErrorMsg::SetErrorMsg(ImageDiffError, { ex.what() });
  265. return 2;
  266. }
  267. }
  268. // 图像数据解码
  269. bool ImgDataDecode(const uint8_t* srcImgData, const int srcDataSize, ImreadModes imReadMode, ImageInfo* imageInfo)
  270. {
  271. std::vector<uchar> dataDecode;
  272. dataDecode.resize(srcDataSize);
  273. for (int ni = 0; ni < srcDataSize; ni++)
  274. {
  275. dataDecode[ni] = srcImgData[ni];
  276. }
  277. cv::Mat imgDecode = cv::imdecode(dataDecode, imReadMode);
  278. imageInfo->width = imgDecode.cols;
  279. imageInfo->height = imgDecode.rows;
  280. auto type = imgDecode.type();
  281. switch (type)
  282. {
  283. case CV_8UC1:
  284. imageInfo->colorType = Gray8;
  285. break;
  286. case CV_8UC3:
  287. imageInfo->colorType = Bgr;
  288. break;
  289. case CV_8UC4:
  290. imageInfo->colorType = Bgra;
  291. break;
  292. default:
  293. return false;
  294. }
  295. return true;
  296. }
  297. // 获得解码后的图像尺寸
  298. int GetDecodedImgSize(const uint8_t* srcImgData, const int srcDataSize, ImreadModes imReadMode)
  299. {
  300. std::vector<uchar> dataDecode;
  301. dataDecode.resize(srcDataSize);
  302. for (int ni = 0; ni < srcDataSize; ni++)
  303. {
  304. dataDecode[ni] = srcImgData[ni];
  305. }
  306. cv::Mat imgDecode = cv::imdecode(dataDecode, imReadMode);
  307. auto total = imgDecode.total();
  308. auto elemSize = imgDecode.elemSize();
  309. return total * elemSize;
  310. }