版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oHanTanYanYing/article/details/81945479
最近做项目用到工业摄像头,其输出最小的数据流是Bayer8,因为带宽有限,只好选用之。
在获得数据后,解析成了比较要命的问题,因为ffmpeg等比较简单的工具没有该格式对其他格式的装换,因此只能自行实现。在这里万分感谢下面这个博客
https://blog.csdn.net/leng_que/article/details/5961436
本人基本上是按照该博客修改出了自己能用的版本(直接照抄会有些变量未定义的问题),下面也分享出来吧。
BayerToRGB.h
//原作者:Vojtech Pavlik
//2010-10-23 23:25:16 冷却 整理、封装以及测试
#pragma once
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#define u8 uint8_t
#define R(x,y) m_pRGB24[2 + 3 * ((x) + m_ulWidth * (y))]
#define G(x,y) m_pRGB24[1 + 3 * ((x) + m_ulWidth * (y))]
#define B(x,y) m_pRGB24[0 + 3 * ((x) + m_ulWidth * (y))]
#define Bay(x,y) m_pBay[(x) + m_ulWidth * (y)]
class BayerToRGB
{
public:
BayerToRGB();
public:
//函数名称:Bayer8ToRgb24
//描述:将8位Bayer原始数据转换为24位RGB格式数据
//注意:该函数不可重入
/*
* 要求的Bayer数据排列格式如下(GBRG):
*
* G B G B G B G B...
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
* ..................
* ..................
*/
static int Bayer8ToRgb24(unsigned char* pbBayer, int dwWidth, int dwHeight, unsigned char* pbRgb, int iRgbBufLen);
protected:
int ExecBayer8ToRgb24(unsigned char* pbBayer, int dwWidth, int dwHeight, unsigned char* pbRgb, int iRgbBufLen);
private:
unsigned long m_ulWidth;
unsigned long m_ulHeight;
u8 *m_pBay;
u8 *m_pRGB24;
private:
void bayer_copy(int x, int y);
void bayer_bilinear(int x, int y);
void bayer_to_rgb24();
};
BayerToRGB.cpp
#include "stdafx.h"
#include "BayerToRGB.h"
#pragma warning(disable: 4244)
#pragma warning(disable: 4018)
BayerToRGB::BayerToRGB()
{
m_ulWidth = 0;
m_ulHeight = 0;
m_pBay = NULL;
m_pRGB24 = NULL;
}
int BayerToRGB::Bayer8ToRgb24(unsigned char * pbBayer, int dwWidth, int dwHeight, unsigned char* pbRgb, int iRgbBufLen)
{
BayerToRGB cPixelFormatConvert;
return cPixelFormatConvert.ExecBayer8ToRgb24(pbBayer, dwWidth, dwHeight, pbRgb, iRgbBufLen);
return 0;
}
int BayerToRGB::ExecBayer8ToRgb24(unsigned char * pbBayer, int dwWidth, int dwHeight, unsigned char* pbRgb, int iRgbBufLen)
{
if (NULL == pbBayer || NULL == pbRgb)
{
return 0;
}
if (dwWidth <= 0 || dwHeight <= 0 || iRgbBufLen <= 0)
{
return 0;
}
if (iRgbBufLen != dwWidth * dwHeight * 3)
{
return 0;
}
m_pBay = pbBayer;
m_pRGB24 = pbRgb;
m_ulWidth = dwWidth;
m_ulHeight = dwHeight;
bayer_to_rgb24();
return 1;
}
void BayerToRGB::bayer_copy(int x, int y)
{
G(x + 0, y + 0) = Bay(x + 0, y + 0);
G(x + 1, y + 1) = Bay(x + 1, y + 1);
G(x + 0, y + 1) = G(x + 1, y + 0) = ((unsigned long)Bay(x + 0, y + 0) + (unsigned long)Bay(x + 1, y + 1)) / 2;
R(x + 0, y + 0) = R(x + 1, y + 0) = R(x + 1, y + 1) = R(x + 0, y + 1) = Bay(x + 0, y + 1);
B(x + 1, y + 1) = B(x + 0, y + 0) = B(x + 0, y + 1) = B(x + 1, y + 0) = Bay(x + 1, y + 0);
}
void BayerToRGB::bayer_bilinear(int x, int y)
{
R(x + 0, y + 0) = ((unsigned long)Bay(x + 0, y + 1) + (unsigned long)Bay(x + 0, y - 1)) / 2;
G(x + 0, y + 0) = Bay(x + 0, y + 0);
B(x + 0, y + 0) = ((unsigned long)Bay(x - 1, y + 0) + (unsigned long)Bay(x + 1, y + 0)) / 2;
R(x + 0, y + 1) = Bay(x + 0, y + 1);
G(x + 0, y + 1) = ((unsigned long)Bay(x + 0, y + 0) + (unsigned long)Bay(x + 0, y + 2) + (unsigned long)Bay(x - 1, y + 1) + (unsigned long)Bay(x + 1, y + 1)) / 4;
B(x + 0, y + 1) = ((unsigned long)Bay(x + 1, y + 0) + (unsigned long)Bay(x - 1, y + 0) + (unsigned long)Bay(x + 1, y + 2) + (unsigned long)Bay(x - 1, y + 2)) / 4;
R(x + 1, y + 0) = ((unsigned long)Bay(x + 0, y + 1) + (unsigned long)Bay(x + 2, y + 1) + (unsigned long)Bay(x + 0, y - 1) + (unsigned long)Bay(x + 2, y - 1)) / 4;
G(x + 1, y + 0) = ((unsigned long)Bay(x + 0, y + 0) + (unsigned long)Bay(x + 2, y + 0) + (unsigned long)Bay(x + 1, y - 1) + (unsigned long)Bay(x + 1, y + 1)) / 4;
B(x + 1, y + 0) = Bay(x + 1, y + 0);
R(x + 1, y + 1) = ((unsigned long)Bay(x + 0, y + 1) + (unsigned long)Bay(x + 2, y + 1)) / 2;
G(x + 1, y + 1) = Bay(x + 1, y + 1);
B(x + 1, y + 1) = ((unsigned long)Bay(x + 1, y + 0) + (unsigned long)Bay(x + 1, y + 2)) / 2;
}
void BayerToRGB::bayer_to_rgb24()
{
int i, j;
for (i = 0; i < m_ulWidth; i += 2)
{
for (j = 0; j < m_ulHeight; j += 2)
{
if (i == 0 || j == 0 || i == m_ulWidth - 2 || j == m_ulHeight - 2)
{
bayer_copy(i, j);
}
else
{
bayer_bilinear(i, j);
}
}
}
}
使用(需要注意本人从摄像头获取到的数据第一行是RGRG,所以做了相应的修改,也就是扔掉了第一行。。。):
#include "ffmpegDecode.hpp"
#include <opencv2/core/core.hpp>//OpenCV包含头文件
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include "BayerToRGB.h"
#define IMGLEN 691200
using namespace std;
using namespace cv;
char imgdata[IMGLEN];
void main()
{
FILE *PF;
fopen_s(&PF, "1.save", "rb");
fread(imgdata, 1, IMGLEN, PF);
fclose(PF);
Mat img(720, 960, CV_8UC3,Scalar(0,0,0));
//bayer8 转 RGB
/* 要求的Bayer数据排列格式如下(注意排列的不同):
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
* G B G B G B G B...
* R G R G R G R G...
*/
double t = (double)cvGetTickCount();
BayerToRGB::Bayer8ToRgb24((uchar*)(&imgdata[960]), 960,719, img.data, img.step*719);
cout << "花费时间" << ((double)cvGetTickCount() - t) / ((double)cvGetTickFrequency() * 1000) << "ms" << endl;
imshow("", img);
waitKey();
img.release();
}