Machine Vision 8bit Bayer RGGB to RGB in Open CV - c++

I am currently trying to convert an 8bit Raw color image to 8 bit RGB.
i get a channel error it expect the Bayer to be 1 channel.
i am using the following code.
if (convertBayerChckBox->Checked)
{
try{
cv::Mat temp(imgOriginal.rows, imgOriginal.cols, CV_8UC3);
imgOriginal.copyTo(temp);
cv::cvtColor(temp, imgOriginal, CV_BayerRG2BGR);
}
catch (const cv::Exception& ex)
{
std::cout << "EXCEPTION: " << ex.what() << std::endl;
errLog << "EXCEPTION: " << ex.what() << std::endl;
}
}
then i am getting the following exception:
EXCEPTION: ......\modules\imgproc\src\color.cpp:4194: error: (-215) scn == 1 && dcn == 3 in function cv::cvtColor
I am not sure how else to convert from Bayer to RGB

You need to set the data pointer of your input Mat to your destination pointer.
Here is a sample program to convert your bayer image to RGB. Here I've used buffer from a file. You can use your camera frame buffer. Hope this helps!
Mat mSource_Bayer(Size(m_IWidth,m_IHeight),CV_8UC1);
Mat mSource_Bgr(Size(m_IWidth,m_IHeight),CV_8UC3);
FILE *fp = NULL;
uchar *imagedata = NULL;
int framesize = m_IWidth * m_IHeight;
//Open raw Bayer image.
fp = fopen(FileName_S.c_str(), "rb");
//Memory allocation for bayer image data buffer.
imagedata = (uchar*) malloc (sizeof(uchar ) * framesize);
//Read image data and store in buffer.
fread(imagedata, sizeof(uchar ), framesize, fp);
mSource_Bayer.data= imagedata;
fclose(fp);
int Selection= m_BayerFormat.GetCurSel();
if(Selection==0)
cvtColor(mSource_Bayer, mSource_Bgr, CV_BayerBG2BGR);//Perform demosaicing process
else if(Selection==1)
cvtColor(mSource_Bayer, mSource_Bgr, CV_BayerGB2BGR);//Perform demosaicing process
else if(Selection==2)
cvtColor(mSource_Bayer, mSource_Bgr, CV_BayerRG2BGR);//Perform demosaicing process
else if(Selection==3)
cvtColor(mSource_Bayer, mSource_Bgr, CV_BayerGR2BGR);//Perform demosaicing process
imshow("mSource_Bgr",mSource_Bgr);

Also in order to perform BAYER to RGB conversion I would recommend to use function SimdBayerToBgr from Simd Library. It seems that it function is faster than its analogue from OpenCV (it uses AVX2 and AVX-512).

Related

converting from unsigned char to uchar4

i'm learning CUDA and i came across a course that is helping even though the code is very old and i'm having problems running it i'm trying to understand it, so he reads images using openCV imread which gives a Mat obj i guess but the data is saved as a uchar*
cv::Mat image = cv::imread(filename.c_str(), CV_LOAD_IMAGE_COLOR);
but after i was stuck in converting uchar to uchar4 and i was reading the code from the teacher and he wrote .
cv::Mat image = cv::imread(filename.c_str(), CV_LOAD_IMAGE_COLOR);
if (image.empty()) {
std::cerr << "Couldn't open file: " << filename << std::endl;
exit(1);
}
cv::cvtColor(image, imageInputRGBA, CV_BGR2RGBA);
//allocate memory for the output
imageOutputRGBA.create(image.rows, image.cols, CV_8UC4);
//This shouldn't ever happen given the way the images are created
//at least based upon my limited understanding of OpenCV, but better to check
if (!imageInputRGBA.isContinuous() || !imageOutputRGBA.isContinuous()) {
std::cerr << "Images aren't continuous!! Exiting." << std::endl;
exit(1);
}
*h_inputImageRGBA = (uchar4 *)imageInputRGBA.ptr<unsigned char>(0);
*h_outputImageRGBA = (uchar4 *)imageOutputRGBA.ptr<unsigned char>(0);
are the two last lines the ones where he subtly converts from uchar to uchar4 ...
h_inputImageRGBA
h_outputImageRGBA
are both uchar4**
can somebody help me understand the code
here is the link to the source
function name : Preprocess

OpenCv 3.3 Cuda Medianfilter generates 2/3 of image black

I'm trying to use the cv::cuda::createMedianfilter function in OpenCV library.
This simple code produces an image which is 2/3 black, and only 1/3 is filtered.
using namespace cv;
int main(int argc, char** argv)
{
Mat src; Mat dst;
src = imread("test.bmp", 1);
cuda::GpuMat imageGpu(src),imageGpuOut;
cuda::Stream stream;
try
{
Ptr<cuda::Filter> filterX = cuda::createMedianFilter(CV_8UC1, 31);
filterX->apply(imageGpu, imageGpuOut,stream);
imageGpuOut.download(dst,stream);
stream.waitForCompletion();
imwrite("test_cuda31.bmp", dst);
}
catch (cv::Exception& e)
{
const char* err_msg = e.what();
std::cout << "exception caught: " << err_msg << std::endl;
}
}
Input image looks like this :Input image
Output image looks like this :Output image
I have tried several other images with different sizes and also different kernal sizes on the medianfilter. All with the same result.
Any ideas on what I'm doing wrong ?
You are loading an image of 3 channels (BGR)
src = imread("test.bmp", 1);
then, you are using as if the source was only 1 channel
Ptr<cuda::Filter> filterX = cuda::createMedianFilter(CV_8UC1, 31);
then it will process only 1/3 of the pixels, and probably the image is initialized in all 0, thus the black pixels in the rest of the image.
Sadly, cuda::createMedianFilter only supports CV_8UC1, so it is not possible to change that, but you can load the image as an CV_8UC1
src = imread("test.bmp", 0);
or convert it to greyscale after the load.
I hope this solves your problem

OpenCV cvtColor image truncated

I am using cvtColor to convert an image from YUYV format to RGB24. The output is fine as far as color is concerned but half of the image is cut. The image is 640x480 YUYV image buffer without any headers. I am using the following code:
FILE* fd = fopen("imgdump", "r+b");
char buffer[640*480*2]; // Each pixel takes two bytes in YUYV
if (fd != NULL)
{
fread(buffer, sizeof(char), 640*480*2, fd);
fclose(fd);
}
Mat s_sImageMat = Mat(640, 480, CV_8UC2);
Mat s_sConvertedImageMat;
cout << "before conversion\n";
s_sImageMat.data = (uchar*) buffer;
cvtColor(s_sImageMat, s_sConvertedImageMat, CV_YUV2RGB_YUYV);
cout << "after conversion\n";
FILE* fw = fopen("converted", "w+b");
if (fw != NULL)
{
fwrite((char*)s_sConvertedImageMat.data, sizeof(char), 640*480*2, fw);
fclose(fw);
}
Original file: https://drive.google.com/file/d/0B0YG1rjiNkBUQ0ZuaWN6Y1E2LUU/view?usp=sharing
Additional info: I am using opencv 3.2
The issue seems to be in the following line :
fwrite((char*)s_sConvertedImageMat.data, sizeof(char), 640*480*2, fw);
For RGB24, it should be be :
fwrite((char*)s_sConvertedImageMat.data, sizeof(char), 640*480*3, fw);
Each pixel is 3 bytes in RGB24

When does imwrite() fails

Does imwrite fails when the pixel values are of type CV_32FC1. I am trying to write an image in a jpg file but this is not working-:
make_response_mat(hr_lrt,response);
if (!response.data) // Checks input
{
cout << "Could not open or find the image" << std::endl;
return -1;
}
while (!imwrite("response.jpg", response))
{
cout << "Hari" << response.size() << "\n" << response.at<float>(456954, 4);
}
Here response has the pixel value of type float.
Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order). You can use Mat::convertTo to convert the image data type.
e.g.
Mat res;
response.convertTo(res, CV_8UC*)
* refer to image channel(1, 2, 3)

OpenCV2.1, map function? accessing each pixel?

I have a function that I would like to apply to each pixel in a YUN image (call it src). I would like the output to be saved to a separate image, call it (dst).
I know I can achieve this through pointer arithmetic and accessing the underlying matrix of the image. I was wondering if there was a easier way, say a predefined "map" function that allows me to map a function to all the pixels?
Thanks,
Since I don't know what a YUN image is, I'll assume you know how to convert RGB to that format.
I'm not aware of an easy way to do the map function you mentioned. Anyway, OpenCV has a few predefined functions to do image conversion, including
cvCvtColor(color_frame, gray_frame, CV_BGR2GRAY);
which you might want to take a closer look.
If you would like to do your own, you would need to access each pixel of the image individually, and this code shows you how to do it (the code below skips all kinds of error and return checks for the sake of simplicity):
// Loading src image
IplImage* src_img = cvLoadImage("input.png", CV_LOAD_IMAGE_UNCHANGED);
int width = src_img->width;
int height = src_img->height;
int bpp = src_img->nChannels;
// Temporary buffer to save the modified image
char* buff = new char[width * height * bpp];
// Loop to iterate over each pixel of the original img
for (int i=0; i < width*height*bpp; i+=bpp)
{
/* Perform pixel operation inside this loop */
if (!(i % (width*bpp))) // printing empty line for better readability
std::cout << std::endl;
std::cout << std::dec << "R:" << (int) src_img->imageData[i] <<
" G:" << (int) src_img->imageData[i+1] <<
" B:" << (int) src_img->imageData[i+2] << " ";
/* Let's say you wanted to do a lazy grayscale conversion */
char gray = (src_img->imageData[i] + src_img->imageData[i+1] + src_img->imageData[i+2]) / 3;
buff[i] = gray;
buff[i+1] = gray;
buff[i+2] = gray;
}
IplImage* dst_img = cvCreateImage(cvSize(width, height), src_img->depth, bpp);
dst_img->imageData = buff;
if (!cvSaveImage("output.png", dst_img))
{
std::cout << "ERROR: Failed cvSaveImage" << std::endl;
}
Basically, the code loads a RGB image from the hard disk and performs a grayscale conversion on each pixel of the image, saving it to a temporary buffer. Later, it will create another IplImage with the grayscale data and then it will save it to a file on the disk.