最邻近插值法原理分析及c++实现
最邻近插值法 : 其核心思想是选取离目标点最近的点作为待插入的新值点
公式推导过程
上述图片中像素点的说明:
Q11,Q21,Q12,Q22 分别为四个真实存在的像素点
P 为最邻近插值法待插值点
因为P点与Q12很接近,所以P ( i , j )=Q12 ( x , y+1 )
用opencv进行图像处理时,根据下面公式来计算目标像素值在源图像中所处的位置:
(src:原图像 dst:目的图像)
srcX =dstX * ( srcWidth / dstWidth)
srcY =dstY * ( srcHeight / dstHeight)
以原图尺寸3x3为例,来计算扩展后5*5图像的像素值:
目标像素(1,1)所对应的原像素的像素值为:
srcX =1 * ( 3 / 5) = 0.6 ~ 1(四舍五入约等于1)
srcY =1 * ( 3 / 5) = 0.6 ~ 1(四舍五入约等于1)
目标像素(1,1)= 原图像(1,1),所以目标像素(1,1)位置所对应的像素值为1
目标像素(1,5)所对应的原像素的像素值为:
srcX =1 * ( 3 / 5) = 0.6 ~ 1(四舍五入约等于1)
srcY =5 * ( 3 / 5) = 3
目标像素(1,5)= 原图像(1,3),所以目标像素(1,5)位置所对应的像素值为1
从而算出5 * 5整幅图像的所对应的像素值
示例代码
#include "stdafx.h"
#include "iostream"
#include "opencv2/opencv.hpp"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
using namespace std;
using namespace cv;
#pragma comment(lib,"./opencv_world300d.lib")
void Linera(cv::Mat& src, cv::Mat& dst, double sx, double sy)
{
int dst_rows = round(src.rows * sy);//把一个小数四舍五入 height
int dst_cols = round(src.cols * sx); //width
dst = cv::Mat(dst_rows, dst_cols, src.type());
for (int i = 0; i < dst.rows; i++)
{
double index_i = i / sy ;
//防止越界
if (index_i < 0) index_i = 0;
if (index_i >= src.rows - 1) index_i = src.rows - 1;
int srcrows = round(index_i);
for (int j = 0; j < dst.cols; j++)
{
double index_j = j / sx ;
//防止越界
if (index_j < 0) index_j = 0;
if (index_j >= src.cols - 1) index_j = src.cols - 1;
int srccols = round(index_j);
if (src.channels() == 1)
{
//灰度图像
dst.at<uchar>(i, j) = src.at<uchar>(srcrows, srccols);
}
else
{
//彩色图像
dst.at<cv::Vec3b>(i, j)[0] = src.at<cv::Vec3b>(srcrows, srccols)[0];
dst.at<cv::Vec3b>(i, j)[1] = src.at<cv::Vec3b>(srcrows, srccols)[1];
dst.at<cv::Vec3b>(i, j)[2] = src.at<cv::Vec3b>(srcrows, srccols)[2];
}
}
}
}
int main()
{
const char* imageName = "C:\\Users\\Public\\Pictures\\Sample Pictures\\flower.jpg";
Mat srcImage = imread(imageName);
if (srcImage.empty())
{
fprintf(stderr, "Can not load image %s\n", srcImage);
return -1;
}
int iSrcWidth = 1024, iSrcHeight = 768;
int iDstWidth = 4000, iDstHeight = 3000;
Mat dstImage;
double sx = static_cast<double>(1.0 / (1.0*iSrcWidth / iDstWidth));
double sy = static_cast<double>(1.0 / (1.0*iSrcHeight / iDstHeight));
Linera(srcImage, dstImage, sx, sy);
imwrite("D:\\123.jpg", dstImage);
system("pause");
return 0;
}
示例图像及结果展示
示例图像
结果图像