mutyala mahesh
mutyala mahesh

Reputation: 137

Problem with Operation on Border pixels of an image

I am trying to implement a demosaicing algorithm (interpolation) for a raw image with the Bayer pattern GRBG. The program logic was to use the neighboring pixels to assign the values to R,G and B channels(I have attached the code). I am having a problem for this logic at the border pixels. For example let i be the pixel at (0,0), I need the value of i-1 which is not present in the image. My question is there a possibility to work around this like masking i-1 and the others as 0 without adding an new border of zeros to my existing image.

Any suggestions will be helpful. thanks.

    int rows = 256;
    int cols = 512;
    Mat raw_img(rows, cols, CV_8U);                 //////////////////////
    Mat image(rows, cols, CV_8UC3);                 //  BAYER PATTERN   //
    cvtColor(image, image, COLOR_BGR2RGB);          //      G R         //  
    for (int i = 0; i < raw_img.rows; i++) {        //      B G         //
        for (int j = 0; j < raw_img.cols; j++) {    //////////////////////
            if ((i % 2 == 0) && (j % 2 == 0))//top green
            {
                image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(i - 1, j) + 
                                            raw_img.at<uchar>(i + 1, j)) / 2; //red

                image.at<Vec3b>(i, j)[1] = (raw_img.at<uchar>(i, j) * 2); //blue

                image.at<Vec3b>(i, j)[2] = (raw_img.at<uchar>(i, j - 1) +
                                            raw_img.at<uchar>(i, j + 1)) / 2;  //green
            }
            else if ((i % 2 == 0) && (j % 2 == 1))//red
            {
                image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(i, j));        //red

                image.at<Vec3b>(i, j)[1] = (raw_img.at<uchar>(i - 1, j) + 
                                            raw_img.at<uchar>(i + 1, j) +
                                            raw_img.at<uchar>(i, j - 1) + 
                                            raw_img.at<uchar>(i, j + 1)) / 2;//green

                image.at<Vec3b>(i, j)[2] = (raw_img.at<uchar>(i + 1, j - 1) +
                                            raw_img.at<uchar>(i - 1, j + 1) +
                                            raw_img.at<uchar>(i + 1, j + 1) + 
                                            raw_img.at<uchar>(i - 1, j - 1)) / 4;//blue

            }
            else if ((i % 2 == 1) && (j % 2 == 0))//blue
            {
                image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(i + 1, j - 1) + 
                                            raw_img.at<uchar>(i - 1, j + 1) +
                                            raw_img.at<uchar>(i + 1, j + 1) + 
                                            raw_img.at<uchar>(i - 1, j - 1)) / 4;//red

                image.at<Vec3b>(i, j)[1] = (raw_img.at<uchar>(i + 1, j) + 
                                            raw_img.at<uchar>(i, j + 1) +
                                            raw_img.at<uchar>(i - 1, j) + 
                                            raw_img.at<uchar>(i, j + 1)) / 2;//green

                image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(i, j));//blue
            }
            else // bottom green
            {
                image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(i, j - 1) + 
                                            raw_img.at<uchar>(i, j + 1)) / 2;//red

                image.at<Vec3b>(i, j)[1] = (raw_img.at<uchar>(i, j) * 2);//blue

                image.at<Vec3b>(i, j)[2] = (raw_img.at<uchar>(i - 1, j) + 
                                            raw_img.at<uchar>(i + 1, j)) / 2;//green
            }
        }
    }

Upvotes: 1

Views: 418

Answers (2)

mutyala mahesh
mutyala mahesh

Reputation: 137

The above stated answer works. But to prevent the hassle of using min,max with each pixel. It can be done as shown below with an Opencv function:

int main(int argc, char** argv)
{
    Mat img_rev = imread("C:/Users/20181217/Desktop/images/imgs/den_check.png");
        
    //number of additional rows and columns
    int top, left, right, bottom;
    top = 1;
    left = 1;
    right = 1;
    bottom = 1;
    
    //define new image with additional borders
    Mat img_clamp(img_rev.rows + 2, img_rev.cols + 2, CV_8UC3);
    
    //if you want to pad the image with zero's
    copyMakeBorder(img_rev, img_clamp, top, left, right, bottom, BORDER_CONSTANT);
    
    //if you want to replicate the border of the image
    copyMakeBorder(img_rev, img_clamp, top, left, right, bottom, BORDER_REPLICATE);
//Now you can access the image without having to worry about the borders as shown below
for(int i=1;i<img_clamp.rows-1;i++)
 {
  for(int j=1;i<img_clamp.cols-1;i++)
   {
     ...
    }
  }

    
    waitKey(100000);
    return 0;
}

More operations can be found here:

https://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html?highlight=copymakeborder#copymakeborder

Upvotes: 0

Jean-Marc Volle
Jean-Marc Volle

Reputation: 3323

You could do something like:

image.at<Vec3b>(i, j)[0] = (raw_img.at<uchar>(max(0,i - 1), j) 
+ raw_img.at<uchar>(min(i + 1,raw_img.rows-1), j)) / 2; //red

For all you i +/- 1 , j +/-1: this way you "replicate" border values by simply sticking to the last value value in the X or Y dimension

As a side note, openCV includes different demosaic algorithm that will be hard to beat (for both quality and execution speed)

Upvotes: 1

Related Questions