Репликация изменения размера OpenCV с билинарной интерполяцией в C (только сжатие)

Я пытаюсь сделать копию алгоритма изменения размера OpenCV с билинейной интерполяцией в C. Я хочу добиться того, чтобы полученное изображение было точно таким же (значение пикселя), что и созданное OpenCV. Меня особенно интересует сжатие, а не увеличение, и мне интересно использовать его на одноканальных изображениях в градациях серого. В сети я читал, что алгоритм билинейной интерполяции отличается между сжатием и расширением, но формул для сжатий-реализаций я не нашел, так что вполне вероятно, что код, который я написал, совершенно неверен. То, что я написал, исходит из моих знаний об интерполяции, полученных на университетском курсе компьютерной графики и OpenGL. Результатом написанного мной алгоритма являются изображения, визуально идентичные изображениям, созданным OpenCV, но значения пикселей которых не полностью идентичны (в частности, вблизи краев). Можете ли вы показать мне алгоритм сжатия с билинейной интерполяцией и возможную реализацию?

Примечание. Прилагаемый код представляет собой одномерный фильтр, который необходимо применить сначала по горизонтали, а затем по вертикали (т. е. с транспонированной матрицей).

Mat rescale(Mat src, float ratio){

    float width = src.cols * ratio; //resized width
    int i_width = cvRound(width);
    float step = (float)src.cols / (float)i_width; //size of new pixels mapped over old image
    float center = step / 2; //V1 - center position of new pixel
    //float center = step / src.cols; //V2 - other possible center position of new pixel
    //float center = 0.099f; //V3 - Lena 512x512 lower difference possible to OpenCV

    Mat dst(src.rows, i_width, CV_8UC1);

    //cycle through all rows
    for(int j = 0; j < src.rows; j++){
        //in each row compute new pixels
        for(int i = 0; i < i_width; i++){
            float pos = (i*step) + center; //position of (the center of) new pixel in old map coordinates
            int pred = floor(pos); //predecessor pixel in the original image
            int succ = ceil(pos); //successor pixel in the original image
            float d_pred = pos - pred; //pred and succ distances from the center of new pixel
            float d_succ = succ - pos;
            int val_pred = src.at<uchar>(j, pred); //pred and succ values
            int val_succ = src.at<uchar>(j, succ);

            float val = (val_pred * d_succ) + (val_succ * d_pred); //inverting d_succ and d_pred, supposing "d_succ = 1 - d_pred"...
            int i_val = cvRound(val);
            if(i_val == 0) //if pos is a perfect int "x.0000", pred and succ are the same pixel
                i_val = val_pred;
            dst.at<uchar>(j, i) = i_val;
        }
    }

    return dst;
}

person Alessandro Gaietta    schedule 11.09.2013    source источник
comment
это было очень полезно. В основном следует добавить термин (0.5 * (1 - 1/ratio)). Тем не менее, из-за ошибок округления (и если OpenCV округляет до целого числа) может быть до 1 разницы.   -  person dashesy    schedule 20.06.2019


Ответы (1)


Билинейная интерполяция неразделима в том смысле, что вы можете изменять размер по вертикали и снова изменять размер по вертикали. См. пример здесь.

Вы можете увидеть resize код OpenCV здесь .

person Adi Shavit    schedule 12.06.2014