Bayer8转RGB并用OpenCV显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 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();
}

猜你喜欢

转载自blog.csdn.net/oHanTanYanYing/article/details/81945479