4

我正在尝试在 C 中使用双线性插值复制 OpenCV 的大小调整算法。我想要实现的是生成的图像与 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;
}
4

1 回答 1

2

双线性插值在您可以垂直调整大小并再次垂直调整大小的意义上是不可分离的。请参见此处的示例。

您可以在此处查看 OpenCV 的resize代码。

于 2014-06-12T06:38:14.867 回答