首页 > 其他分享 >OpenCV对NV12进行通道分离后缩放再保存为NV12格式

OpenCV对NV12进行通道分离后缩放再保存为NV12格式

时间:2023-02-17 11:22:30浏览次数:54  
标签:缩放 int image yuv OpenCV image2 NV12 cv 分量

1.OpenCV对NV12进行通道分离后缩放再保存为NV12格式

 

#include <stdio.h>
#include <opencv2/opencv.hpp>

/**
 * @brief 
 *   把输入的NV12图像分离为YUV三个分量图像
 * @param image_yuv 输入YUV图像
 * @param image_y   输出的Y分量
 * @param image_u   输出的U分量
 * @param image_v   输出的V分量
 * @param image_h   输入图像高度
 * @param image_w   输入图像宽度
 * @return void     方法返回空值
 */
int nv12_split_yuv(cv::Mat &image_yuv, cv::Mat &image_y, cv::Mat &image_u, cv::Mat &image_v, int image_h, int image_w)
{
	// 分离Y分量数据
	void *y_src = (void *)image_yuv.data; // Y分量的起始指针
	void *y_dst = (void *)image_y.data;   // Y分量的目的指针
	size_t y_len = image_h * image_w;     // Y分量的拷贝长度
	memcpy(y_dst, y_src, y_len);          // 分离Y分量的数据

	// 分离UV分量数据
	unsigned char *uv_src = (unsigned char *)(image_yuv.data + image_h * image_w); // UV分量的起始指针
	unsigned char *u_dst = (unsigned char *)image_u.data;                          //  U分量的目的指针
	unsigned char *v_dst = (unsigned char *)image_v.data;                          //  V分量的目的指针
	int uv_len = (image_h / 2) * (image_w / 2);                                    // UV分量的拷贝长度
	for(int i = 0; i < uv_len; i++){                                               // 分量UV分量的数据
		u_dst[i] = *uv_src++;                                                      // 拷贝 U后指针后移
		v_dst[i] = *uv_src++;                                                      // 拷贝 V后指针后移
	}

	return 0;
}

/**
 * @brief 
 *   把输入的YUV三个分量图像合并为NV12图像
 * @param image_y   输入的Y分量
 * @param image_u   输入的U分量
 * @param image_v   输入的V分量
 * @param image_yuv 输出YUV图像
 * @param image_h   输入图像高度
 * @param image_w   输入图像宽度
 * @return void     方法返回空值
 */
int nv12_merge_yuv(cv::Mat &image_y, cv::Mat &image_u, cv::Mat &image_v, cv::Mat &image_yuv, int image_h, int image_w)
{
	// 合并Y分量数据
	void *y_src = (void *)image_y.data;   // Y分量的起始指针
	void *y_dst = (void *)image_yuv.data; // Y分量的目的指针
	size_t y_len = image_h * image_w;     // Y分量的拷贝长度
	memcpy(y_dst, y_src, y_len);          // 合并Y分量的数据

	// 合并UV分量数据
	unsigned char *u_src = (unsigned char *)image_u.data;                          //  U分量的起始指针
	unsigned char *v_src = (unsigned char *)image_v.data;                          //  V分量的起始指针
	unsigned char *uv_dst = (unsigned char *)(image_yuv.data + image_h * image_w); // UV分量的目的指针
	int uv_len = (image_h / 2) * (image_w / 2);                                    // UV分量的拷贝长度
	for(int i = 0; i < uv_len; i++){                                               // 分量UV分量的数据
		*uv_dst++ = u_src[i];                                                      // 拷贝 U后指针后移
		*uv_dst++ = v_src[i];                                                      // 拷贝 V后指针后移
	}

	return 0;
}

int main(int argc, char **argv)
{
	// 检查输入参数
	if(argc != 4){
		printf("Usage: %s <image_path> <image_width> <image_height>\n", argv[0]);
		return -1;
	}

	// 读取输入图像
	char *image_path = argv[1];
	int image_w = atoi(argv[2]);
	int image_h = atoi(argv[3]);
	int image_len = image_w * image_h * 3 / 2;
	unsigned char *image_buf = (unsigned char *)malloc(image_len);

	FILE *fp = fopen(image_path, "rb");
	fread(image_buf, image_len, 1, fp);
	fclose(fp);

	// 分离NV12分量
	cv::Mat image_yuv(image_h * 3 / 2, image_w, CV_8UC1, image_buf);
	cv::Mat image_y(image_h, image_w, CV_8UC1);
	cv::Mat image_u(image_h / 2, image_w / 2, CV_8UC1);
	cv::Mat image_v(image_h / 2, image_w / 2, CV_8UC1);

	nv12_split_yuv(image_yuv, image_y, image_u, image_v, image_h, image_w);

	// 缩放分离图像
	float hw_ratio = (float)image_h / image_w;
	int image2_h = int(416 * hw_ratio);
	int image2_w = 416;
	printf("image2_h:%d, image2_w:%d\n", image2_h, image2_w);

	cv::resize(image_y, image_y, cv::Size(image2_w, image2_h), cv::INTER_LINEAR);
	cv::resize(image_u, image_u, cv::Size(image2_w / 2, image2_h / 2), cv::INTER_LINEAR);
	cv::resize(image_v, image_v, cv::Size(image2_w / 2, image2_h / 2), cv::INTER_LINEAR);

	// 合并NV12分量
	cv::Mat image_yuv2(image2_h * 3 / 2, image2_w, CV_8UC1, image_buf);
	nv12_merge_yuv(image_y, image_u, image_v, image_yuv2, image2_h, image2_w);

	// 显示分离图像
	cv::imshow("image_y", image_y);
	cv::waitKey();

	cv::imshow("image u", image_u);
	cv::waitKey();

	cv::imshow("image v", image_v);
	cv::waitKey();

	cv::Mat image_bgr;
	cv::cvtColor(image_yuv2, image_bgr, cv::COLOR_YUV2BGR_NV12);
	cv::imshow("image bgr", image_bgr);
	cv::waitKey();

	// 保存转换图像
	fp = fopen("output/result.yuv", "wb");
	int image2_len = image2_w * image2_h * 3 / 2;
	fwrite(image_yuv2.data, image2_len, 1, fp);
	fclose(fp);

	// 读取转换图像
	fp = fopen("output/result.yuv", "rb");
	unsigned char *image2_buf = (unsigned char *)malloc(image_len);
	fread(image2_buf, image2_len, 1, fp);
	fclose(fp);

	// 显示转换图像
	cv::Mat image2_yuv(image2_h * 3 / 2, image2_w, CV_8UC1, image2_buf);
	cv::Mat image2_bgr;
	cv::cvtColor(image2_yuv, image2_bgr, cv::COLOR_YUV2BGR_NV12);
	cv::imshow("image2 bgr", image2_bgr);
	cv::waitKey();

	// 释放图像缓存
	free(image_buf);
	free(image2_buf);

	return 0;
}

 

 

参考地址:

https://www.shuzhiduo.com/A/Ae5Rw1W3dQ/

https://blog.51cto.com/u_12204415/3804362

https://blog.csdn.net/sinat_36684217/article/details/75117920

https://www.cnblogs.com/peifx/p/16360976.html

https://cloud.tencent.com/developer/article/2048327

https://blog.csdn.net/sadsfdsvf/article/details/124291194

https://blog.csdn.net/chengkeke366/article/details/119616735

https://blog.csdn.net/m0_37862025/article/details/100727652

https://blog.csdn.net/weixin_43817380/article/details/111578757

 

标签:缩放,int,image,yuv,OpenCV,image2,NV12,cv,分量
From: https://www.cnblogs.com/d442130165/p/17129477.html

相关文章

  • 图像处理之拼接---图像拼接opencv
    基于SURF特征的图像与视频拼接技术的研究和实现(一)   一直有计划研究实时图像拼接,但是直到最近拜读西电2013年张亚娟的《基于SURF特征的图像与视频拼接技术的研究和实......
  • element-ui的tree结构自定义节点点击是否可触发展开缩放
    近期公司项目,用element-ui的tree结构渲染一套数据,层级以两级或三级居多其中一级节点无实际意义,因此希望一级节点点击后正常展开缩放二级节点有实际意义,点击后,若下方有三......
  • qt+opencv读取视频
    #include"mainwindow.h"#include<QApplication>#include"opencv2/opencv.hpp"#include<iostream>#include<QDebug>usingnamespacecv;usingnamespacestd;in......
  • flask_socketio_rasip_video_stream_opencv
    E:\song\Flask-SocketIO-Chat-master\run.py#!/bin/envpythonfromappimportcreate_app,socketioapp=create_app(debug=False)if__name__=='__main__':......
  • 【OpenCV】-重映射
    文章目录​​1、重映射的概念​​​​2、实现重映射:remap()函数​​​​3、基本重映射​​​​4、实现多重映射​​1、重映射的概念重映射是把一幅图像中某位置的像素放置到......
  • 【OpenCV】-霍夫变换
    序言:什么是霍夫变换?在图像处理和计算机视觉邻域中,如何从当前的图像中提前所需要的特征信息是图像识别的关键所在。霍夫变换可以快速准确地检测出直线或者圆,在图像处理中识别......
  • 【OpenCV】-边缘检测汇总示例
    汇总之前:这一节还有一个scharr滤波器(也是算子)没有介绍,先介绍一下。。。1计算图像差分:Scharr()函数使用Scharr滤波器运算符计算x或y方向的图像差分,包含的参数与Sobel算子基......
  • 【OpenCV】-算子(Sobel、Canny、Laplacian)学习
    开头一下:本篇博客主要介绍边缘检测所涉及的三大算子,分别是Sobel算子、Canny算子、Laplacian算子)。上篇博客​​python版CV​​也介绍了这三个算子的用法。文章目录​​1、s......
  • pycharm配置opencv库
    我走的弯路:对于刚刚入手OpenCV的小白,又第一次接触pycharm编译器。所以在配置opencv库的时候遇到很多问题。如下:1、如果直接在Terminal运行界面输入【pipinstallopencv-p......
  • 【OpenCV】—阈值化
    什么是阈值化?答:在对各种图形进行处理操作的过程中,需要对图像中的像素做出取舍与决策,直接剔除一些低于或者高于一定值的像素。阈值可以被视作最简单的图像分割方法。如:从一......