ImageTailor.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. #include "ImageTailor.h"
  2. #include <libyuv.h>
  3. #include "OptimizeCal.h"
  4. #include "FusionAndTailor.cuh"
  5. std::mutex g_CurFrameMutex;
  6. std::mutex g_PanoMutex;
  7. ImageTailor::ImageTailor()
  8. {
  9. pPanoImageBuffer = NULL;
  10. pTailorThread = NULL;
  11. this->bTailorThreadOut = true;
  12. StartTailorThread();
  13. bTailorThreadWork = false;
  14. }
  15. ImageTailor::~ImageTailor()
  16. {
  17. this->bTailorThreadOut = false;
  18. if (pTailorThread->joinable())
  19. pTailorThread->join();
  20. if (pTailorThread!=NULL)
  21. {
  22. delete pTailorThread;
  23. pTailorThread = NULL;
  24. }
  25. if (pPanoImageBuffer != NULL)
  26. {
  27. delete[] pPanoImageBuffer;
  28. cudaFree(pPanoImageBufferInGpu);
  29. pPanoImageBuffer = NULL;
  30. }
  31. }
  32. void ImageTailor::Init(unsigned char* pImage, int nPanoWidth, int nPanoHeight, cv::Point cvLeftTop)
  33. {
  34. //get the pointer
  35. pPanoImageBuffer = pImage;
  36. //get the width
  37. this->nPanoWidth = nPanoWidth;
  38. //get the height
  39. this->nPanoHeight = nPanoHeight;
  40. //get the lefttop point
  41. this->LeftTop = cvLeftTop;
  42. //get the panoimage pitch
  43. this->nPanoPitch = (nPanoWidth*3 + 3) / 4 * 4;
  44. }
  45. void ImageTailor::Init_Gpu(unsigned char* pImage, unsigned char* pImageGpu, int nPanoWidth, int nPanoHeight, cv::Point cvLeftTop)
  46. {
  47. //get the pointer
  48. pPanoImageBuffer = pImage;
  49. //get the width
  50. this->nPanoWidth = nPanoWidth;
  51. //get the height
  52. this->nPanoHeight = nPanoHeight;
  53. //get the lefttop point
  54. this->LeftTop = cvLeftTop;
  55. //get the panoimage pitch
  56. this->nPanoPitch = (nPanoWidth * 3 + 3) / 4 * 4;
  57. pPanoImageBufferInGpu = pImageGpu;
  58. }
  59. int ImageTailor::StitchingOnPano(cv::Point LeftTop, cv::Mat* FrameImage,std::vector<std::vector<int>>* pvvOverlap)
  60. {
  61. //in the paon image ,the lefttop point is (0,0),stitching the image on the pano image
  62. //get the lefttop point
  63. cv::Point cvLeftTop = LeftTop;
  64. //get the width
  65. int nFrameWidth = FrameImage->cols;
  66. //get the height
  67. int nFrameHeight = FrameImage->rows;
  68. //get the pitch
  69. int nFramePitch = FrameImage->step[0];
  70. //set a pointer to pano image stitching target
  71. unsigned char* pPanoImageTarget = pPanoImageBuffer + cvLeftTop.y * nPanoPitch + cvLeftTop.x * 3;
  72. cv::Mat PanoImage = cv::Mat(nPanoHeight, nPanoWidth, CV_8UC3, pPanoImageBuffer);
  73. //stitching the image
  74. for (int i = 0; i < nFrameHeight; i++)
  75. {
  76. //get this line overlap
  77. std::vector<int>& vOverlap = (*pvvOverlap)[i];
  78. //copy the image
  79. FastCopy_Any(FrameImage->ptr<uchar>(i) + vOverlap[0] * 3
  80. , pPanoImageTarget + nPanoPitch * i + vOverlap[0] * 3
  81. , (vOverlap[1]- vOverlap[0]) * 3);
  82. }
  83. return 0;
  84. }
  85. int ImageTailor::StitchingOnPanoYUV(cv::Point LeftTop, unsigned char* pImage, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
  86. {
  87. //get Y,U,V pointer in pano image
  88. unsigned char* pPanoImageY = pPanoImageBuffer;
  89. unsigned char* pPanoImageU = pPanoImageBuffer + nPanoPitch * nPanoHeight;
  90. unsigned char* pPanoImageV = pPanoImageBuffer + nPanoPitch * nPanoHeight * 5 / 4;
  91. cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
  92. //get Y,U,V pointer in frame image
  93. unsigned char* pFrameImageY = pImage;
  94. unsigned char* pFrameImageU = pImage + nPitch * nHeight;
  95. unsigned char* pFrameImageV = pImage + nPitch * nHeight * 5 / 4;
  96. //Disassembly the pvvOverlap in rect to calculate the planepaste
  97. std::vector<cv::Rect> vPastePart;
  98. int nPanoImageHeight = int(pvvOverlap->size());
  99. cv::Rect rectPastePart;
  100. bool bChangeFlags = true;
  101. for (int i = 0; i < nPanoImageHeight; i++)
  102. {
  103. std::vector<int>& vOverlap = (*pvvOverlap)[i];
  104. if (rectPastePart.x != vOverlap[0]
  105. && rectPastePart.y != vOverlap[1])
  106. bChangeFlags = true;
  107. if (bChangeFlags)
  108. {
  109. if (i != 0)
  110. vPastePart.push_back(rectPastePart);
  111. rectPastePart.x = vOverlap[0];
  112. rectPastePart.width = vOverlap[1] - vOverlap[0];
  113. rectPastePart.y = i;
  114. rectPastePart.height = 0;
  115. bChangeFlags = false;
  116. }
  117. rectPastePart.height++;
  118. }
  119. vPastePart.push_back(rectPastePart);
  120. int nPartNum = (int)vPastePart.size();
  121. for (int i = 0; i < nPartNum; i++)
  122. {
  123. cv::Rect& CurPart = vPastePart[i];
  124. //panoImage pointer
  125. unsigned char* pPanoImageTargetY = pPanoImageY + (CurPart.y + LeftTop.y) * nPanoPitch + (CurPart.x + LeftTop.x);
  126. unsigned char* pPanoImageTargetU = pPanoImageU + (CurPart.y + LeftTop.y) * nPanoPitch / 4 + (CurPart.x + LeftTop.x) / 2;
  127. unsigned char* pPanoImageTargetV = pPanoImageV + (CurPart.y + LeftTop.y) * nPanoPitch / 4 + (CurPart.x + LeftTop.x) / 2;
  128. //frameImage pointer
  129. unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * nPitch + CurPart.x;
  130. unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * nPitch / 4 + CurPart.x / 2;
  131. unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * nPitch / 4 + CurPart.x / 2;
  132. //copy the Y plane
  133. libyuv::CopyPlane(
  134. pPanoImageTargetY, nPanoPitch,
  135. pFrameImageTargetY, nPitch,
  136. CurPart.width, CurPart.height
  137. );
  138. //copy the U plane
  139. libyuv::CopyPlane(
  140. pPanoImageTargetU, nPanoPitch / 2,
  141. pFrameImageTargetU, nPitch / 2,
  142. CurPart.width / 2, CurPart.height / 2
  143. );
  144. //copy the V plane
  145. libyuv::CopyPlane(
  146. pPanoImageTargetV, nPanoPitch / 2,
  147. pFrameImageTargetV, nPitch / 2,
  148. CurPart.width / 2, CurPart.height / 2
  149. );
  150. }
  151. return 0;
  152. }
  153. int ImageTailor::StitchingOnPanoYUV(cv::Point LeftTop, cv::Mat* FrameImage, std::vector<std::vector<int>>* pvvOverlap)
  154. {
  155. //get Y,U,V pointer in pano image
  156. unsigned char* pPanoImageY = pPanoImageBuffer;
  157. unsigned char* pPanoImageU = pPanoImageBuffer + ALIGN_4(nPanoWidth) * nPanoHeight;
  158. unsigned char* pPanoImageV = pPanoImageBuffer + ALIGN_4(nPanoWidth) * nPanoHeight * 5 / 4;
  159. cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
  160. //get Y,U,V pointer in frame image
  161. unsigned char* &pFrameImageY = FrameImage->data;
  162. unsigned char* pFrameImageU = pFrameImageY + FrameImage->step * FrameImage->rows;
  163. unsigned char* pFrameImageV = pFrameImageY + FrameImage->step * FrameImage->rows * 5 / 4;
  164. //Disassembly the pvvOverlap in rect to calculate the planepaste
  165. std::vector<cv::Rect> vPastePart;
  166. int nPanoImageHeight = int(pvvOverlap->size());
  167. cv::Rect rectPastePart;
  168. bool bChangeFlags = true;
  169. for (int i = 0; i < nPanoImageHeight; i++)
  170. {
  171. std::vector<int>& vOverlap = (*pvvOverlap)[i];
  172. if (rectPastePart.x != vOverlap[0]
  173. && rectPastePart.y != vOverlap[1])
  174. bChangeFlags = true;
  175. if (bChangeFlags)
  176. {
  177. if (i != 0)
  178. vPastePart.push_back(rectPastePart);
  179. rectPastePart.x = vOverlap[0];
  180. rectPastePart.width = vOverlap[1] - vOverlap[0];
  181. rectPastePart.y = i;
  182. rectPastePart.height = 0;
  183. bChangeFlags = false;
  184. }
  185. rectPastePart.height++;
  186. }
  187. vPastePart.push_back(rectPastePart);
  188. int nPartNum = (int)vPastePart.size();
  189. for (int i = 0; i < nPartNum; i++)
  190. {
  191. cv::Rect& CurPart = vPastePart[i];
  192. //panoImage pointer
  193. unsigned char* pPanoImageTargetY = pPanoImageY + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) + (CurPart.x + LeftTop.x);
  194. unsigned char* pPanoImageTargetU = pPanoImageU + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x + LeftTop.x) / 2;
  195. unsigned char* pPanoImageTargetV = pPanoImageV + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x + LeftTop.x) / 2;
  196. //frameImage pointer
  197. unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * FrameImage->step + CurPart.x;
  198. unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * FrameImage->step / 4 + CurPart.x / 2;
  199. unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * FrameImage->step / 4 + CurPart.x / 2;
  200. //copy the Y plane
  201. libyuv::CopyPlane(
  202. pFrameImageTargetY, FrameImage->step,
  203. pPanoImageTargetY, ALIGN_4(nPanoWidth),
  204. CurPart.width, CurPart.height
  205. );
  206. //copy the U plane
  207. libyuv::CopyPlane(
  208. pFrameImageTargetU, FrameImage->step / 2,
  209. pPanoImageTargetU, ALIGN_4(nPanoWidth) / 2,
  210. CurPart.width / 2, CurPart.height / 2
  211. );
  212. //copy the V plane
  213. libyuv::CopyPlane(
  214. pFrameImageTargetV, FrameImage->step / 2,
  215. pPanoImageTargetV, ALIGN_4(nPanoWidth) / 2,
  216. CurPart.width / 2, CurPart.height / 2
  217. );
  218. }
  219. return 0;
  220. }
  221. void ImageTailor::TailorWordInThread(ImageTailor* pClass)
  222. {
  223. while (pClass->bTailorThreadOut)
  224. {
  225. g_CurFrameMutex.lock();
  226. g_PanoMutex.lock();
  227. if (pClass->qWorkQueue.size()<=0 || pClass->qWorkQueue.size() >10000)
  228. {
  229. g_CurFrameMutex.unlock();
  230. g_PanoMutex.unlock();
  231. continue;
  232. //pClass->ClearWorkOrder();
  233. }
  234. pClass->bTailorThreadWork = true;
  235. //WAIT_TAILOR& WorkOrder = pClass->qWorkQueue.front();
  236. if (!pClass->bUseYUV)
  237. pClass->StitchingOnPano(pClass->qWorkQueue.front().ptPosition, pClass->qWorkQueue.front().pROI, pClass->qWorkQueue.front().pvvOverlap);
  238. else
  239. pClass->StitchingOnPanoYUVByGPU(
  240. pClass->qWorkQueue.front().ptPosition,
  241. pClass->qWorkQueue.front().pImage,
  242. pClass->qWorkQueue.front().nWidth,
  243. pClass->qWorkQueue.front().nHeight,
  244. ALIGN_4(pClass->qWorkQueue.front().nPitch),
  245. pClass->qWorkQueue.front().pvvOverlap
  246. );
  247. g_CurFrameMutex.unlock();
  248. g_PanoMutex.unlock();
  249. pClass->qWorkQueue.pop();
  250. if (pClass->qWorkQueue.size() > 25)
  251. pClass->qWorkQueue.pop();
  252. if( pClass->qWorkQueue.size() > 50)
  253. pClass->qWorkQueue.pop();
  254. pClass->bTailorThreadWork = false;
  255. }
  256. }
  257. /// <summary>
  258. /// Stitchings the on pano.
  259. /// </summary>
  260. /// <param name="LeftTop">The left top.</param>
  261. /// <param name="FrameImage">The frame image.</param>
  262. /// <param name="nWidth">Width of the n.</param>
  263. /// <param name="nHeight">Height of the n.</param>
  264. /// <param name="nPitch">The n pitch.</param>
  265. /// <param name="pvvOverlap">The PVV overlap.</param>
  266. /// <returns></returns>
  267. int ImageTailor::StitchingOnPanoYUVByGPU(cv::Point LeftTop, unsigned char* FrameImage, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
  268. {
  269. //get Y,U,V pointer in pano image
  270. unsigned char* pPanoImageY = pPanoImageBufferInGpu + LeftTop.y * ALIGN_4(nPanoWidth) + LeftTop.x;
  271. unsigned char* pPanoImageU = pPanoImageBufferInGpu + ALIGN_4(nPanoWidth) * nPanoHeight + LeftTop.y/2 * (ALIGN_4(nPanoWidth)/2) + LeftTop.x/2;
  272. unsigned char* pPanoImageV = pPanoImageBufferInGpu + ALIGN_4(nPanoWidth) * nPanoHeight * 5 / 4 + LeftTop.y / 2 * (ALIGN_4(nPanoWidth) / 2) + LeftTop.x / 2;
  273. //cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
  274. unsigned char*& pFrameImageY = FrameImage;
  275. unsigned char* pFrameImageU = pFrameImageY + nPitch * nHeight;
  276. unsigned char* pFrameImageV = pFrameImageY + nPitch * nHeight * 5 / 4;
  277. //Disassembly the pvvOverlap in rect to calculate the planepaste
  278. std::vector<cv::Rect> vPastePart;
  279. int nPanoImageHeight = int(pvvOverlap->size());
  280. cv::Rect rectPastePart;
  281. bool bChangeFlags = true;
  282. for (int i = 0; i < nPanoImageHeight; i++)
  283. {
  284. std::vector<int>& vOverlap = (*pvvOverlap)[i];
  285. if (rectPastePart.x != vOverlap[0]
  286. && rectPastePart.y != vOverlap[1])
  287. bChangeFlags = true;
  288. if (bChangeFlags)
  289. {
  290. if (i != 0)
  291. vPastePart.push_back(rectPastePart);
  292. rectPastePart.x = vOverlap[0];
  293. rectPastePart.width = vOverlap[1] - vOverlap[0];
  294. rectPastePart.y = i;
  295. rectPastePart.height = 0;
  296. bChangeFlags = false;
  297. }
  298. rectPastePart.height++;
  299. }
  300. vPastePart.push_back(rectPastePart);
  301. int nBlockCount =int(vPastePart.size());
  302. for (int i = 0; i < nBlockCount; i++)
  303. {
  304. cv::Rect CurPart = vPastePart[i];
  305. int nPasteWidth = CurPart.width;
  306. int nPasteHeight = CurPart.height;
  307. int nPasteLeft = CurPart.x;
  308. int nPasteTop = CurPart.y;
  309. unsigned char* pPanoImageTargetY = pPanoImageY;//; +(CurPart.y) * ALIGN_4(nPanoWidth) + (CurPart.x);
  310. unsigned char* pPanoImageTargetU = pPanoImageU;// +(CurPart.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x) / 2;
  311. unsigned char* pPanoImageTargetV = pPanoImageV;// +(CurPart.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x) / 2;
  312. //frameImage pointer
  313. unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * nPitch + CurPart.x;
  314. unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * nPitch / 4 + CurPart.x / 2;
  315. unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * nPitch / 4 + CurPart.x / 2;
  316. YUVTailorAndBlender::CopyPlane(
  317. pFrameImageTargetY, nWidth, nHeight, nPitch,
  318. pPanoImageTargetY, nPanoWidth, nPanoHeight, ALIGN_4(nPanoWidth),
  319. nPasteWidth, nPasteHeight, nPasteLeft, nPasteTop,
  320. 1, NULL
  321. );
  322. YUVTailorAndBlender::CopyPlane(
  323. pFrameImageTargetU, nWidth / 2, nHeight / 2, nPitch / 2,
  324. pPanoImageTargetU, nPanoWidth / 2, nPanoHeight / 2, ALIGN_4(nPanoWidth) / 2,
  325. nPasteWidth / 2, nPasteHeight / 2, nPasteLeft / 2, nPasteTop / 2,
  326. 1, NULL
  327. );
  328. YUVTailorAndBlender::CopyPlane(
  329. pFrameImageTargetV, nWidth / 2, nHeight / 2, nPitch / 2,
  330. pPanoImageTargetV, nPanoWidth / 2, nPanoHeight / 2, ALIGN_4(nPanoWidth) / 2,
  331. nPasteWidth / 2, nPasteHeight / 2, nPasteLeft / 2, nPasteTop / 2,
  332. 1, NULL
  333. );
  334. cudaError Error = cudaDeviceSynchronize();
  335. if (Error == 700)
  336. int x = 10;
  337. }
  338. return 0;
  339. }
  340. int ImageTailor::Stitching(int nPostion, cv::Mat& ROI, std::vector<std::vector<int>>* pvvOverlap)
  341. {
  342. return 0;
  343. }
  344. void ImageTailor::SetOverlap(std::vector<std::vector<int>>* pvvOverlap)
  345. {
  346. vvOverlap = *pvvOverlap;
  347. }
  348. bool ImageTailor::StartTailorThread()
  349. {
  350. pTailorThread = new std::thread(TailorWordInThread, this);
  351. return false;
  352. }
  353. bool ImageTailor::EndTailorThread()
  354. {
  355. if (pTailorThread->joinable())
  356. {
  357. this->bTailorThreadOut = false;
  358. pTailorThread->join();
  359. return true;
  360. }
  361. else
  362. {
  363. return false;
  364. }
  365. }
  366. void ImageTailor::AddWorkOrderInqueue(cv::Point LeftTop, cv::Mat* FrameImage, std::vector<std::vector<int>>* pvvOverlap)
  367. {
  368. WAIT_TAILOR WorkOrder;
  369. WorkOrder.ptPosition = LeftTop;
  370. WorkOrder.pROI = FrameImage;
  371. WorkOrder.pvvOverlap = pvvOverlap;
  372. qWorkQueue.push(WorkOrder);
  373. }
  374. void ImageTailor::ClearWorkOrder()
  375. {
  376. std::queue<WAIT_TAILOR>().swap(qWorkQueue);
  377. /*while (!qWorkQueue.empty())
  378. {
  379. qWorkQueue.pop();
  380. }*/
  381. }
  382. void ImageTailor::AddWorkOrderInQueueGpu(cv::Point LeftTop, unsigned char* pData, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
  383. {
  384. WAIT_TAILOR WorkOrder;
  385. WorkOrder.ptPosition = LeftTop;
  386. WorkOrder.pImage = pData;
  387. WorkOrder.nWidth = nWidth;
  388. WorkOrder.nHeight = nHeight;
  389. WorkOrder.nPitch = nPitch;
  390. WorkOrder.pvvOverlap = pvvOverlap;
  391. qWorkQueue.push(WorkOrder);
  392. }