Jump to content
Compvision.ru
Sign in to follow this  
Vicul

Конвертор формата BGR24 to YUYV

Recommended Posts

Работаю с программой, где я принимаю фреймы в BGR24 формате и передаю их в модуль, собранный на кодах FFMPEG, который передает их на тв сайт по RTMP протоколу. Все работает нормально, но возникла необходимость передавать фреймы не в BGR24, а в YUYV (YUY2), т.е, нужен конвертор BGR24 -> YUYV. Нашел коды на openCV, немного подправил их и получил одну фигню - концовка кадра почему то оказалась вначале, см. приатаченный файл.

Не могу понять, где хомутнул, вот коды конвертора




typedef struct _typeYUYV

{

	char Y0;

	char U0;

	char Y1;

	char V0;

} _typeYUYV;


typedef enum _typeFormat

{

	_NONE = 0,

	_UYVY,

	_YUYV

}


int  ConvertBGRTo(char* pSrcBuf, size_t nSrcBufSize, _typeFormat nFormatType, char* pDstBuf, size_t& nDstBufSize, int outX, int outY)

{

	int nRes = NO_ERROR;


	// Create IplImage for given BMP

	int nStep = outX*3;

	IplImage RgbImg;

	cvInitImageHeader( &RgbImg, cvSize(outX, outY), IPL_DEPTH_8U, 3 );

	cvSetData( &RgbImg, (char*)pSrcBuf, nStep );


	// Convert RGB24 to YUV (YCrCb)

	IplImage* pYuvImg = cvCloneImage(&RgbImg);

	cvCvtColor(&RgbImg,pYuvImg, CV_BGR2YCrCb);


	char* pDstBufEndPos = pDstBuf + nDstBufSize;

	for(int nCurYPos = outY - 1; nCurYPos > 0; nCurYPos--)

	{

		_typeYUV* pSrcBufCurPos = (_typeYUV*)(pYuvImg->imageData + nCurYPos * nStep);

		char* pSrcBufEndPos = (char*)pSrcBufCurPos + nStep;


		for(;(char*)pSrcBufCurPos < pSrcBufEndPos;)

		{

			_typeYUYV YUYV = {	pSrcBufCurPos[0].Y,

								pSrcBufCurPos[0].U,

								pSrcBufCurPos[1].Y,

								pSrcBufCurPos[0].V	};


			if((pDstBuf + sizeof(_typeYUYV)) > pDstBufEndPos)

				break;


			memcpy(pDstBuf,&YUYV,sizeof(_typeYUYV));

			pDstBuf += sizeof(_typeYUYV);


			if((char*)(pSrcBufCurPos + 2) > pSrcBufEndPos)

				break;

			pSrcBufCurPos += 2;

		}		

	}


	cvReleaseImage(&pYuvImg);


	return nRes;


}


Поделитесь идеями?

Share this post


Link to post
Share on other sites

это понятно, что не правильный, только вот где?

Вот здесь я заполняю BITMAPINFOHEADER в FFMPEG модуле для YUYV (аналог YUY2), может здесь я что то намутил?


struct VIDEOSTRUCT

{

        uint32_t lBufSize;

        uint32_t iWidth;

        uint32_t iHeight;

        int64_t  iTime;

        uint8_t* pBuf;

};


.......



                                list<VIDEOSTRUCT>::iterator delIter = VideoBuf.begin();

				int headersSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

				int bufSize = headersSize + delIter->lBufSize;


				PBYTE data =  new BYTE [bufSize];

				if (data != NULL)

				{

					BITMAPFILEHEADER* pbfHeader;

					BITMAPINFOHEADER* pbmiHeader;


					pbfHeader = (BITMAPFILEHEADER *)(data);


					pbfHeader->bfType = ('M' << CHAR_BIT) | 'B' ; //'MB';

					pbfHeader->bfSize = bufSize;

					pbfHeader->bfOffBits = headersSize;

					pbfHeader->bfReserved1 = pbfHeader->bfReserved2 = 0;


					uint8_t* pData;

					pData = data + headersSize;

					pbmiHeader = (BITMAPINFOHEADER *)(pData - sizeof(BITMAPINFOHEADER));


					pbmiHeader->biBitCount = 16;

					pbmiHeader->biWidth    = delIter->iWidth;

					pbmiHeader->biHeight   = delIter->iHeight;


					pbmiHeader->biPlanes   = 1;

					pbmiHeader->biSize     = sizeof(BITMAPINFOHEADER);

					pbmiHeader->biCompression  = MAKEFOURCC('Y', 'U', 'Y', '2');//MAKEFOURCC('Y', 'U', 'Y', 'V');//MAKEFOURCC('Y', 'U', 'Y', 'V');//BI_RGB;

					pbmiHeader->biClrImportant = pbmiHeader->biClrUsed =

                                        pbmiHeader->biXPelsPerMeter =

                                                 pbmiHeader->biYPelsPerMeter = 0;

                                        pbmiHeader->biSizeImage =  DIBSIZE(*pbmiHeader);



Share this post


Link to post
Share on other sites

Со сдвигом разобрался, дело в том, что в приемном модуле у меня кодек был установлен как RAWVIDEO и заголовки типа BITMAP... там не нужны, потому все сдвигалось на размер этих заголовков.

Но теперь проблема чисто opencv, изображение на выходе идет с синими лицами. С помощью cvSaveImage() определил, что bgr кадр поступает в конвертор c нормальными цветами,

а вот на выходе идет уже с искажением на синий цвет.

Где копать? коды конвертора в первом посте.

Share this post


Link to post
Share on other sites

А если заменить cvCvtColor(&RgbImg, pYuvImg, CV_BGR2YCrCb) на cvCvtColor(&RgbImg, pYuvImg, CV_RGB2YCrCb)?

  • Like 1

Share this post


Link to post
Share on other sites

Блин заработало!!!

Дай Бог тебе здоровья и удачи.

Полдня сидел, чуть себе резьбу не сорвал.

Не понятно, почему CV_RGB2YCrC, ведь на вход у меня поступает bgr?

Share this post


Link to post
Share on other sites

Я как-то столкнулся с похожей проблемой в IPP'шных кодеках. Так и не понял в чём дело. Специально для них писал функцию на ассемблере для быстрой смены каналов местами.

В твоём конкретном случае, чувствую, тоже надо разбираться отдельно.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×