对于YUV420sp格式图像的copy and paste

重点在于计算好y、u、v分量的位置。

yuv420sp存储格式详解:RGB 与YUV颜色模型及存储格式

rgb转yuv420sp:RGB、YUV420p、YUV420sp之间的互相转换(C++)(代码中的showImage(),encodeYUV420sp()函数在此)

 

OpenCV中如果是单通道或者三通道一样的大的图像,直接使用copyTo函数即可。对于yuv420的图像则不是适用。

下面以图像的copy and paste 为例,解释如何获取某个坐标的y、u、v分量。

将一副小图copy到大图中去(都是yuv420sp格式)。y分量排在图像数据的前面,大小为w*h,直接copy and paste即可,v、u分量大小为w/2 * h/2,分别对行和列下二采样,v、u间隔存储,这样一行就有w个数据,(i,j)的v分量在w*h + i/2*w + j,u分量在w*h + i/2*w + j+1。

 

一个测试demo:

测试图片在:

链接:https://pan.baidu.com/s/1qHdPHNMaH5xUafH6XlWcMw 
提取码:b4m6

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	Mat img_eye = imread("eye_1.jpg");//Sharingan_1  eye_1
	Mat img_hand = imread("hand_1.jpg");
	//showImage("img_eye", img_eye);

	int height = img_eye.rows;
	int width = img_eye.cols;

	int height_back = img_hand.rows;
	int width_back = img_hand.cols;

	//get brg data
    unsigned char* img_eye_bgr_data = (unsigned char*)malloc(height*width * 3 * sizeof(unsigned char));
	unsigned char* img_hand_bgr_data = (unsigned char*)malloc(height_back*width_back * 3 * sizeof(unsigned char));
	for (int i = 0; i < height; i++)
	{
		unsigned char* current_row = img_eye.ptr<uchar>(i);
		for (int j = 0; j < width; j++)
		{
			img_eye_bgr_data[(i * width + j) * 3 + 0] = current_row[j * 3 + 0];//B
			img_eye_bgr_data[(i * width + j) * 3 + 1] = current_row[j * 3 + 1];//G
			img_eye_bgr_data[(i * width + j) * 3 + 2] = current_row[j * 3 + 2];//R
		}
	}
	for (int i = 0; i < height_back; i++)
	{
		unsigned char* current_row = img_hand.ptr<uchar>(i);
		for (int j = 0; j < width_back; j++)
		{
			img_hand_bgr_data[(i * width_back + j) * 3 + 0] = current_row[j * 3 + 0];//B
			img_hand_bgr_data[(i * width_back + j) * 3 + 1] = current_row[j * 3 + 1];//G
			img_hand_bgr_data[(i * width_back + j) * 3 + 2] = current_row[j * 3 + 2];//R
		}
	}
	
	// RGB covert to NV21
	unsigned char* img_eye_nv21_data = (unsigned char*)malloc(height*width * 3 / 2 * sizeof(unsigned char));
	unsigned char* img_hand_nv21_data = (unsigned char*)malloc(height_back*width_back * 3 / 2 * sizeof(unsigned char));
	encodeYUV420sp(img_eye_nv21_data, img_eye_bgr_data, width, height);
	encodeYUV420sp(img_hand_nv21_data, img_hand_bgr_data, width_back, height_back);

	//Mat img_eye_nv21(height * 3 / 2, width, CV_8UC1, img_eye_nv21_data);
	//Mat img_hand_nv21(height_back * 3 / 2, width_back, CV_8UC1, img_hand_nv21_data);

	// copy and paste 
	// 1. RGB
	//Rect roi(200, 450, img_eye.cols, img_eye.rows);
	//img_eye.copyTo(img_hand(roi));
	//showImage("img_hand", img_hand);

	// 2.YUV420sp
	int frame_size_eye = width*height;
	int frame_size_hand = width_back*height_back;
	int uv_index = frame_size_eye;
	int x0 = 450;
	int y0 = 200;

	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			*(img_hand_nv21_data + ((x0 + i)*width_back + y0 + j)) = *(img_eye_nv21_data + (i*width + j));//copy Y
		}
	}

	for (int i = 0; i < height; i+=2)
	{
		for (int j = 0; j < width; j+=2)
		{
			*(img_hand_nv21_data + frame_size_hand + ((x0 + i) / 2 * width_back + y0 + j)) = *(img_eye_nv21_data + (uv_index++));//copy V
			*(img_hand_nv21_data + frame_size_hand + ((x0 + i) / 2 * width_back + y0 + j + 1)) = *(img_eye_nv21_data + (uv_index++));//copy U
		}
	}

	Mat img_hand_nv21(height_back * 3 / 2, width_back, CV_8UC1, img_hand_nv21_data);
	Mat img_hand_bgr(height_back, width_back, CV_8UC3);
	cvtColor(img_hand_nv21, img_hand_bgr, CV_YUV2BGR_NV21);
	showImage("img_hand_bgr", img_hand_bgr);
	return 0;
}

效果:


版权声明:本文为u014485485原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。