Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What algorithm does OpenCV's Bayer conversion use?

Tags:

c++

c

opencv

cuda

gpu

I would like to implement a GPU Bayer to RGB image conversion algorithm, and I was wondering what algorithm the OpenCV cvtColor function uses. Looking at the source I see what appears to be a variable number of gradients algorithm and a basic algorithm that could maybe be bilinear interpolation? Does anyone have experience with this that they could share with me, or perhaps know of GPU code to convert from Bayer to BGR format?

The source code is in imgproc/src/color.cpp. I'm looking for a link to it. Bayer2RGB_ and Bayer2RGB_VNG_8u are the functions I'm looking at.

Edit: Here's a link to the source.

http://code.opencv.org/projects/opencv/repository/revisions/master/entry/modules/imgproc/src/color.cpp

I've already implemented a bilinear interpolation algorithm, but it doesn't seem to work very well for my purposes. The picture looks ok, but I want to compute HOG features from it and in that respect it doesn't seem like a good fit.

like image 447
Ian Avatar asked Aug 09 '12 19:08

Ian


2 Answers

Default is 4way linear interpolation or variable number of gradients if you specify the VNG version.

see ..\modules\imgproc\src\color.cpp for details.

I submitted a simple linear CUDA Bayer->RGB(A) to opencv, haven't followed if it's been accepted but it should be in the bugs tracker. It's based on the code in Cuda Bayer/CFA demosaicing example.

Here is a sample of howto use cv::GPU in your own code.

/*-------RG ccd  BGRA output ----------------------------*/
 __global__ void bayerRG(const cv::gpu::DevMem2Db in, cv::gpu::PtrStepb out)  
{ 
    // Note called for every pair, so x/y are for start of cell so need x+1,Y+1 for right/bottom pair
    // R G 
    // G B 

    // src
    int x = 2 * ((blockIdx.x*blockDim.x) + threadIdx.x);
    int y = 2 * ((blockIdx.y*blockDim.y) + threadIdx.y);

    uchar r,g,b;        

    // 'R'
    r = (in.ptr(y)[x]);
    g = (in.ptr(y)[x-1]+in.ptr(y)[x+1]+(in.ptr(y-1)[x]+in.ptr(y+1)[x]))/4;
    b = (in.ptr(y-1)[x-1]+in.ptr(y-1)[x+1]+(in.ptr(y+1)[x-1]+in.ptr(y+1)[x+1]))/4;  
    ((uchar4*)out.ptr(y))[x] = make_uchar4( b,g,r,0xff);

    // 'G' in R 
    r = (in.ptr(y)[x]+in.ptr(y)[x+2])/2;
    g = (in.ptr(y)[x+1]);
    b = (in.ptr(y-1)[x+1]+in.ptr(y+1)[x+1])/2;
    ((uchar4*)out.ptr(y))[x+1] = make_uchar4( b,g,r,0xff);

    // 'G' in B
    r = (in.ptr(y)[x]+in.ptr(y+2)[x])/2;
    g = (in.ptr(y+1)[x]);
    b = (in.ptr(y+1)[x-1]+in.ptr(y+1)[x+2])/2;
    ((uchar4*)out.ptr(y+1))[x] = make_uchar4( b,g,r,0xff);

    // 'B' 
    r = (in.ptr(y)[x]+in.ptr(y)[x+2]+in.ptr(y+2)[x]+in.ptr(y+2)[x+2])/4;;
    g = (in.ptr(y+1)[x]+in.ptr(y+1)[x+2]+in.ptr(y)[x+1]+in.ptr(y+2)[x+1])/4;
    b = (in.ptr(y+1)[x+1]);
    ((uchar4*)out.ptr(y+1))[x+1] = make_uchar4( b,g,r,0xff);    
} 


/* called from */
extern "C" void cuda_bayer(const cv::gpu::DevMem2Db& img, cv::gpu::PtrStepb out)
{
    dim3 threads(16,16);    
    dim3 grid((img.cols/2)/(threads.x), (img.rows/2)/(threads.y));  

    bayerGR2<<<grid,threads>>>(img,out);    
    cudaThreadSynchronize();
}
like image 126
Martin Beckett Avatar answered Sep 28 '22 21:09

Martin Beckett


Currently, to my knowledge, the best debayer out there is DFPD (directional filtering with posteriori decision) as explained in this paper. The paper is quite explanatory and you can easily prototype this approach on Matlab. Here's a blog post comparing the results of DFPD to debayer based on linear approach. You can visibly see the improvement in artifacts, colors and sharpness.

like image 32
jwdmsd Avatar answered Sep 28 '22 21:09

jwdmsd