#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <sstream>
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
const unsigned char *BGR2NV21(cv::Mat bgrImg)
{
int cols = bgrImg.cols;
int rows = bgrImg.rows;
cout<<"cols = "<< cols <<"\t ,rows = "<< rows <<endl;
int Yindex = 0;
int UVindex = rows * cols;
unsigned char* yuvbuff = new unsigned char[rows * cols *3 /2];
cv::Mat NV21(rows+rows/2, cols, CV_8UC1);
int UVRow{ 0 };
for (int i=0;i<rows;i++)
{
for (int j=0;j<cols;j++)
{
uchar* YPointer = NV21.ptr<uchar>(i);
int B = bgrImg.at<cv::Vec3b>(i, j)[0];
int G = bgrImg.at<cv::Vec3b>(i, j)[1];
int R = bgrImg.at<cv::Vec3b>(i, j)[2];
//计算Y的值
int Y = (77 * R + 150 * G + 29 * B) >> 8;
YPointer[j] = Y;
yuvbuff[Yindex++] = (Y < 0) ? 0 : ((Y > 255) ? 255 : Y);
uchar* UVPointer = NV21.ptr<uchar>(rows+i/2);
//计算U、V的值,进行2x2的采样
if (i%2==0&&(j)%2==0)
{
int U = ((-44 * R - 87 * G + 131 * B) >> 8) + 128;
int V = ((131 * R - 110 * G - 21 * B) >> 8) + 128;
UVPointer[j] = V;
UVPointer[j+1] = U;
yuvbuff[UVindex++] = (V < 0) ? 0 : ((V > 255) ? 255 : V);
yuvbuff[UVindex++] = (U < 0) ? 0 : ((U > 255) ? 255 : U);
}
}
}
return yuvbuff;
}
const unsigned char *resize_nv21(const unsigned char *in_data , int in_w, int in_h, int out_w, int out_h)
{
Mat nv21(in_h *3 /2, in_w, CV_8UC1,const_cast<uchar *>(in_data));// in_data to Mat nv21
Mat bgr;
Mat bgr_small;//define a mat in rgb datas
cvtColor(nv21,bgr,CV_YUV2BGR_NV21);//converto nv21 to bgr
resize(bgr, bgr_small, Size(out_w,out_h));
//cv::imwrite("bgr_small.jpg", bgr_small);
return BGR2NV21(bgr_small);
}
//使用时修改相关路径及宽高尺寸
int main()
{
const char *filename = "yuv.yuv"; //储存原有的nv21数据
FILE *fp = fopen(filename,"rb");
if(fp == nullptr){
cout << "open file foreman failed" << endl;
return 0;
}
int len = 416 * 416 * 3/2;
const unsigned char *buff = (const unsigned char *)malloc(len);
fread(const_cast<uchar *>(buff), sizeof(const unsigned char), len, fp);
const char *outname = "yuv224.yuv"; //储存新生成的nv21数据
FILE *out = fopen(outname,"wb");
int len_out = 224 * 224 * 3/2;
const unsigned char *buff_out = (const unsigned char *)malloc(len_out);
buff_out = resize_nv21(buff,416,416,224,224);
fwrite(buff_out, sizeof(const unsigned char), len_out, out);
return 0;
}
部分内容参考博客