Home > Software design >  How can I scale/interpolate an image with indexed values smoothly?
How can I scale/interpolate an image with indexed values smoothly?

Time:08-11

I am wanting to scale grayscale images (input masks, really) with discrete values up smoothly. The values in these images are indexes that represent arbitrary concepts (e.g. "terrain types"; they are usually indices into a table), rather than values on a continuous scale, so they can't be averaged or blended in any way.

Do there exist algorithms that can do this with a more pleasing result than nearest-neighbour, which results in a very blocky, pixelated result? I am looking for something that will at least produce more rounded results, and hopefully there are even algorithms that approximate a higher resolution version of the shapes made by the pixels.

I've researched the subject, but I can't find anything. There is plenty about linear or cubic interpolation, etc., but that won't work for indexed values. The only algorithm I ever see mentioned that does not try to average values is nearest-neighbour. But there must be more?

diagram of desired result

Using colour here for clarity. I do of course understand that the preferred result here is impossible; I'm not asking for something that reconstitutes destroyed information, just hoping for something that will at least guestimate something smoother than the first result.

CodePudding user response:

One thing you could try is to extract a polygon for the boundary of each uniformly-colored region, then upscale and draw the polygon in the output image. You won’t create neatly rounded edges, but you will avoid the stair-case effect of the nearest neighbor interpolation. Upscaling polygons should avoid gaps between the regions too.

CodePudding user response:

I guess that smoothing the shape for each value individually is a way to avoid undesired mixed value.

To handle values individually, here, I started with your nearest-neighbour image v, and create 3 image { A.bmp, B.bmp, C.bmp } by hand. (each image has only 1 color region and background is black. e.g. A.bmp is below:)

enter image description here

After smoothing the shape for each image, draw these shapes to one result image buffer with different color.

//I use C   and OpenCV
int main()
{
    const std::string FileNames[3] = { "A.bmp", "B.bmp", "C.bmp" };
    const cv::Scalar ResultShowColor[3] = { cv::Scalar(0,255,255), cv::Scalar(0,255,0), cv::Scalar(0,0,255) };
    cv::Mat Imgs[3];

    const int KernelSize = 15;
    for( int i=0; i<3;   i )
    {
        Imgs[i] = cv::imread( FileNames[i], cv::IMREAD_GRAYSCALE );
        if( Imgs[i].empty() )return 0;

        cv::threshold( Imgs[i], Imgs[i], 32, 255, cv::THRESH_BINARY );
        cv::GaussianBlur( Imgs[i], Imgs[i], cv::Size(KernelSize,KernelSize), 0 );
        cv::threshold( Imgs[i], Imgs[i], 255*0.5, 255, cv::THRESH_BINARY );
        cv::imshow( FileNames[i], Imgs[i] );
    }

    cv::Mat ResultImg = cv::Mat::zeros( Imgs[0].size(), CV_8UC3 );
    for( int i=0; i<3;   i )
    {
        ResultImg.setTo( ResultShowColor[i], Imgs[i] );
    }
    cv::imshow( "ResultImg", ResultImg );

    if( cv::waitKey() == 's' ){ cv::imwrite( "ResultImg.png", ResultImg );  }
    return 0;
}

This is result:

enter image description here

Yes, this result is not enough. Gaps exist at the boundaries of shapes. Therefore some ingenuity is required... but I post this because it might be some hint for you.

  • Related