HEVC/3D-HEVC视频编码中LCU分割信息提取及保留

     经过查阅许多牛人的博客,特别是要感谢博主minbiao880224(http://blog.csdn.net/minbiao880224/article/details/17685935),具体LCU分割信息提取参照该博主的文章,本文将博文中LCU显示MATLAB代码改写成了opencvC++代码,能够显示彩色图像LCU分割信息,也增加了一些新的代码(比如提取txt文档二进制数据,yuv文件420格式转换为Mat格式),希望对初学opencv mat类有一定帮助吧!

#include "opencv2/opencv.hpp"
#include <iostream>
#include <fstream>

using namespace std;
using namespace cv;


#define LCU_Size 64
#define MaxNumPartition 256
#define nWidth 1024
#define nHeight 768
#define FrameSize nWidth*nHeight*3/2
#define NumLCU_Row  (nWidth + LCU_Size - 1) / LCU_Size
#define NumLCU_Col  (nHeight + LCU_Size - 1) / LCU_Size
#define Numdata  NumLCU_Row*NumLCU_Col*MaxNumPartition

void DrawCUDepthLine(Mat rgbImg, int* DepthCTU, int uiPelX, int uiPelY, int uiSize_X, int  uiSize_Y, int uiNumPartition)
{
	int uiDepth = DepthCTU[0];
	if (uiDepth == 0) { return; }
	else
	{
		for (int i = 0; i < uiNumPartition; i++)
		{
			DepthCTU[i] -= 1;
		}
		Point p1, p2;
		p1.x = uiPelX + uiSize_X / 2; p1.y = uiPelY;
		p2.x = uiPelX + uiSize_X / 2; p2.y = uiPelY + uiSize_Y;
		line(rgbImg, p1, p2, cv::Scalar(255, 0, 0), 1);
		Point p3, p4;
		p3.x = uiPelX; p3.y = uiPelY + uiSize_Y / 2;
		p4.x = uiPelX + uiSize_X; p4.y = uiPelY + uiSize_Y / 2;
		line(rgbImg, p3, p4, cv::Scalar(255, 0, 0), 1);
		//further drawing
		int uiNextSize_X = uiSize_X / 2;
		int uiNextSize_Y = uiSize_Y / 2;
		int uiNumPartitionNext = uiNumPartition / 4;

		for (int iAbsPartY = 0; iAbsPartY < 2; iAbsPartY++)
		{
			for (int iAbsPartX = 0; iAbsPartX < 2; iAbsPartX++)
			{

				int uiNextPelX, uiNextPelY;
				int  iAbsPartIndex = iAbsPartY * 2 + iAbsPartX;
				int* iNextDepth = new int[uiNumPartitionNext];
				for (int i = 0; i <uiNumPartitionNext; i++)
				{
					iNextDepth[i] = DepthCTU[i + iAbsPartIndex * uiNumPartitionNext];
				}
				uiNextPelX = uiPelX + iAbsPartX*uiNextSize_X;
				uiNextPelY = uiPelY + iAbsPartY*uiNextSize_Y;
				DrawCUDepthLine(rgbImg, iNextDepth, uiNextPelX, uiNextPelY, uiNextSize_X, uiNextSize_Y, uiNumPartitionNext);

			}

		}

	}

}


int main()
{

	//读取txt文件分割深度数据存入arr数组中,每个分割深度数据代表4*4的块,一个LCU有256个分割深度数据
	int length = 0;
	ifstream t("BestDepth.txt", ios::in | ios::binary);
	if (!t)
	{
		cout << "open error!" << endl;
		return 1;
	}
	t.seekg(0, std::ios::end);    // go to the end  
	length = t.tellg();           // report location (this is the length)  
	cout << "length=" << length << endl;
	t.seekg(0, std::ios::beg);    // go back to the beginning  
	char* buffer = new char[length];    // allocate memory for a buffer of appropriate dimension  
	t.read(buffer, length);
	int* arr = new int[length];
	for (int i = 0; i<length; i++)
	{
		arr[i] = (int)buffer[i];
	}

	//打开yuv文件
	FILE *f;
	if (!(f = fopen("balloons3.yuv", "rb")))
	{
		printf("file open error!");
	}
	//计算YUV视频帧数和文件大小
	fseek(f, 0, SEEK_END);
	int frame_count = 0;
	long file_size = 0;
	frame_count = (int)((int)ftell(f) / ((nWidth * nHeight * 3) / 2));  // ftell 用于求文件大小
	printf("frame num is %d \n", frame_count);
	printf("file length is   %d\n", ftell(f));
	fseek(f, 0, SEEK_SET);//文件内位置定位到文件头


	namedWindow("balloons", WINDOW_NORMAL);
	int bufLen = nWidth*nHeight * 3 / 2;
	unsigned char* pYuvBuf = new unsigned char[bufLen];
	int pos = 0;
	for (int n = 0; n < frame_count; n++)//对每一帧图像画LCU分割图,需要保留那一帧的LCU分割,只需修改frame_count值
	{
		fseek(f, pos, SEEK_SET);
		//读取yuv420格式的文件,转换成cv::Mat格式
		fread(pYuvBuf, bufLen*sizeof(unsigned char), 1, f);
		Mat yuvImg;
		yuvImg.create(nHeight * 3 / 2, nWidth, CV_8UC1);
		memcpy(yuvImg.data, pYuvBuf, bufLen*sizeof(unsigned char));
		Mat rgbImg;
		cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);

		//在图像上画出LCU的分割情况
		Point p1, p2;
		for (int i = 1; i < nWidth / LCU_Size; i++)
		{
			p1.x = i*LCU_Size; p1.y = 0;
			p2.x = i*LCU_Size; p2.y = nHeight;
			line(rgbImg, p1, p2, cv::Scalar(0, 0, 255), 2);
		}
		for (int i = 1; i < nHeight / LCU_Size; i++)
		{
			p1.y = i*LCU_Size; p1.x = 0;
			p2.y = i*LCU_Size; p2.x = nWidth;
			line(rgbImg, p1, p2, cv::Scalar(0, 0, 255), 2);
		}
		int LCUData[MaxNumPartition];
		for (int i = 0; i < NumLCU_Col; i++)
		{
			for (int j = 0; j < NumLCU_Row; j++)
			{
				int Idx = i*NumLCU_Row + j;
				int uiPelX = j*LCU_Size;
				int uiPelY = i*LCU_Size;

				for (int k = 0; k <MaxNumPartition; k++)
				{
					LCUData[k] = arr[k + Idx*MaxNumPartition+ Numdata*n];
				}
				DrawCUDepthLine(rgbImg, LCUData, uiPelX, uiPelY, LCU_Size, LCU_Size, MaxNumPartition);
			}
		}
		
		imshow("balloons", rgbImg);
		imwrite("plotLCU.jpg", rgbImg);
		waitKey(30);
		pos += FrameSize;
	
	}
	waitKey(0);
	destroyWindow("balloons");
	delete[] pYuvBuf;
	fclose(f);
	system("pause");
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值