实现基于最近邻内插和双线性内插的图像缩放C++实现
2017-09-23 00:36
447 查看
平时我们写图像处理的代码时,如果需要缩放图片,我们都是直接调用图像库的resize函数来完成图像的缩放。作为一个机器视觉或者图像处理算法的工作者,图像缩放代码的实现应该是必须掌握的。在众多图像缩放算法中,最近邻内插算法和双线性内插算法最为基本和常见,所以这篇文章就说一说如何用c++实现这两种算法下的图像缩放。
原图
缩放图
最近邻内插算法实现的图像缩放的原理很简单,编码起来也容易,缺点就是得到的图像效果不太好。
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
双线性内值算法的核心思想就是上面的那个公式,它解释了对于原图不存在的浮点像素(比如<1.5,1.5>)是如何确定其实际值的。其实它是以4个相邻的像素值来共同确定,即<1,1> <2,1> <1,2> <2,2>。谁离<1,1>比较近,谁就对它起的影响比较大,这些都在公式中有所体现,这就是双线性插值的精髓。
最近邻内插
最近邻内插这种算法就是根据原图像和目标图像的尺寸,计算缩放的比例,然后根据缩放比例计算目标像素所依据的原像素,过程中自然会产生小数,这时就采用四舍五入,取与这个点最相近的点,当然向下取整也是可以的。#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std; void scale(cv::Mat& input_img, int width, int height); int main() { cv::Mat img = cv::imread("41.png",0); cv::imshow("src", img); scale(img, 450, 300); return 0; } //获取原图相应坐标的像素值 uchar get_scale_value(cv::Mat& input_img, int i, int j) { uchar* p = input_img.ptr<uchar>(i); return p[j]; } void scale(cv::Mat& input_img,int width,int height) { cv::Mat output_img(height, width, CV_8UC1); output_img.setTo(0); float h_scale_rate = (float)input_img.rows/ height; //高的比例 float w_scale_rate = (float)input_img.cols / width; //宽的比例 for (int i = 0; i < height; i++) { uchar* p = output_img.ptr<uchar>(i); for (int j = 0; j < width; j++) { int i_scale = h_scale_rate * i; //依照高的比例计算原图相应坐标中的x,这里采用的是向下取整,当然四舍五入也可以 int j_scale = w_scale_rate * j; //依照宽的比例计算原图相应坐标中的y //cout << "i_scale: " << i_scale <<" j_scale: "<< j_scale << endl; p[j] = get_scale_value(input_img,i_scale, j_scale); } } cv::imshow("scale", output_img); cv::imwrite("result.png", output_img); cv::waitKey(); }
原图
缩放图
最近邻内插算法实现的图像缩放的原理很简单,编码起来也容易,缺点就是得到的图像效果不太好。
双线性内插
对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(x,y),当然我们也可以将其表示成整数+小数的形式,即(i+u,j+v),其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
双线性内值算法的核心思想就是上面的那个公式,它解释了对于原图不存在的浮点像素(比如<1.5,1.5>)是如何确定其实际值的。其实它是以4个相邻的像素值来共同确定,即<1,1> <2,1> <1,2> <2,2>。谁离<1,1>比较近,谁就对它起的影响比较大,这些都在公式中有所体现,这就是双线性插值的精髓。
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std; void bin_linear_scale(cv::Mat& input_img, int width, int height); int main() { cv::Mat img = cv::imread("41.png", 0); cv::imshow("src", img); bin_linear_scale(img, 450, 300); return 0; } //f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1) uchar get_scale_value(cv::Mat& input_img, float raw_i, float raw_j) { int i = raw_i; int j = raw_j; float u = raw_i - i; float v = raw_j - j; //注意处理边界问题,容易越界 if (i + 1 >= input_img.rows || j + 1 >= input_img.cols) { uchar* p = input_img.ptr<uchar>(i); return p[j]; } uchar* p = input_img.ptr<uchar>(i); uchar x1 = p[j]; //f(i,j) uchar x2 = p[j + 1]; //f(i,j+1) p = input_img.ptr<uchar>(i+1); uchar x3 = p[j]; //(i+1,j) uchar x4 = p[j + 1]; //f(i+1,j+1) // printf("%d %d\n", i, j); return ((1-u)*(1-v)*x1+(1-u)*v*x2+u*(1-v)*x3+u*v*x4); } void bin_linear_scale(cv::Mat& input_img, int width, int height) { cv::Mat output_img(height, width, CV_8UC1); output_img.setTo(0); float h_scale_rate = (float)input_img.rows / height; float w_scale_rate = (float)input_img.cols / width; for (int i = 0; i < height; i++) { uchar* p = output_img.ptr<uchar>(i); for (int j = 0; j < width; j++) { float i_scale = h_scale_rate * i; float j_scale = w_scale_rate * j; //cout << "i_scale: " << i_scale <<" j_scale: "<< j_scale << endl; p[j] = get_scale_value(input_img, i_scale, j_scale); } } cv::imshow("scale", output_img); cv::imwrite("result.png", output_img); cv::waitKey(); }
相关文章推荐
- 基于 MFC+Halcon 实现图像缩放、平移
- C++基于Directx MMX实现的图像灰度转换代码
- scxml 图像展示器 (基于C++ MFC GDI tinyxpath的实现)
- 使用Matlab进行图像的读写、显示和缩放(最近临插值和双线性内插值法)
- 图像缩放插值算法以及matlab简单实现(最近邻法、双线性插值法、三次卷积法)
- 基于C++实现的简单的图像搜索引擎
- [转]opencv3 图像处理 之 图像缩放( python与c++实现 )
- 图像几何变换之图像缩放---最临近插值和双线性内插值实现
- 基于C++和OpenCv的SIFT_图像局部特征检测算法代码的实现
- opencv3 图像处理(一)图像缩放( python与c++ 实现)
- 基于OpenCV实现图像线性变化
- 最近邻图像旋转代码 灰度图像 c++实现
- 数字图像处理,基于PM和Catte模型各向异性扩散的C++实现
- 图像卷积操作的手动实现(基于opencv的C++编译环境)
- opencl:C++实现双线性插值图像缩放
- 基于深度学习的图像匹配技术专题- [patch based matching5]-手把手教你实现MatchNet(Metric network)
- fast neural style transfer图像风格迁移基于tensorflow实现
- 【数字图像处理】<纯C++>读取、裁剪、缩放、旋转和存储8位bmp灰度图像
- 【图像处理】C++实现模板匹配
- 基于MIDP2.0实现图片的缩放功能