经过查阅许多牛人的博客,特别是要感谢博主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;
}