图像处理-放大和缩小
个人博客:http://www.chenjianqu.com/
原文链接:http://www.chenjianqu.com/show-7.html
在计算机图像处理和计算机图形学中,图像缩放(image scaling)是指对数字图像的大小进行调整的过程。图像缩放是一种非平凡的过程,需要在处理效率以及结果的平滑度(smoothness)和清晰度(sharpness)上做一个权衡。当一个图像的大小增加之后,组成图像的像素的可见度将会变得更高,从而使得图像表现得“软”。相反地,缩小一个图像将会增强它的平滑度和清晰度。
图像缩小
图像缩小是通过减少像素个数来实现的,因此要根据缩小的尺寸,从原图像中选择合适的像素点,使图像缩小后可以保持原有图像的特征。图像缩小的算法有很多,这里主要介绍和实现两种算法:等间隔采样、局部均值。
基于等间隔采样的图像缩小算法
等间隔采样其实就是在原图中每间隔一定的距离取像素点放到输出图像上。设原图的大小为W*H,宽度和长度的缩小因子分别为看k1和k2,那么采样间隔为:W/k1,W/k2.也就是说在原图的水平方向每隔W/k1,在垂直方向每隔W/k2取一个像素。长和宽的缩小因子k1和k2相等时,图像时等比例缩小,不等时是不等比例缩小,缩小图像的长和宽的比例会发生变化。
算法的实现步骤:
(1)计算采样间隔
设原图的大小为W*H,将其放大(缩小)为(k1*W)*(K2*H),则采样区间为
ii=1/k1;
jj=1/k2;
当k1==k2时为等比例缩小;当k1!=k2时为不等比例放大(缩小);当k1<1 && k2<1时为图片缩小,k1>1 && k2>1时图片放大。
(2)求出放大(缩小)后的图像
设原图为F(x,y)(i=1,2, ……W; j=1,2,……H),放大(缩小)的图像为G(x,y)(x=1,2, ……M; y=1,2,……N,其中M=W*k1,N=H*k2),则有 G(x,y) = f(ii*x, jj*y)
代码实现:
//图像缩小—等间隔采样 参数:原图 x轴缩放比例 y轴缩放比例
Mat ZoomOutEqualInterval(Mat& src, double x_k,double y_k)
{Mat dst(src.rows*y_k, src.cols*x_k, src.type(), Scalar(0));x_k = 1 / x_k;//将缩小率转换为采样间隔y_k = 1 / y_k;cout << "dst x y:" << dst.cols << " " << dst.rows << endl;cout << "src x y:" <<src.cols << " " << src.rows << endl;if (src.channels() == 3){for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){int x = j * x_k + 0.5;int y = i * y_k + 0.5;if (x >= src.cols)x = src.cols - 1;if (y >= src.rows)y = src.rows - 1;dst.at<Vec3b>(i, j) = src.at<Vec3b>(y, x);}}}return dst;
}
缩小一倍的效果如下:
基于局部均值的图像缩小算法
算法描述
等间隔采样的缩小方法实现简单,但是原图像中未被选中的像素信息会在缩小后的图像中丢失。局部均值的图像缩小方法对其进行了改进。在求缩小图像的像素时,不仅仅单纯的取在原图像中的采样点像素,而是以相邻的两个采样点为分割,将原图像分成一个个的子块。缩小图像的像素取相应子块像素的均值。
根据局部均值缩小的原理:g11 = (f11 + f12 + f21 + f22 ) / 4
代码实现:
//图像缩小—局部均值采样 参数:原图 x轴缩放比例 y轴缩放比例
Mat ZoomOutLocalMean(Mat& src, double x_k, double y_k)
{Mat dst(src.rows*y_k, src.cols*x_k, src.type(), Scalar(0));x_k = 1 / x_k;//将缩小率转换为采样间隔y_k = 1 / y_k;cout << "dst x y:" << dst.cols << " " << dst.rows << endl;cout << "src x y:" << src.cols << " " << src.rows << endl;if (src.channels() == 3){for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){int j_start = (j-1) * x_k+1;if (j_start < 0)j_start = 0;int j_end = j* x_k;if (j_end >=src.cols )j_end = src.cols;int i_start= (i-1) * y_k +1;if (i_start < 0)i_start = 0;int i_end = i * y_k;if (i_end >= src.rows)i_end = src.rows;int pix[3] = { 0,0,0 };int count = (j_end - j_start)*(i_end - i_start);for (int n = i_start; n < i_end; n++)for (int m = j_start; m < j_end; m++) {pix[0] = src.at<Vec3b>(n, m)[0];pix[1] = src.at<Vec3b>(n, m)[1];pix[2] = src.at<Vec3b>(n, m)[2];}if (count != 0) {Vec3b v(pix[0] / count, pix[1] / count, pix[2] / count);dst.at<Vec3b>(i, j) = v;}elsedst.at<Vec3b>(i, j) = src.at<Vec3b>(i,j);}}}return dst;
}
效果图:
图像放大
要将该图像放大两倍,可以有很多种算法,最简单的方法为邻域插值,即将每一个原像素原封不动地复制映射到扩展后对应四个像素中:
这种方法在放大图像的同时保留了所有的原图像的所有信息,但是会产生锯齿现象。
双线性插值的效果对于放大的图像而言较领域插值来得平滑,但是却使得图像变得模糊而且仍然会有一部分锯齿现象。双三次插值更好比双线性插值更好。这里只实现最近邻插值和双线性插值。
最邻近插值
原理
原始图像:I(x,y), 输出图像:F(x,y),则放大过程可转换为I(x,y)=F(int(c1*i),int(c2*j)),其中c1=1/y轴放大倍数,c2=1/x轴放大倍数系数乘以原坐标值得到的坐标值可能含有小数,所以,我们必须采取一定方法(如:四舍五入,我们这里直接去掉小数部分)来舍弃小数部分,从而取得整数表示的像素点坐标, 该过程即为最邻近插值方法。
优缺点
最邻近插值简单且直观,但得到的图像质量不高,特别在图像放大后可能产生明显锯齿。
代码实现://图像放大-最近邻插值法
Mat ZoomInNearestNeighborInterpolation(Mat& src, double x_k, double y_k)
{Mat dst(src.rows*y_k, src.cols*x_k, src.type(), Scalar(0));x_k = 1 / x_k;y_k = 1 / y_k;if (src.channels() == 3){for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++)dst.at<Vec3b>(i, j) = src.at<Vec3b>(y_k*i, x_k*j);}}return dst;
}
当x轴和y轴的放大系数均为2时,运行的效果为:
双线性插值
原理
如图所示,最邻近插值是当求得p0后,直接找其邻近的点p1, p2, p3, p4中的一个的像素值作为目标点的像素;而双线性插值,则是根据p0点与周围4点(p1, p2, p3, p4)距离关系计算目标点的像素值。
通过计算得到的原始点为p0(x0, y0),则其4周的点分别为:
x0的可能取值为:sx1 = (int)x0, sx2 = sx1 + 1
y0的可能取值为:sy1 = (int)y0, sy2 = sy1 + 1
设:
s1 = y0 – sy1
s2 = sx2 – x0
s3 = 1.0 – s1
s4 = 1.0 – s2
假设p1, p2, p3, p4的像素值分别为v1, v2, v3, v4,
则双线性插值计算p0点像素值v0公式为:
v0 = v1*s1*s4 + v2*s1*s2 + v3*s2*s3 + v4*s3*s4
优缺点
双线性内插值法计算量大,但缩放后图像质量高,不会出现像素值不连续的的情况。
双线性插值具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。
代码实现:
//图像放大-双线性插值法
Mat ZoomInBilinearInterpolation(Mat& src, double x_k, double y_k)
{Mat dst(src.rows*y_k, src.cols*x_k, src.type(), Scalar(0));x_k = 1 / x_k;y_k = 1 / y_k;if (src.channels() == 3){for (int i = 0; i < dst.rows; i++){for (int j = 0; j < dst.cols; j++){double x0 = x_k * j;double y0 = y_k * i;int x1 = int(x0);int y1 = int(y0);double s1 = y0 - y1;double s4 = x0 - x1;double s2 = 1 - s4;double s3 = 1 - s1;if (x1 >= src.cols - 1)x1 = src.cols - 2;if (y1 >= src.rows - 1)y1 = src.rows - 2;dst.at<Vec3b>(i, j) = src.at<Vec3b>(y1, x1)*s1*s4 + src.at<Vec3b>(y1, x1 + 1)*s1*s2 + src.at<Vec3b>(y1 + 1, x1 + 1)*s2*s3 + src.at<Vec3b>(y1 + 1, x1)*s3*s4;}}}return dst;
}
效果图:
三次卷积法
原理
双立方插值算法与双线性插值算法类似,对于放大后未知的像素点P,将对其影响的范围扩大到邻近的16个像素点,依据对P点的远近影响进行插值计算,因P点的像素值信息来自16个邻近点,所以可得到较细致的影像,不过速度比较慢。
不过双立方插值算法与双线性插值算法的本质区别不仅在于扩大了影响点的范围,还采用高级的插值算法,如图所示:
要求A,B两点之间e点的值,需要利用A,B周围A-1,A,B,B 1四个点的像素值,通过某种非线性的计算,得到光滑的曲线,从而算出e点的值来。
所谓“双”或者叫“二次”的意思就是在计算了横向插值影响的基础上,把上述运算拓展到二维空间,再计算纵向插值影响的意思。
双立方插值算法能够得到相对清晰的画面质量,不过计算量也变大。该算法在现在的众多图像处理软件中最为常用,比如Photoshop,After Effects,Avid,Final Cut Pro等。
为了得到更好的图像质量,在以上的基础上,许多新的算法不断涌现,它们使用了更加复杂的改进的插值方式。譬如B样条(B-SPline), 米切尔(Mitchell)等插值算法,它们的目的是使插值的曲线显得更平滑,图像边缘的表现更加完美。
自适应样条插值极其增强技术( S-Spline & S-Spline XL)
与上述经典的插值方法最大的区别在于, S-Spline 采用了一种自适应技术,那些传统的方法总是依据周围的像素点来求未知点的色彩值,也就是说需要求解的色彩值仅仅依靠该像素点在图像中的位置,而非实际的图像的像素信息,而自适应样条算法还会考虑实际图像的像素信息。 实验表明,经过 S-Spline 算法得到的图像效果要优于双立方插值算法。
现在 S-Spline 算法又出现了增强版 S-Spline XL,新版本的 S-Spline XL 算法较 S-Spline 而言画面的锐度得到进一步增强,物体的轮廓更加清晰,边缘的锯齿现象大大减弱,图像感受更加自然。
参考文献
[1]博客园:淑月尘缘. 图像缩放算法 .
https://www.cnblogs.com/sycy/p/4743620.html . 2015-08-19
[2]CSDN博客:rainbowbirds_aes.图像放大算法.
https://blog.csdn.net/rainbowbirds_aes/article/details/83114266. 2018.10.17
[3]博客园:Brook_icv. OpenCV2:等间隔采样和局部均值的图像缩小.
http://www.cnblogs.com/wangguchangqing/p/4011892.html. 2014.10.08
[3]韩九强,杨磊.数据图像处理-基于XAVIS组态软件.西安交通大学出版社.2018.8
图像处理-放大和缩小相关推荐
- 【图像处理】图像内插“最近邻插值 最近邻内插法(Nearest Neighbour Interpolate)”代码演示(调整图像大小、放大、缩小)
文章目录 何为内插--最近邻插值,引用自<数字图像处理--第三版> 代码演示 1.设置缩放倍数来放大.缩小图像 2.设置图片最终分辨率来放大.缩小图像 代码中使用的源图 20200625 ...
- (三)图像的放大和缩小
图像的放大和缩小 一.知识简介 在计算机图像处理和计算机图形学中,图像缩放(image scaling)是指对数字图像的大小进行调整的过程.图像缩放是一种非平凡的过程,需要在处理效率以及结果的平滑度( ...
- matlab对图片进行放大和缩小
利用matlab 对数字图片进行放大缩小是matlab在数字图像处理上的一个简单的应用 matlab库函数imresize()的功能就是这个,那么imresize具体怎么实现的呢,我们可以自己写一个m ...
- 计算机画图工具怎么缩小图片,Win10如何放大或缩小图片?利用win10画图工具放大、缩小图片教程...
在日常使用电脑过程中,我们经常会碰到需要放大或缩小照片(图片)的情况.那么,win10系统下该如何扩大或者缩小照片(图片)呢?其实,我们可以通过使用win10系统自带的画图工具来实现.下面小编就向大家 ...
- android 手势放缩_AIR Android:放大与缩小手势
放大与缩小手势(1) 放大与缩小手势对应TransformGestureEvent. GESTURE_ZOOM事件类型,使用时要求两个手指触摸屏幕,同时向外或向内做放缩动作,如图3-2所示. 图3-2 ...
- Android实现网页的放大与缩小
以前实现打开某一网的功能都是调用系统内的浏览器,这个实例实现的是利用Webview控件实现网页的打开,放大与缩小的功能. 实现的截图如下: 正常模式的大小: 放大网页: 缩小网页: 实现这个例子 的代 ...
- 图像的放大与缩小(2)——双线性插值放大与均值缩小
2019独角兽企业重金招聘Python工程师标准>>> 概述 基于上一节"等距采样法"实现图片放大与缩小的缺点.要对其进行改进,对图像的缩小则可以用"局 ...
- IOS代码添加控件,控件移动,放大,缩小,旋转
控件移动,放大,缩小,旋转 1,代码添加控件 例如: [objc] view plaincopy /* 1.创建一个控件 2.设置控件的位置,大小 3.设置控件所需要的各个属性 4.添加入父控件 5. ...
- 对象属性对话框只能放大不能缩小
Microsft SQL Server2008 在SQL Server Management Studio中, 对象资源管理器里,所有对象的对象属性对话框只能放大不能缩小. 在显示器显示尺寸小的环境中 ...
- powerpoint预览_如何放大和缩小PowerPoint演示文稿的一部分
powerpoint预览 Microsoft PowerPoint lets you zoom in and out on a specific part of your PowerPoint sli ...
最新文章
- VS2017 报错;C2440:无法从“const char [14]”转换为“char *”
- unix中的grep家族
- java程序测试总结_Java测试总结(ATM)
- 在终端(Terminal)中用颜色显示不同类型文件
- CSS border-radius边框圆角
- Ubuntu17.04 之 systemd 设置开机启动
- 2021中国到店消费新趋势洞察报告
- php脚本定时更新商品列表
- MVC过滤器详解 面向切面编程(AOP)
- glassfish3新建domain
- npm ERR! code ETIMEDOUTnpm ERR! syscall connectnpm ERR! errno ETIMEDOUTnpm ERR! network request t
- origin柱状图同时有两组数和两组数差值_「技能」如何用Origin进行实验数据处理...
- 高效能人士的七个习惯--读书笔记
- ICLR2020推荐阅读论文50篇
- springboot的jsp应该放在哪_七、SpringBoot项目集成JSP以及项目不同启动方式及访问路径配置...
- Python中的datetime模块!
- 使用SwiftyJSON解析JSON
- NodeJS C++ Addons基础
- 迪克斯特拉算法--Dijkstra's Algorithm
- 垃圾清理软件 CCleaner 5.59 绿色便携优化版
热门文章
- 公路自行车入门级推荐java_想玩公路自行车,有没有入门推荐?
- 闲的没事,自己动手修改上兴3.2源代码
- 面试时如何回答离开上家公司的原因?
- linux系统双显示器怎么设置复制,在 Linux 中配置双显示器
- Ubuntu设置双显示器
- C# 身份证读卡器开发
- 解决双击excel文件打开多个excel.exe进程的问题
- sdn主要包含哪些接口_SDN个人理解
- Win10下WinRAR“拒绝访问”解决+获取everyone权限
- Pytorch—模型微调(fine-tune)