OpenCV图像缩放resize各种插值方式的比较实现
作者:pan_jinquan 发布时间:2023-03-18 13:31:45
1. resize函数说明
OpenCV提供了resize函数来改变图像的大小,函数原型如下:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );
参数说明:
src:输入,原图像,即待改变大小的图像;dst:输出,改变大小之后的图像,这个图像和原图像具有相同的内容,只是大小和原图像不一样而已;dsize:输出图像的大小。如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:dsize = Size(round(fx*src.cols), round(fy*src.rows))
其中,fx和fy就是下面要说的两个参数,是图像width方向和height方向的缩放比例。
fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;interpolation:这个是指定插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,有以下几种:INTER_NEAREST - 最邻近插值
INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
INTER_AREA -区域插值 resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
INTER_CUBIC - 4x4像素邻域内的双立方插值
INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值
使用注意事项:
dsize和fx/fy不能同时为0,要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像
resize(img, imgDst, Size(30,30));
要么你就让dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
OpenCV官方说明:注意红色方框那句话:https://docs.opencv.org/3.2.0/da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d
To shrink an image, it will generally look best with cv::INTER_AREA interpolation, whereas to enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv::INTER_LINEAR (faster but still looks OK).
2.各种插值方式的比较
OpenCV的cv::resize函数支持多种插值方式,这里主要比较下面四个常用的插值方式。
参考资料:《OpenCV中resize函数五种插值算法的实现过程》
2.1 INTER_NEAREST(最近邻插值)
最近邻插值是最简单的插值方法,选取离目标点最近的点作为新的插入点,计算公式表示如下:
插值后的边缘效果:由于是以最近的点作为新的插入点,因此边缘不会出现缓慢的渐慢过度区域,这也导致放大的图像容易出现锯齿的现象
2.2 INTER_CUBIC (三次样条插值)
插值后的边缘效果:可以有效避免出现锯齿的现象
2.3 INTER_LINEAR(线性插值)
线性插值是以距离为权重的一种插值方式。
插值后的边缘效果:可以有效避免出现锯齿的现象
2.4 INTER_AREA (区域插值)
区域插值共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现。因此对图像进行缩小时,为了避免出现波纹现象,推荐采用区域插值方法。
OpenGL说明文档有这么解释:To shrink an image, it will generally look best with #INTER_AREA interpolation, whereas to enlarge an image, it will generally look best with #INTER_CUBIC (slow) or #INTER_LINEAR (faster but still looks OK).
如果要缩小图像,通常推荐使用INTER_AREA插值效果最好,而要放大图像,通常使用INTER_CUBIC(速度较慢,但效果最好),或者使用INTER_LINEAR(速度较快,效果还可以)。
插值后的边缘效果:
测试代码:
#include <chrono>
#include <opencv2/opencv.hpp>
#define millisecond 1000000
#define DEBUG_PRINT(...) printf( __VA_ARGS__); printf("\n")
#define DEBUG_TIME(time_) auto time_ =std::chrono::high_resolution_clock::now()
#define RUN_TIME(time_) (double)(time_).count()/millisecond
using namespace std;
cv::Mat image_resize(cv::Mat image, int width, int height, int interpolation, int num) {
cv::Mat dest;
for (int i = 0; i < num; ++i) {
cv::resize(image, dest, cv::Size(width, height), 0, 0, interpolation);//最近邻插值
}
return dest;
}
int main() {
string path = "../1.jpg";
cv::Mat image = cv::imread(path);
cv::resize(image, image, cv::Size(1000, 1000));
int re_width = 900;
int re_height = 900;
int num=10;
cv::Mat image2X_INTER_NEAREST;
cv::Mat image2X_INTER_LINEAR;
cv::Mat image2X_INTER_AREA;
cv::Mat image2X_INTER_CUBIC;
cv::Mat initMat;
DEBUG_PRINT("image input size:%dx%d", image.rows, image.cols);
DEBUG_TIME(T0);
image2X_INTER_NEAREST=image_resize(image, re_width, re_height, cv::INTER_NEAREST, num);
DEBUG_TIME(T1);
image2X_INTER_LINEAR=image_resize(image, re_width, re_height, cv::INTER_LINEAR, num);
DEBUG_TIME(T2);
image2X_INTER_AREA=image_resize(image, re_width, re_height, cv::INTER_AREA, num);
DEBUG_TIME(T3);
image2X_INTER_CUBIC=image_resize(image, re_width, re_height, cv::INTER_CUBIC, num);
DEBUG_TIME(T4);
DEBUG_PRINT("resize_image:%dx%d,INTER_NEAREST:%3.3fms",
image2X_INTER_NEAREST.rows,
image2X_INTER_NEAREST.cols,
RUN_TIME(T1 - T0)/num);
DEBUG_PRINT("resize_image:%dx%d,INTER_LINEAR :%3.3fms",
image2X_INTER_LINEAR.rows,
image2X_INTER_LINEAR.cols,
RUN_TIME(T2 - T1)/num);
DEBUG_PRINT("resize_image:%dx%d,INTER_AREA :%3.3fms",
image2X_INTER_AREA.rows,
image2X_INTER_AREA.cols,
RUN_TIME(T3 - T2)/num);
DEBUG_PRINT("resize_image:%dx%d,INTER_CUBIC :%3.3fms",
image2X_INTER_CUBIC.rows,
image2X_INTER_CUBIC.cols,
RUN_TIME(T4 - T3)/num);
return 0;
}
运行结果:
image input size:1000x1000
resize_image:900x900,INTER_NEAREST:0.389ms
resize_image:900x900,INTER_LINEAR :0.605ms
resize_image:900x900,INTER_AREA :2.611ms
resize_image:900x900,INTER_CUBIC :1.920ms
3. 总结
测试结果表明:
速度比较:INTER_NEAREST(最近邻插值)>INTER_LINEAR(线性插值)>INTER_CUBIC(三次样条插值)>INTER_AREA (区域插值)
对图像进行缩小时,为了避免出现波纹现象,推荐采用INTER_AREA 区域插值方法。
OpenCV推荐:如果要缩小图像,通常推荐使用#INTER_AREA插值效果最好,而要放大图像,通常使用INTER_CUBIC(速度较慢,但效果最好),或者使用INTER_LINEAR(速度较快,效果还可以)。至于最近邻插值INTER_NEAREST,一般不推荐使用
来源:https://blog.csdn.net/guyuealian/article/details/85097633
猜你喜欢
- 使用fso对象遍历指定文件夹函数:'遍历文件夹sub ListFolderContents(path) &nbs
- 本文采用os.walk()和os.listdir()两种方法,获取指定文件夹下的文件名。一、os.walk()模块os中的walk()函数可
- 爬虫所需要的功能,基本上在urllib中都能找到,学习这个标准库,可以更加深入的理解后面更加便利的requests库。首先在Pytho2.x
- 本文实例为大家分享了python实现简单俄罗斯方块游戏的具体代码,供大家参考,具体内容如下import pygame,sys,random,
- iterator循环器(iterator)是对象的容器,包含有多个对象。通过调用循环器的next()方法 (next()方法,在Python
- 更新 2016/8/9:最近发现目标网站已经屏蔽了这个
- 其实小程序上面也可以使用 echart 等开源图表库得,而且支持代码包得裁切功能,但是可能我不会用吧,效果不太好,而且我这就一个图,也没什么
- 用ASP判断一个字符串中只包含字母和数字要怎么做啊? for s=1 to len(trim(use
- 本文实例讲述了Python实现计算圆周率π的值到任意位的方法。分享给大家供大家参考,具体如下:一、需求分析输入想要计算到小数点后的位数,计算
- 本节列出了可以运行MySQL的操作系统。我们使用GNU Autoconf,因此将MySQL移植到所有使用Posix线程和C++编译器的现代系
- 前言:Python 中的画图工具——turtle(海龟绘图),turtle 是 Python 中自带
- 前言Laravel是一个简单优雅的PHP Web开发框架,可以将开发者从意大利面条式的代码中解放出来,通过简单、高雅、表达式语法开发出很棒的
- 大多的MySQL都是装在Linux上的,而我们的本机上一般都会装MySQL-Front.那如何用MySQL-Front连接远端Linux系统
- asp使用WScript.Shell获取电脑的网络配置信息Option Explicit Dim WSHShe
- 本文实例讲述了Python采用socket模拟TCP通讯的实现方法。分享给大家供大家参考。具体实现方法如下:对于TCP server端的创建
- 写过PHP+MySQL的程序员都知道有时间差,UNIX时间戳和格式化日期是我们常打交道的两个时间表示形式,Unix时间戳存储、处理方便,但是
- 在输入框里面预设一段提示文字,当焦点在输入框的时候清空这段文字,这在目前来说已经不是什么新鲜事了。淘宝的搜索框就用到了这样一种设计:这种设计
- ThinkPHP的分组功能是广为开发者使用的一个具有很大实用价值的功能,该功能可以解决中大型项目情况中MVC分层文件过多导致不易管理的问题。
- 交叉表(cross-tabulation,简称crosstab)是⼀种⽤于计算分组频率的特殊透视表。语法详解:pd.crosstab(ind
- Python自带的pdb库,发现用pdb来调试程序还是很方便的,当然了,什么远程调试,多线程之类,pdb是搞不定的。用pdb调试有多种方式可