V4L2读取摄像头YUYV(YUV420)帧后使用C语言转存为bmp格式

2023-05-16

  • 摄像头配置
  • 读取一帧YUV420(YUYV)
  • 保存为RGB24图像(BRG的顺序,bmp)
  • 下面是内存中摄像头读取的数据直接转存为RGB图片的源码。
  • 输入:图像指针地址,图像长度(两个参数都能由V4L2读取一帧的时候获得)
  • 下面是源码,读取一张yuyv的图之后转存为bmp(BGR24和灰度)
  • 注意,核心都是C语言实现的。opencv只是用来show检查转换是否正确。
  • 测试的yuyv的图片大小是640*480,它实际大小是640*480*2*8bit。而转为RGB24之后,占用的空间是640*480*3*8bit。BMP使用的是BGR的顺序。
  • yuyv的格式说明参见http://www.fourcc.org/yuv.php#YUYV

// tmp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// yuyv (yuy2) to RGB24(bgr顺序)
// test passed  
// ref http://www.fourcc.org/yuv.php#YUYV


#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib,"opencv_world430d.lib")

using namespace cv;
using namespace std;


void yuyv2bgr(unsigned char *p_yuyv, unsigned char * bgr_image, int size);//yuyv to bgr

void save_bmp_bgr(uchar * pdata, const char * bmp_file, int width, int height); // 24bit BGR24 save to bmp

void save_bmp_gray(unsigned char *inputImg, int width, int height, const char *outputFileName);// gray scale
// char 一行一行拉直 3byte或者1byte


int main()
{
	std::cout << "Hello World!\n";
	FILE *binaryf = fopen("H:\\0communicate\\my0630.yuyv", "rb");
	unsigned char* bytesFromBinary = new unsigned char[640 * 480 * 2];
	unsigned char* bgr_image = new unsigned char[640 * 480 * 3];

	fread(bytesFromBinary, 1, 640 * 480 * 2, binaryf);
	fclose(binaryf);
	yuyv2bgr(bytesFromBinary, bgr_image, 640 * 480 * 2);
	save_bmp_gray(bgr_image,640,480,"filename.bmp"); // 出错,需要输入灰度图
	const char * fn= "BGR.bmp";
	save_bmp_bgr(bgr_image, fn, 640, 480);


	delete[] bytesFromBinary;
	delete[] bgr_image;

}

//static unsigned char   *bgr_image;

void yuyv2bgr(unsigned char *p_yuyv, unsigned char * bgr_image, int size)
{

	int i;
	float y1, y2, u, v;
	unsigned char * bgr_p = bgr_image;
	unsigned char * p_tmp = (unsigned char *)p_yuyv;

	for (i = 0; i < size; i += 4)
	{

		y1 = p_tmp[i];
		u = p_tmp[i + 1];
		y2 = p_tmp[i + 2];
		v = p_tmp[i + 3];

		bgr_p[0] = (y1 + 1.371*(u - 128.0));
		bgr_p[1] = (y1 - 0.698*(u - 128.0) - 0.336*(v - 128.0));
		bgr_p[2] = (y1 + 1.732*(v - 128.0));
		// 如果要灰度图,在此处处理 要更改rgb顺序,在此处修改
		bgr_p[3] = (y2 + 1.371*(v - 128.0));
		bgr_p[4] = (y2 - 0.698*(v - 128.0) - 0.336*(u - 128.0));
		bgr_p[5] = (y2 + 1.732*(u - 128.0));
		// 合到一起用para for todo 2020年7月1日
		bgr_p += 6;
	}
	int row = 480;
	int col = 640;
	Mat im = Mat(row, col, CV_8UC3, bgr_image);
	imshow("BGR", im);
	imwrite("byopencv.jpg", im);
	if (im.isContinuous())
	{
		cout << im.channels()<<endl;
		const char *fname = "bmp2.bmp";
		save_bmp_bgr(im.data, fname,640,480 );// 
	}
	else
		cout << "Not Continuous" << endl;
	//cvtColor(im, im, COLOR_BGR2RGB);
	cvtColor(im, im, COLOR_BGR2GRAY);
	if (im.isContinuous())
	{
		cout << im.channels();
		save_bmp_gray(im.data, 640, 480, "bmp1.bmp");// 正确
		/*const char *fname = "bmp3.bmp";
		save_bmp_bgr(im.data, fname, 640, 480);*/
	}
	waitKey(0);
}


void write_bmpheader(unsigned char *bitmap, int offset, int bytes, int value)
{
	int i;
	for (i = 0; i < bytes; i++)
		bitmap[offset + i] = (value >> (i << 3)) & 0xFF;
}

unsigned char *convertToBmp(unsigned char *inputImg, int width, int height, int *ouputSize)
{
	/*create a bmp format file*/
	int bitmap_x = (int)ceil((float)width * 3 / 4) * 4;
	unsigned char *bitmap = (unsigned char*)malloc(sizeof(unsigned char)*height*bitmap_x + 54);

	bitmap[0] = 'B';
	bitmap[1] = 'M';
	write_bmpheader(bitmap, 2, 4, height*bitmap_x + 54); //whole file size
	write_bmpheader(bitmap, 0xA, 4, 54); //offset before bitmap raw data
	write_bmpheader(bitmap, 0xE, 4, 40); //length of bitmap info header
	write_bmpheader(bitmap, 0x12, 4, width); //width
	write_bmpheader(bitmap, 0x16, 4, height); //height
	write_bmpheader(bitmap, 0x1A, 2, 1);//biPlanes
	write_bmpheader(bitmap, 0x1C, 2, 24); //bit per pixel 24
	write_bmpheader(bitmap, 0x1E, 4, 0); //compression
	write_bmpheader(bitmap, 0x22, 4, height*bitmap_x); //size of bitmap raw data
	for (int i = 0x26; i < 0x36; i++)//0x36 54 //0x26 38
		bitmap[i] = 0;

	int k = 54;
	for (int i = height - 1; i >= 0; i--) 
	{
		int j;
		for (j = 0; j < width; j++) 
		{
			int index = i * width + j;//index 只到了width*height-1 so 只能保存灰度图。如果要彩色的,直接将imgdatacopy到bitmap中就行
			// 如果只是保存灰度图,那么bit per pixel 24写成8就行。说明比特数/像素数,值有1、2、4、8、16、24、32;
			for (int l = 0; l < 3; l++)
			{ 
				bitmap[k++] = inputImg[index];
			}
		}
		j *= 3;
		while (j < bitmap_x) //width*3
		{
			bitmap[k++] = 0;
			j++;
		}
	}

	*ouputSize = k;
	return bitmap;
}

void save_bmp_gray(unsigned char *inputImg, int width, int height, const char *outputFileName)
{
	int size;
	unsigned char *bmp = convertToBmp(inputImg, width, height, &size);
	FILE *fp = fopen(outputFileName, "wb+");
	if (fp == NULL)
	{
		printf("Could not open file.\n");
	}
	fwrite(bmp, 1, size, fp);
	fclose(fp);
	free(bmp);
}
//--------------------

typedef long LONG;//4
typedef unsigned int DWORD;//4
typedef unsigned short WORD;//2

typedef struct {
	WORD    bfType;
	DWORD   bfSize;
	WORD    bfReserved1;
	WORD    bfReserved2;
	DWORD   bfOffBits;
} BMPFILEHEADER_T; // sizeof  = 16 注意了,此处有坑。

typedef struct {
	DWORD      biSize;
	LONG       biWidth;
	LONG       biHeight;
	WORD       biPlanes;
	WORD       biBitCount;
	DWORD      biCompression;
	DWORD      biSizeImage;
	// 接下来的填0可以
	LONG       biXPelsPerMeter;
	LONG       biYPelsPerMeter;
	//biClrUsed:说明位图使用的调色板中的颜色索引数,为0说明使用所有;
	//	biClrImportant:说明对图像显示有重要影响的颜色索引数,为0说明都重要;
	DWORD      biClrUsed;
	DWORD      biClrImportant;
} BMPINFOHEADER_T;

void save_bmp_bgr(uchar * pdata, const char * bmp_file, int width, int height)
{      //分别为rgb数据,要保存的bmp文件名,图片长宽 无调色板
	int size = width * height * 3 * sizeof(char); // 每个像素点3个字节
	// 位图第一部分,文件信息
	BMPFILEHEADER_T bfh;
	bfh.bfType = (WORD)0x4d42;  //bm unsigned short bfType=0x4d42;  
	bfh.bfSize = size  // data size
		+ sizeof(BMPFILEHEADER_T) // first section size
		+ sizeof(BMPINFOHEADER_T) // second section size
		;
	bfh.bfReserved1 = 0; // reserved
	bfh.bfReserved2 = 0; // reserved
	//bfh.bfOffBits = sizeof(BMPFILEHEADER_T) + sizeof(BMPINFOHEADER_T);//真正的数据的位置 注意了,此处有坑 2020年7月1日
	bfh.bfOffBits = 54;// 14 + 40, 前一行的结论是56

	// 位图第二部分,数据信息
	BMPINFOHEADER_T bih;
	bih.biSize = sizeof(BMPINFOHEADER_T); //biSize:4字节,信息头的大小,即40;
	bih.biWidth = width; //biWidth:4字节,以像素为单位说明图像的宽度;
	bih.biHeight = -height;//BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了
	bih.biPlanes = 1;//为1,不用改
	bih.biBitCount = 24;// 24位一个像素
	bih.biCompression = 0;//不压缩
	bih.biSizeImage = size;//图像数据的byte个数
	bih.biXPelsPerMeter = 2835;//像素每米
	bih.biYPelsPerMeter = 2835;//像素每米
	bih.biClrUsed = 0;//已用过的颜色,24位的为0
	bih.biClrImportant = 0;//每个像素都重要
	FILE * fp = fopen(bmp_file, "wb");
	if (!fp) return;

	//fwrite(&bfh, 8, 1, fp);//由于linux上4字节对齐,而信息头大小为54字节,第一部分14字节,第二部分40字节,所以会将第一部分补齐为16字节,直接用sizeof,打开图片时就会遇到premature end-of-file encountered错误
	//fwrite(&bfh.bfReserved2, sizeof(bfh.bfReserved2), 1, fp);
	//fwrite(&bfh.bfOffBits, sizeof(bfh.bfOffBits), 1, fp);
	cout << sizeof(LONG) << endl;//4
	cout << sizeof(WORD) << endl;//2
	cout << sizeof(DWORD) << endl;//4

	cout << sizeof(BMPFILEHEADER_T) << endl;//16
	cout << sizeof(BMPINFOHEADER_T) << endl;//40

	fwrite(&bfh, 8, 1, fp);//由于linux上4字节对齐,而信息头大小为54字节,第一部分14字节,第二部分40字节,所以会将第一部分补齐为16直接,直接用sizeof,打开图片时就会遇到premature end-of-file encountered错误
	fwrite(&bfh.bfReserved2, sizeof(bfh.bfReserved2), 1, fp); //2
	fwrite(&bfh.bfOffBits, sizeof(bfh.bfOffBits), 1, fp); //4
	fwrite(&bih, sizeof(BMPINFOHEADER_T), 1, fp); //40
 

	fwrite(pdata, size, 1, fp);
	fclose(fp);
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

V4L2读取摄像头YUYV(YUV420)帧后使用C语言转存为bmp格式 的相关文章

  • 《cmake调用shell》

    1 CMakeLists txt add custom target config ALL COMMAND bash x sh 2 shell File Name x sh Author XXDK Created Time Wed 01 N
  • Ardupilot之cpu外设基础抽象聚合类 HAL.h

    libraries AP HAL HAL h 定义了所有外设的基础抽象类集合 一个 HAL 抽象类世界 xff0c 由 HAL 层的cpu外设的抽象类基础组件组聚而成 xff1b 也就是一个 HAL 派生类子对象 代表了一个 cpu 的所有
  • 一次Ajax报错:“存储空间不足,无法完成此操作”的解决经验

    连续几天我们收到几位客户的问题工单 xff0c 问题描述都类似 xff0c 都是在做登陆或者交易时报脚本错误 xff0c 交易无法正常执行 我们 远程协助 客户机器时 xff0c 调试发现都是ajax代码出错 xff0c 错误如下 xff1
  • Java异常的另类用法(一)

    异常在我们的代码中是不可避免的 xff0c 有些异常可以忽略 xff0c 多数的异常我们要显式处理 xff08 至少要记录日志 xff0c 以便后面排查问题 xff09 xff0c 这里我们不是要细说异常的处理规范 xff0c 而是使用异常
  • 使用POI在Excel单元格插入符号(Symbol)

    最近看到有人在 技术问答 上提问怎么用java在excel中插入打勾符号 xff1f 我想解决这个问题并不难 我们先打开一个excel文件 xff0c 在里面插入特定符号 xff0c 然后用poi xff08 其他的技术也可以 xff09
  • Eclipse下C语言的Socket编程(Winsock,gcc)问题总结

    最近心血来潮想从新温习一下C语言 xff08 工作后一直用Java xff0c 其实大学时C语言课程也没好好上 xff0c 正经的代码基本没写过 xff0c 惭愧啊 xff01 xff09 xff0c 找了些小例子 xff0c 修修改改 x
  • 各种哈希函数的java实现

    收集整理 public class HashUtils br private static final int crctab 61 0x00000000 0x77073096 0xee0e612c 0x990951ba br 0x076dc
  • libssl.so.10缺失库文件的解决办法

    libssl so 10缺失库文件的解决办法 在RHEL6 5中对openssl进行了升级 xff0c 如果老版本是OpenSSL 1 0 1e fips 那直接安装最新的openssl 1 0 1g 1 x86 64 rpm就行了 xff
  • Nvidia Jetson Nano入门与使用

    Pre xff1a Nvidia Nano板等了好久 xff0c 国内终于便宜了一点 刚从网上买一个 xff0c 准备替换掉Nvidia TX2开发板 xff08 因为目前的算法在Nano开发板上跑应该没有问题 xff09 打开包装 xff
  • 算法之路(四)----汉诺塔(又称河内之塔)

    汉诺塔是很简单也很经典的算法之一 汉诺塔是根据一个传说形成的数学问题 xff1a 有三根杆子A xff0c B xff0c C A杆上有N个 N gt 1 穿孔圆盘 xff0c 盘的尺寸由下到上依次变小 要求按下列规则将所有圆盘移至C杆 x
  • 相位一致性——利用频域检测边缘

    相位一致性 利用频域检测边缘 一 相位一致性提出的背景 相位一致性的提出是基于科学家发现了人感觉图像的关键不在于图像的长度差或者高度差之类的因素 xff0c 关键在于图像信号的相位大小 xff0c 例如人知道一个方波的边缘 xff0c 并不
  • 图像分割——掩膜法

    电路板是用掩膜法制作而成的 xff0c 现在电路板表面涂上一层抗腐蚀的材料 xff0c 然后再进行处理 xff0c 最后洗去材料就得到了电路 掩膜法在图像处理中的应用 xff1a 可用于分割图像中的特定部分 xff0c 关键在于怎么取膜 例
  • C++ 值传递、指针传递、引用传递详解

    具体内容源自 xff1a http www cnblogs com yanlingyin archive 2011 12 07 2278961 html 以下是简介 xff1a 值传递 xff1a 形参是实参的拷贝 xff0c 改变形参的值
  • MATLAB: 读取同一目录下的所有文件名并按时间排序

    用MATLAB测试图像处理算法的过程中 通常需要读入一个目录下的多张测试图片 可以根据文件命名规则来读入某个特定目录下的所有文件 但是相对比较麻烦 通过利用MATLAB自带的dir 可以先读入所有的文件名字 知道文件数量 而且不用知道文件的
  • 相机模型(Camera Model)

    Perspective Camera Model Perspective Camera Model 或 Pinhole Camera Model都是简单但是应用广泛的模型 xff0c 描述了将物体从3D世界坐标系转换 xff08 World
  • Solid Compression

    定义 Solid Compression是一种多文件的数据压缩方式 xff0c 其中所有未被压缩的文件是一个整体 xff0c 视为一个独立的data block 这样的文件称为solid archive 7z RAR压缩格式和tar bas
  • 区分AR、VR、MR、CR

    终极扫盲贴 xff1a VR AR MR CR到底如何区分 xff1f
  • (2016/02/19)多传感器数据融合算法---9轴惯性传感器

    2016年2月18日 传感器的原理 加速度计 xff1a 加速度计 我们可以把它想作一个圆球在一个方盒子中 假定这个盒子不在重力场中或者其他任何会影响球的位置的场中 xff0c 球处于盒子的正中央 你可以想象盒子在外太空中 xff0c 或远
  • 【tx2】——NVIDIA TX2--3--NVIDIA Jetson TX2 查看系统版本参数状态及重要指令

    NVIDIA Jetson TX2 查看系统参数状态 当前博主的TX2更新的版本为 xff1a Jetpack 3 3 cuda 9 0 252 cudnn7 0 opencv3 3 1 TensorRT4 0 2 系统内核 xff1a t
  • 训练深度学习模型时电脑自动重启

    文章目录 问题可能原因解决方案 问题 前面用自己的台式机利用GPU训练模型的时候 xff0c 电脑老是自动重启 xff0c 当时试了各种方法 xff0c 找了各种原因 电脑配置 电脑买的是二手的 xff0c xff08 强烈建议买新的 xf

随机推荐

  • 华为机试题[2017.8.23]

    题目 xff1a 给定一个正整数 xff0c 给出消除重复数字以后最大的整数 输入描述 xff1a 正整数 xff0c 注意考虑长整数 输出描述 xff1a 消除重复数字以后的最大整数 下面的好像有问题 xff0c 当输入是4325432时
  • Kubernetes(k8s)中dashboard的汉化

    1 访问服务器的http 192 168 110 133 8080 ui地址 xff0c 如下所示 xff1a 使用dashboard版本registry cn hangzhou aliyuncs com google containers
  • docker + Rancher + guacamole 容器环境搭建并配置vnc连接

    Rancher 43 guacamole 容器环境搭建 准备环境 xff1a docker ce 17 01 43 43 centos7 x 43 guacamole 最新版0 9 14 43 Rancher 搭建完成效果 xff1a 1
  • C语言习题(1)——字符串拷贝,去空格,奇偶抽取字符串

    1 字符串拷贝 作者 xff1a 一叶扁舟 作用 xff1a 字符串的拷贝 时间 xff1a 18 25 2017 5 1 include lt stdio h gt include lt string h gt include lt st
  • 基于安卓平台的滤镜功能相机

    1 1需求背景 爱美之心 xff0c 人皆有之 我们拍照是为了留住一个美好的瞬间 Android自带的相机拍照效果满足不了人们的爱美心理 xff0c 而且比较单一 xff1b 因此为了解决这个问题我们研 发 滤镜功能相机 滤镜功能相机主要基
  • 威廉·巴特勒·叶芝:“我们是最后的浪漫主义者”

    喜欢叶芝是一件很文艺的事情 叶芝的诗滋润了无数少男少女的情怀 在叶芝被茅德 冈 嫌弃的这一生中 我们不知道他是否曾经后悔 我感动了全世界 却感动不了你 但至少 他的诗 感动了后世无数人 题记 多少人曾爱你青春欢畅的时辰 爱慕你的美丽 假意或
  • Javassist即时编译技术,热修复核心与原理

    Java 字节码以二进制的形式存储在 class 文件中 xff0c 每一个 class 文件包含一个Java类或接口 Javaassist 框架就是一个用来处理 Java 字节码的类库 它可以在一个已经编译好的类中添加新的方法 xff0c
  • ubuntu系统编译安装

    Ubuntu程序安装是个很好理解的 xff0c 这里我发表一下个人理解 xff0c 下面就这就来讲术Ubuntu编译安装 Ubuntu编译程序新手指导Ubuntu 团队对它的使用者公开的承诺 Ubuntu 永远免费 并且对于 34 企业版本
  • Android Launcher浅析(一)

    Launcher桌面的一大功能就是支持左右滑动 xff0c 这样的功能在现在的应用中使用非常广泛 xff0c 并且有很多实现的方式 xff0c 可以通过使用Fragment来实现也可以通过自定义的控件来实现 Launcher采用了后者 xf
  • Android OTA升级

    1 xff0c Build otapackage后system img没有打包进去 xff1f Ota包里面缺失system img xff0c 原因是客户修改了prop里面的 ro product device value值 尝试以下两种
  • Android Launcher浅析(三)

    Launcher是系统启动后第一个启动的程序 是其它应用程序的入口 也就是我们的手机程序的桌面程序 一 Launcher的定义及构成 xff1a lt 1 gt 通过查看官方提供的Launcher源码可以知道其实Launcher也是一个Ac
  • 在Java中,return null 是否安全, 为什么?

    Java代码中return value 为null 是不是在任何情况下都可以 xff0c 为什么不会throw NullPointerException Java语言层面 xff1a null值自身是不会引起任何问题的 它安安静静的待在某个
  • 有一个文科女友是一场怎样的体验?

    1 我是一枚标准的工科男 xff0c 毕业后变成了加班狗程序猿 xff0c 我的女朋友是一枚标准的文科妹子 xff0c 这里姑且叫她miss梁吧 xff0c 我觉得以她的智商来看 xff0c 她应该是单细胞动物 xff0c 但是不知道她是怎
  • activity的startActivity和context的startActivity区别

    我们以 startActivity Intent 这个最常用的 api 来讲 1 首先 xff0c Context 类有一个 abstract 方法 Same as 64 link startActivity Intent Bundle w
  • android平台下移动DM接入流程?

    中国移动拟建设终端管理与服务系统 通过对终端产品的激活 配置使用等信息的收集 结合终端公司对产品的供应链管理 实现产品全生命周期的掌控 要求2017年3月起 所有入中国移动产品库的定制 非定制Android终端均要支持终端管理功能 必选要求
  • C++经典面试题(九)

    最近看一些面试题 xff0c 觉得如果自己被问到了 xff0c 并不能很利落的回答出来 一是从来没有这个意识 xff0c 二是没有认真的梳理下 下面对这些题做出分析 xff0c 哈 xff01 个人能力有限 xff0c 其中难免有疏漏 xf
  • 我的大学——学习生活总结

    纪念我终将逝去的青春 大一上學期 專業 1 C語言K amp R amp amp 習題 2 C語言經典習題 3 C語言趣味習題 4 C陷阱与缺陷 5 彙編語言 6 C 43 43 程序設計 7 C 程序設計
  • latex论文作图(python+matplotlib)

    20210425 0 引言 论文中进行作图 xff0c 需要对图片中的各种元素进行控制 xff0c 最近在论文写作过程中为了能够得到匹配文章的高质量图片 xff0c 也是花了很多心血 除了对图片中的风格进行控制 xff0c 另一方面比较重要
  • SAP结转方法:表结法、帐结法

    SAP 处理会计期间结帐方法主要有两种方法 xff1a 表结法和帐结法 国内在会计期末结帐大都采用 帐结 的方法 xff0c 而 SAP 一般都是采用 表 结 xff0c 通过财务报表的编制来披露当期利润 xff0c 即 xff1a 销售科
  • V4L2读取摄像头YUYV(YUV420)帧后使用C语言转存为bmp格式

    摄像头配置读取一帧YUV420 xff08 YUYV xff09 保存为RGB24图像 BRG的顺序 xff0c bmp 下面是内存中摄像头读取的数据直接转存为RGB图片的源码 输入 xff1a 图像指针地址 xff0c 图像长度 xff0