图像内插-最近邻内插法

一、数学原理

     当一幅二维数字图像从源图像N*M被放为(j*N) * (k*M)目标图像是,参照数学斜率计算公式

     必然有: (X1 – Xmin)/(Xmax - Xmin) = (Y1 - Ymin)/(Ymax-Ymin)

     当Xmin 和 Ymin均为从零开始的像素点时,公式可以简化为:X=Y1 (Xmax/Ymax)

     对于任意一幅源图像来说,假设放大后目标图像的宽为Dw高为Dh,任意目标像素点(Dx, Dy)

     在源图像上的位置为:

      Sx= Dx * (Sh/Dh) // row

      Sy= Dy * (Sw/Dw) // column

     最简单的图像缩放算法就是最近邻插值。顾名思义,就是将目标图像各点的像素值设为源图像中与其最近的点。假设源图像的宽度和高度分别为w0和h0, 缩放后的目标图像的宽度和高度分别为w1和h1, 那么比例就是float fw = float(w0)/w1; float fh = float(h0)/h1; 对于目标图像中的(x,y)点坐标对应着源图像中的(x0, y0)点。其中:x0 = int(x*fw), y0 = int(y*fh)。

二、代码实现

int _tmain(int argc, _TCHAR* argv[])
{
	//导入图像
	Mat src = imread("1.jpg");

	//显示
	imshow("src",src);

	//创建矩阵
	Mat dst = Mat::zeros(Size(800,1000),CV_8UC3);

	//放大的比例
	double fRows = 1000 / (float)src.rows;
	double fCols = 800 / (float)src.cols;
	int primaryX = 0;
	int primaryY = 0;
	//近邻内插法
	for (int i =0; i != dst.rows; ++ i)
	{
		for (int j = 0; j != dst.cols; ++ j)
		{
			primaryX = cvRound(i / (double)fRows); 
			primaryY = cvRound(j / (double)fCols);
			if(primaryX<src.rows&&primaryX>= 0&&primaryY>= 0&& primaryY<src.cols)
			{
				dst.at<cv::Vec3b>(i,j)[0] = src.at<cv::Vec3b>(primaryX,primaryY)[0];
				dst.at<cv::Vec3b>(i,j)[1] = src.at<cv::Vec3b>(primaryX,primaryY)[1];
				dst.at<cv::Vec3b>(i,j)[2] = src.at<cv::Vec3b>(primaryX,primaryY)[2];
			}
		}
	}

	imshow("dst",dst);

	waitKey(0);
	return 0;
}

三、结果显示与分析

得到的结果如下图所示:


    临近点插值算法会产生锯齿效果, 不是一个很好的图像放缩算法,临近点插值算法不改变源像素点到目标像素点的值,只是最简单的位置匹配而已,相比之下,双线性内插值算法和双立方插值算法效果更好,但是计算量更大,临近点插值是计算量最小的防缩算法。


展开阅读全文

没有更多推荐了,返回首页