Проблема с работой с пограничными пикселями изображения - PullRequest
1 голос
/ 08 мая 2020

Я пытаюсь реализовать алгоритм демозаики (интерполяции) для необработанного изображения с шаблоном Байера GRBG . Программа logi c должна была использовать соседние пиксели для присвоения значений каналам R, G и B (я приложил код). У меня проблема с этим logi c на границе пикселей. Например, пусть i будет пикселем в (0,0) , мне нужно значение i-1 , которого нет на изображении. Мой вопрос, есть ли возможность обойти это, например, замаскировать i-1 и другие как 0 без добавления новой границы нулей к моему существующему изображению.

Любые предложения будут полезны. спасибо.

    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
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Вы можете сделать что-то вроде:

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

Для всех вас i +/- 1, j +/- 1: таким образом вы "реплицируете" значения границ, просто придерживаясь последнего значения в размер X или Y

В качестве примечания, openCV включает в себя другой демонстрационный алгоритм c, который будет сложно превзойти (как по качеству, так и по скорости выполнения)

0 голосов
/ 25 июня 2020

Приведенный выше ответ работает. Но чтобы не было хлопот использовать min,max с каждым пикселем. Это можно сделать, как показано ниже, с помощью функции Opencv:

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;
}

Дополнительные операции можно найти здесь:

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

...