Spline Catmull-Rom for image zooming using C++ and opencv

Hello,
I’m trying to implement spline Catmull-Rom for image zooming using C++ and OpenCV. I performed two tests, the first is image zooming (X2), and the second image reconstruction (zooming image decimated). My problem is that in the image interpolated appear some white and black pixel (image1) when I displayed the value of pixels I found that white pixels have a negative value and the black one has a value greater than 255, also the image reconstructed appear blurred (image2).

float CalCurveInt(float t, float p0, float p1, float p2, float p3)
{

    float t2 = t * t;
    float t3 = t2 * t;

    float x = 0.5f * ((2.0f * p1) +
        (-p0 + p2) * t +
        (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 +
        (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
return x;
}

Mat CalcCatmull(Mat &src, int zoom)
{
    int v1, v2, v3, v4, Ptr, Xmax, Ymax;
    float Result, t, c1, c2, c3, c4;
    //------------------------------------------------------------
    Xmax = src.cols;
    Ymax = src.rows;
    Size srcSize(zoom*Xmax, Ymax);
    Mat dst(srcSize, CV_8UC1);

    for (int j = 0; j < Ymax; j++)
    {
        Ptr = 0;
        for (int i = 0; i < Xmax; i++)
        {
            v1 = i - 1; v2 = i; v3 = i + 1; v4 = i + 2;

            if (i - 1 < 0)      v1 = 0;
            if (Xmax <= i + 1)  v3 = Xmax - 1;
            if (Xmax <= i + 2)  v4 = Xmax - 1;

            for (double J = 1; J <= zoom; J++)
            {
                t = J / zoom;
                Result = 0.0;

                c1 = src.at<uchar>(j, v1);
                c2 = src.at<uchar>(j, v2);
                c3 = src.at<uchar>(j, v3);
                c4 = src.at<uchar>(j, v4);

                Result = CalCurveInt(t, c1, c2, c3, c4);
                dst.at<uchar>(j, Ptr) = abs(Result);
                Ptr++;
            }
        }
    }

    //------------------------------------------------
    Xmax = dst.cols;
    Ymax = dst.rows;

    Size srcSize1(Xmax, zoom*Ymax);
    Mat dest(srcSize1, CV_8UC1);

    for (int i = 0; i < Xmax; i++)
    {
        Ptr = 0;
        for (int j = 0; j < Ymax; j++)
        {

            v1 = j - 1; v2 = j; v3 = j + 1; v4 = j + 2;

            if (j - 1 < 0)      v1 = 0;
            if (Ymax <= j + 1)  v3 = Ymax - 1;
            if (Ymax <= j + 2)  v4 = Ymax - 1;

            for (double J = 1; J <= zoom; J++)
            {
                t = J / zoom;
                Result = 0.0;

                c1 = dst.at<uchar>(v1, i);
                c2 = dst.at<uchar>(v2, i);
                c3 = dst.at<uchar>(v3, i);
                c4 = dst.at<uchar>(v4, i);
                Result = CalCurveInt(t, c1, c2, c3, c4);           
                dest.at<uchar>(Ptr, i) = Result;
                Ptr++;
            }
        }
    }

    return dest;
}

float zoom = 2.0;


int main()
{
    Mat src = imread("fruits.png", CV_LOAD_IMAGE_GRAYSCALE);
    int width = src.cols;
    int hight = src.rows;

    /*Image Decimation*/
    Size srcdSize(int(width / zoom), int(hight / zoom));
    Mat srcd;
    pyrDown(src, srcd, srcdSize);
    imshow("decimation", srcd);

    Mat dst = CalcCatmull(srcd, zoom);

    imshow("Image Source", src);
    imshow("Image dest", dst);
    imwrite("Image dest.png", dst);

    waitKey(0);
    return 0;
}

Thanks in advance.

related

the issue you have is that interpolated values may exceed the range of 0…255, and since computers wrap integers around, you get those artefacts.

calculate with floats, clip/saturate the final result before converting back to integers.

1 Like

Thanks for your help @crackwitz

as for why the “reconstructed” picture is blurred… you removed the information in the downsampling step. it is gone. it can’t be recreated by mere interpolation.

1 Like