resize_NV21

#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;
}

部分内容参考博客

可以使用OpenCV库中的cv::resize函数来进行缩放操作。具体的操作步骤如下: 1. 读取NV12格式的图像数据,可以通过cv::imdecode函数将NV12数据解码为BGR格式的图像。 2. 将BGR格式的图像转换为灰度图像,可以使用cv::cvtColor函数。 3. 使用cv::resize函数对灰度图像进行缩放操作,同时保持NV12格式的数据结构。 下面是一段代码示例: ```cpp // 读取NV12数据 std::vector<uchar> nv12_data; // NV12数据 int width, height; // 图像宽度和高度 // 读取NV12数据... // ... // 解码NV12数据为BGR格式的图像 cv::Mat bgr_img = cv::imdecode(nv12_data, cv::IMREAD_COLOR); // 转换为灰度图像 cv::Mat gray_img; cv::cvtColor(bgr_img, gray_img, cv::COLOR_BGR2GRAY); // 缩放灰度图像,并保持NV12数据结构 int dst_width = width / 2; // 缩放后的宽度 int dst_height = height / 2; // 缩放后的高度 cv::Mat dst_img(dst_height * 3 / 2, dst_width, CV_8UC1); // 目标图像 cv::resize(gray_img, dst_img(cv::Rect(0, 0, dst_width, dst_height)), cv::Size(dst_width, dst_height)); // 将缩放后的灰度图像转换为NV12格式的数据 std::vector<uchar> dst_nv12_data(dst_height * dst_width * 3 / 2); // 目标NV12数据 uchar* p_dst_y = &dst_nv12_data[0]; // 目标Y分量 uchar* p_dst_uv = p_dst_y + dst_height * dst_width; // 目标UV分量 uchar* p_src_y = dst_img.data; // 源Y分量 uchar* p_src_uv = p_src_y + dst_height * dst_width; // 源UV分量 for (int i = 0; i < dst_height; i++) { memcpy(p_dst_y, p_src_y, dst_width); p_dst_y += dst_width; p_src_y += dst_img.step; } for (int i = 0; i < dst_height / 2; i++) { memcpy(p_dst_uv, p_src_uv, dst_width); p_dst_uv += dst_width; p_src_uv += dst_img.step; } ``` 其中,dst_img是缩放后的灰度图像,dst_nv12_data是缩放后的NV12格式的数据。注意,在NV12格式中,Y分量和UV分量交错存储,所以需要分别处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值