123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- #include "ImageTailor.h"
- #include <libyuv.h>
- #include "OptimizeCal.h"
- #include "FusionAndTailor.cuh"
- std::mutex g_CurFrameMutex;
- std::mutex g_PanoMutex;
- ImageTailor::ImageTailor()
- {
- pPanoImageBuffer = NULL;
- pTailorThread = NULL;
- this->bTailorThreadOut = true;
- StartTailorThread();
- bTailorThreadWork = false;
- }
- ImageTailor::~ImageTailor()
- {
- this->bTailorThreadOut = false;
- if (pTailorThread->joinable())
- pTailorThread->join();
- if (pTailorThread!=NULL)
- {
- delete pTailorThread;
- pTailorThread = NULL;
- }
- if (pPanoImageBuffer != NULL)
- {
- delete[] pPanoImageBuffer;
- cudaFree(pPanoImageBufferInGpu);
- pPanoImageBuffer = NULL;
- }
- }
- void ImageTailor::Init(unsigned char* pImage, int nPanoWidth, int nPanoHeight, cv::Point cvLeftTop)
- {
- //get the pointer
- pPanoImageBuffer = pImage;
- //get the width
- this->nPanoWidth = nPanoWidth;
- //get the height
- this->nPanoHeight = nPanoHeight;
- //get the lefttop point
- this->LeftTop = cvLeftTop;
- //get the panoimage pitch
- this->nPanoPitch = (nPanoWidth*3 + 3) / 4 * 4;
- }
- void ImageTailor::Init_Gpu(unsigned char* pImage, unsigned char* pImageGpu, int nPanoWidth, int nPanoHeight, cv::Point cvLeftTop)
- {
- //get the pointer
- pPanoImageBuffer = pImage;
- //get the width
- this->nPanoWidth = nPanoWidth;
- //get the height
- this->nPanoHeight = nPanoHeight;
- //get the lefttop point
- this->LeftTop = cvLeftTop;
- //get the panoimage pitch
- this->nPanoPitch = (nPanoWidth * 3 + 3) / 4 * 4;
- pPanoImageBufferInGpu = pImageGpu;
- }
- int ImageTailor::StitchingOnPano(cv::Point LeftTop, cv::Mat* FrameImage,std::vector<std::vector<int>>* pvvOverlap)
- {
- //in the paon image ,the lefttop point is (0,0),stitching the image on the pano image
- //get the lefttop point
- cv::Point cvLeftTop = LeftTop;
- //get the width
- int nFrameWidth = FrameImage->cols;
- //get the height
- int nFrameHeight = FrameImage->rows;
- //get the pitch
- int nFramePitch = FrameImage->step[0];
- //set a pointer to pano image stitching target
- unsigned char* pPanoImageTarget = pPanoImageBuffer + cvLeftTop.y * nPanoPitch + cvLeftTop.x * 3;
- cv::Mat PanoImage = cv::Mat(nPanoHeight, nPanoWidth, CV_8UC3, pPanoImageBuffer);
- //stitching the image
- for (int i = 0; i < nFrameHeight; i++)
- {
- //get this line overlap
- std::vector<int>& vOverlap = (*pvvOverlap)[i];
- //copy the image
-
- FastCopy_Any(FrameImage->ptr<uchar>(i) + vOverlap[0] * 3
- , pPanoImageTarget + nPanoPitch * i + vOverlap[0] * 3
- , (vOverlap[1]- vOverlap[0]) * 3);
-
- }
- return 0;
- }
- int ImageTailor::StitchingOnPanoYUV(cv::Point LeftTop, unsigned char* pImage, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
- {
- //get Y,U,V pointer in pano image
- unsigned char* pPanoImageY = pPanoImageBuffer;
- unsigned char* pPanoImageU = pPanoImageBuffer + nPanoPitch * nPanoHeight;
- unsigned char* pPanoImageV = pPanoImageBuffer + nPanoPitch * nPanoHeight * 5 / 4;
- cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
- //get Y,U,V pointer in frame image
- unsigned char* pFrameImageY = pImage;
- unsigned char* pFrameImageU = pImage + nPitch * nHeight;
- unsigned char* pFrameImageV = pImage + nPitch * nHeight * 5 / 4;
- //Disassembly the pvvOverlap in rect to calculate the planepaste
- std::vector<cv::Rect> vPastePart;
- int nPanoImageHeight = int(pvvOverlap->size());
- cv::Rect rectPastePart;
- bool bChangeFlags = true;
- for (int i = 0; i < nPanoImageHeight; i++)
- {
- std::vector<int>& vOverlap = (*pvvOverlap)[i];
- if (rectPastePart.x != vOverlap[0]
- && rectPastePart.y != vOverlap[1])
- bChangeFlags = true;
- if (bChangeFlags)
- {
- if (i != 0)
- vPastePart.push_back(rectPastePart);
- rectPastePart.x = vOverlap[0];
- rectPastePart.width = vOverlap[1] - vOverlap[0];
- rectPastePart.y = i;
- rectPastePart.height = 0;
- bChangeFlags = false;
- }
- rectPastePart.height++;
- }
- vPastePart.push_back(rectPastePart);
- int nPartNum = (int)vPastePart.size();
- for (int i = 0; i < nPartNum; i++)
- {
- cv::Rect& CurPart = vPastePart[i];
- //panoImage pointer
- unsigned char* pPanoImageTargetY = pPanoImageY + (CurPart.y + LeftTop.y) * nPanoPitch + (CurPart.x + LeftTop.x);
- unsigned char* pPanoImageTargetU = pPanoImageU + (CurPart.y + LeftTop.y) * nPanoPitch / 4 + (CurPart.x + LeftTop.x) / 2;
- unsigned char* pPanoImageTargetV = pPanoImageV + (CurPart.y + LeftTop.y) * nPanoPitch / 4 + (CurPart.x + LeftTop.x) / 2;
- //frameImage pointer
- unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * nPitch + CurPart.x;
- unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * nPitch / 4 + CurPart.x / 2;
- unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * nPitch / 4 + CurPart.x / 2;
- //copy the Y plane
- libyuv::CopyPlane(
- pPanoImageTargetY, nPanoPitch,
- pFrameImageTargetY, nPitch,
- CurPart.width, CurPart.height
- );
- //copy the U plane
- libyuv::CopyPlane(
- pPanoImageTargetU, nPanoPitch / 2,
- pFrameImageTargetU, nPitch / 2,
- CurPart.width / 2, CurPart.height / 2
- );
- //copy the V plane
- libyuv::CopyPlane(
- pPanoImageTargetV, nPanoPitch / 2,
- pFrameImageTargetV, nPitch / 2,
- CurPart.width / 2, CurPart.height / 2
- );
- }
-
- return 0;
- }
- int ImageTailor::StitchingOnPanoYUV(cv::Point LeftTop, cv::Mat* FrameImage, std::vector<std::vector<int>>* pvvOverlap)
- {
- //get Y,U,V pointer in pano image
- unsigned char* pPanoImageY = pPanoImageBuffer;
- unsigned char* pPanoImageU = pPanoImageBuffer + ALIGN_4(nPanoWidth) * nPanoHeight;
- unsigned char* pPanoImageV = pPanoImageBuffer + ALIGN_4(nPanoWidth) * nPanoHeight * 5 / 4;
- cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
- //get Y,U,V pointer in frame image
- unsigned char* &pFrameImageY = FrameImage->data;
- unsigned char* pFrameImageU = pFrameImageY + FrameImage->step * FrameImage->rows;
- unsigned char* pFrameImageV = pFrameImageY + FrameImage->step * FrameImage->rows * 5 / 4;
- //Disassembly the pvvOverlap in rect to calculate the planepaste
- std::vector<cv::Rect> vPastePart;
- int nPanoImageHeight = int(pvvOverlap->size());
- cv::Rect rectPastePart;
- bool bChangeFlags = true;
- for (int i = 0; i < nPanoImageHeight; i++)
- {
- std::vector<int>& vOverlap = (*pvvOverlap)[i];
- if (rectPastePart.x != vOverlap[0]
- && rectPastePart.y != vOverlap[1])
- bChangeFlags = true;
- if (bChangeFlags)
- {
- if (i != 0)
- vPastePart.push_back(rectPastePart);
- rectPastePart.x = vOverlap[0];
- rectPastePart.width = vOverlap[1] - vOverlap[0];
- rectPastePart.y = i;
- rectPastePart.height = 0;
- bChangeFlags = false;
- }
- rectPastePart.height++;
- }
- vPastePart.push_back(rectPastePart);
- int nPartNum = (int)vPastePart.size();
- for (int i = 0; i < nPartNum; i++)
- {
- cv::Rect& CurPart = vPastePart[i];
- //panoImage pointer
- unsigned char* pPanoImageTargetY = pPanoImageY + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) + (CurPart.x + LeftTop.x);
- unsigned char* pPanoImageTargetU = pPanoImageU + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x + LeftTop.x) / 2;
- unsigned char* pPanoImageTargetV = pPanoImageV + (CurPart.y + LeftTop.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x + LeftTop.x) / 2;
- //frameImage pointer
- unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * FrameImage->step + CurPart.x;
- unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * FrameImage->step / 4 + CurPart.x / 2;
- unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * FrameImage->step / 4 + CurPart.x / 2;
- //copy the Y plane
- libyuv::CopyPlane(
- pFrameImageTargetY, FrameImage->step,
- pPanoImageTargetY, ALIGN_4(nPanoWidth),
- CurPart.width, CurPart.height
- );
- //copy the U plane
- libyuv::CopyPlane(
- pFrameImageTargetU, FrameImage->step / 2,
- pPanoImageTargetU, ALIGN_4(nPanoWidth) / 2,
- CurPart.width / 2, CurPart.height / 2
- );
- //copy the V plane
- libyuv::CopyPlane(
- pFrameImageTargetV, FrameImage->step / 2,
- pPanoImageTargetV, ALIGN_4(nPanoWidth) / 2,
- CurPart.width / 2, CurPart.height / 2
- );
- }
- return 0;
- }
- void ImageTailor::TailorWordInThread(ImageTailor* pClass)
- {
- while (pClass->bTailorThreadOut)
- {
-
- g_CurFrameMutex.lock();
- g_PanoMutex.lock();
- if (pClass->qWorkQueue.size()<=0 || pClass->qWorkQueue.size() >10000)
- {
- g_CurFrameMutex.unlock();
- g_PanoMutex.unlock();
- continue;
- //pClass->ClearWorkOrder();
-
- }
-
- pClass->bTailorThreadWork = true;
-
- //WAIT_TAILOR& WorkOrder = pClass->qWorkQueue.front();
-
-
- if (!pClass->bUseYUV)
- pClass->StitchingOnPano(pClass->qWorkQueue.front().ptPosition, pClass->qWorkQueue.front().pROI, pClass->qWorkQueue.front().pvvOverlap);
- else
- pClass->StitchingOnPanoYUVByGPU(
- pClass->qWorkQueue.front().ptPosition,
- pClass->qWorkQueue.front().pImage,
- pClass->qWorkQueue.front().nWidth,
- pClass->qWorkQueue.front().nHeight,
- ALIGN_4(pClass->qWorkQueue.front().nPitch),
- pClass->qWorkQueue.front().pvvOverlap
- );
- g_CurFrameMutex.unlock();
- g_PanoMutex.unlock();
- pClass->qWorkQueue.pop();
- if (pClass->qWorkQueue.size() > 25)
- pClass->qWorkQueue.pop();
- if( pClass->qWorkQueue.size() > 50)
- pClass->qWorkQueue.pop();
- pClass->bTailorThreadWork = false;
- }
- }
- /// <summary>
- /// Stitchings the on pano.
- /// </summary>
- /// <param name="LeftTop">The left top.</param>
- /// <param name="FrameImage">The frame image.</param>
- /// <param name="nWidth">Width of the n.</param>
- /// <param name="nHeight">Height of the n.</param>
- /// <param name="nPitch">The n pitch.</param>
- /// <param name="pvvOverlap">The PVV overlap.</param>
- /// <returns></returns>
- int ImageTailor::StitchingOnPanoYUVByGPU(cv::Point LeftTop, unsigned char* FrameImage, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
- {
-
- //get Y,U,V pointer in pano image
- unsigned char* pPanoImageY = pPanoImageBufferInGpu + LeftTop.y * ALIGN_4(nPanoWidth) + LeftTop.x;
- unsigned char* pPanoImageU = pPanoImageBufferInGpu + ALIGN_4(nPanoWidth) * nPanoHeight + LeftTop.y/2 * (ALIGN_4(nPanoWidth)/2) + LeftTop.x/2;
- unsigned char* pPanoImageV = pPanoImageBufferInGpu + ALIGN_4(nPanoWidth) * nPanoHeight * 5 / 4 + LeftTop.y / 2 * (ALIGN_4(nPanoWidth) / 2) + LeftTop.x / 2;
- //cv::Mat panoImage(nPanoHeight * 3 / 2, nPanoWidth, CV_8U, pPanoImageBuffer);
- unsigned char*& pFrameImageY = FrameImage;
- unsigned char* pFrameImageU = pFrameImageY + nPitch * nHeight;
- unsigned char* pFrameImageV = pFrameImageY + nPitch * nHeight * 5 / 4;
- //Disassembly the pvvOverlap in rect to calculate the planepaste
- std::vector<cv::Rect> vPastePart;
- int nPanoImageHeight = int(pvvOverlap->size());
- cv::Rect rectPastePart;
- bool bChangeFlags = true;
- for (int i = 0; i < nPanoImageHeight; i++)
- {
- std::vector<int>& vOverlap = (*pvvOverlap)[i];
- if (rectPastePart.x != vOverlap[0]
- && rectPastePart.y != vOverlap[1])
- bChangeFlags = true;
- if (bChangeFlags)
- {
- if (i != 0)
- vPastePart.push_back(rectPastePart);
- rectPastePart.x = vOverlap[0];
- rectPastePart.width = vOverlap[1] - vOverlap[0];
- rectPastePart.y = i;
- rectPastePart.height = 0;
- bChangeFlags = false;
- }
- rectPastePart.height++;
- }
- vPastePart.push_back(rectPastePart);
- int nBlockCount =int(vPastePart.size());
- for (int i = 0; i < nBlockCount; i++)
- {
- cv::Rect CurPart = vPastePart[i];
- int nPasteWidth = CurPart.width;
- int nPasteHeight = CurPart.height;
- int nPasteLeft = CurPart.x;
- int nPasteTop = CurPart.y;
- unsigned char* pPanoImageTargetY = pPanoImageY;//; +(CurPart.y) * ALIGN_4(nPanoWidth) + (CurPart.x);
- unsigned char* pPanoImageTargetU = pPanoImageU;// +(CurPart.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x) / 2;
- unsigned char* pPanoImageTargetV = pPanoImageV;// +(CurPart.y) * ALIGN_4(nPanoWidth) / 4 + (CurPart.x) / 2;
- //frameImage pointer
- unsigned char* pFrameImageTargetY = pFrameImageY + CurPart.y * nPitch + CurPart.x;
- unsigned char* pFrameImageTargetU = pFrameImageU + CurPart.y * nPitch / 4 + CurPart.x / 2;
- unsigned char* pFrameImageTargetV = pFrameImageV + CurPart.y * nPitch / 4 + CurPart.x / 2;
- YUVTailorAndBlender::CopyPlane(
- pFrameImageTargetY, nWidth, nHeight, nPitch,
- pPanoImageTargetY, nPanoWidth, nPanoHeight, ALIGN_4(nPanoWidth),
- nPasteWidth, nPasteHeight, nPasteLeft, nPasteTop,
- 1, NULL
- );
- YUVTailorAndBlender::CopyPlane(
- pFrameImageTargetU, nWidth / 2, nHeight / 2, nPitch / 2,
- pPanoImageTargetU, nPanoWidth / 2, nPanoHeight / 2, ALIGN_4(nPanoWidth) / 2,
- nPasteWidth / 2, nPasteHeight / 2, nPasteLeft / 2, nPasteTop / 2,
- 1, NULL
- );
- YUVTailorAndBlender::CopyPlane(
- pFrameImageTargetV, nWidth / 2, nHeight / 2, nPitch / 2,
- pPanoImageTargetV, nPanoWidth / 2, nPanoHeight / 2, ALIGN_4(nPanoWidth) / 2,
- nPasteWidth / 2, nPasteHeight / 2, nPasteLeft / 2, nPasteTop / 2,
- 1, NULL
- );
- cudaError Error = cudaDeviceSynchronize();
- if (Error == 700)
- int x = 10;
- }
- return 0;
- }
- int ImageTailor::Stitching(int nPostion, cv::Mat& ROI, std::vector<std::vector<int>>* pvvOverlap)
- {
- return 0;
- }
- void ImageTailor::SetOverlap(std::vector<std::vector<int>>* pvvOverlap)
- {
- vvOverlap = *pvvOverlap;
- }
- bool ImageTailor::StartTailorThread()
- {
- pTailorThread = new std::thread(TailorWordInThread, this);
- return false;
- }
- bool ImageTailor::EndTailorThread()
- {
- if (pTailorThread->joinable())
- {
- this->bTailorThreadOut = false;
- pTailorThread->join();
- return true;
- }
- else
- {
- return false;
- }
- }
- void ImageTailor::AddWorkOrderInqueue(cv::Point LeftTop, cv::Mat* FrameImage, std::vector<std::vector<int>>* pvvOverlap)
- {
- WAIT_TAILOR WorkOrder;
- WorkOrder.ptPosition = LeftTop;
- WorkOrder.pROI = FrameImage;
- WorkOrder.pvvOverlap = pvvOverlap;
- qWorkQueue.push(WorkOrder);
- }
- void ImageTailor::ClearWorkOrder()
- {
- std::queue<WAIT_TAILOR>().swap(qWorkQueue);
- /*while (!qWorkQueue.empty())
- {
- qWorkQueue.pop();
- }*/
- }
- void ImageTailor::AddWorkOrderInQueueGpu(cv::Point LeftTop, unsigned char* pData, int nWidth, int nHeight, int nPitch, std::vector<std::vector<int>>* pvvOverlap)
- {
- WAIT_TAILOR WorkOrder;
- WorkOrder.ptPosition = LeftTop;
- WorkOrder.pImage = pData;
- WorkOrder.nWidth = nWidth;
- WorkOrder.nHeight = nHeight;
- WorkOrder.nPitch = nPitch;
- WorkOrder.pvvOverlap = pvvOverlap;
- qWorkQueue.push(WorkOrder);
- }
|