任务目标:将CIF视频文件进行红色通道提取。//任务出错,后面详解
(一)C++文件读取
打开二进制文件用binary方式。
以读取CIF文件为例,以下先不对其进行操作,也不深究CIF文件的存储格式。
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream iofile("D:\\0CUC\\digital_video\\miss.cif",ios::binary);//读入文件
if (!iofile)
{
cout << "error!" << endl;
exit(1);
}
//计算文件大小
int m, n;
iofile.seekg(0, ios::beg);
m = iofile.tellg();
iofile.seekg(0, ios::end);
n = iofile.tellg();
int size = n - m;
//返回文件首部
iofile.seekg(0, ios::beg);
char* infile = new char[size];
char* outfile = new char[size];
//文件读取复制
iofile.read(infile, size);
for (int i = 0; i < size; i++)
{
outfile[i] = infile[i];
}
//输出文件
ofstream iofile_2("D:\\0CUC\\digital_video\\miss_new.cif", ios::binary);
iofile_2.write(outfile, size);
iofile_2.close();
return 0;
}
经检验,成功将文件读入并且将复制本写出。
(二)CIF文件
CIF文件按照二进制存储,因而对其的读取与操作与对二进制文件的读取及操作一致。
CIF的文件存储格式
YUVY(4:2:2):
Y
0
C
b
0
Y
1
C
r
0
Y
2
C
b
1
Y
3
C
r
1
⋯
Y_0C_{b0}Y_1C_{r0}Y_2C_{b1}Y_3C_{r1}\cdots
Y0Cb0Y1Cr0Y2Cb1Y3Cr1⋯
UYVY(4:2:2):
C
b
0
Y
0
C
r
0
Y
1
C
b
1
Y
2
C
r
1
Y
3
⋯
C_{b0}Y_0C_{r0}Y_1C_{b1}Y_2C_{r1}Y_3\cdots
Cb0Y0Cr0Y1Cb1Y2Cr1Y3⋯
YUV422P(4:2:2),YV12,YU12(4:2:0):先存储完所有
Y
Y
Y,再存储完所有
C
b
C_b
Cb,再存储所有
C
r
C_r
Cr
NV12,NV21(4:2:0):先存储完所有
Y
Y
Y,之后
C
b
x
C
b
x
+
1
C
r
x
C
r
x
+
1
C_{b_x}C_{b_{x+1}}C_{r_x}C_{r_{x+1}}
CbxCbx+1CrxCrx+1的结构交替出现。
每个像素点用一个字节存储信息
YUV和RGB之间的转换关系
Y = 0.257 R + 0.504 G + 0.098 B + 16 C r = V = 0.439 R − 0.368 G − 0.071 B + 128 C b = − 0.418 R − 0.291 G + 0.439 B + 128 B = 1.164 ( Y − 16 ) + 2.018 ( U − 128 ) G = 1.164 ( Y − 16 ) − 0.813 ( V − 128 ) − 0.391 ( U − 128 ) R = 1.164 ( Y − 16 ) + 1.596 ( V − 128 ) \begin{aligned}&Y=0.257R+0.504G+0.098B+16\\ &C_r=V=0.439R-0.368G-0.071B+128\\ &C_b=-0.418R-0.291G+0.439B+128\\ &B=1.164(Y-16)+2.018(U-128)\\ &G=1.164(Y-16)-0.813(V-128)-0.391(U-128)\\ &R=1.164(Y-16)+1.596(V-128)\end{aligned} Y=0.257R+0.504G+0.098B+16Cr=V=0.439R−0.368G−0.071B+128Cb=−0.418R−0.291G+0.439B+128B=1.164(Y−16)+2.018(U−128)G=1.164(Y−16)−0.813(V−128)−0.391(U−128)R=1.164(Y−16)+1.596(V−128)
任务出错原因
因为使用的CIF文件采用的是4:2:0的采样格式,得到的
Y
,
C
b
,
C
r
Y,C_b,C_r
Y,Cb,Cr没有办法一一对应,所以无法实现单纯的
R
,
G
,
B
R,G,B
R,G,B通道提取。
图片来自数字视频分量编码4:2:2、4:1:1和4:2:0取样格式简介
参考文章
[1]使用c++处理YUV文件
[2]C/C++读写文本文件、二进制文件
[3]C++二进制(写入,读取)
[4]YUV与RGB格式转换