1、最近邻插值(最最基础的方法了)
举个栗子:
假设我们有一张原始图(源图,source),大小为3*3。
225 | 46 | 77 |
56 | 88 | 77 |
45 | 125 | 35 |
想要放大为4*4的目标图(destination)。
? | ? | ? | ? |
? | ? | ? | ? |
? | ? | ? | ? |
? | ? | ? | ? |
接着就该考虑怎么由源图填充目标图的像素了。
以左上角(0,0)为例,由公式
得到应该由源图中的(0,0)点像素值进行填充。以此类推目标图片中(1,0)点由源图中(1*(3/4),0*(3/4))=>(0.75,0)=>(1,0)填充(四舍五入),其它点类推可得到放大的图。
这种放大图像的方法会引起严重的失真,根源在于当坐标是浮点数时直接四舍五入取最近的整数。
代码:
# include<iostream>
# include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
Mat NearInter(Mat &srcImage, double kx, double ky)
{
int rows = cvRound(srcImage.rows*kx);
int cols = cvRound(srcImage.cols*ky);
Mat resultImg(rows, cols, srcImage.type());
int i, j, x, y;
for (i = 0; i < rows; i++)
{
x = static_cast<int>((i + 1) / kx + 0.5) - 1;
for (j = 0; j < cols; j++)
{
y = static_cast<int>((j + 1) / ky + 0.5) - 1;
resultImg.at<Vec3b>(i, j) = srcImage.at<Vec3b>(x, y);
}
}
return resultImg;
}
int main()
{
Mat srcImg = imread("文件路径");
Mat resultImg = NearInter(srcImg, 0.6, 1.2);
imshow("src", srcImg);
imshow("0.6,1.2", resultImg);
waitKey(0);
return 0;
}
2、 双线性插值
在最近邻插值时,对于源图中坐标为浮点数的点,直接四舍五入取整带来了严重的失真。比如0.75直接取1,更科学的方法是,0.75距离1为0.25,距离0为0.75,按照距离的占比取相应点像素值的找比。
对于目标图通过反向变换得到的源图中浮点坐标为(i+u,j+v)(其中i,j为浮点数的整数部分,u,v为浮点数的小数部分);
这个点的像素值f(i+u,j+v)=(1-u)(1-v)f(i,j)+(1-u)vf(i,j+1