2019独角兽企业重金招聘Python工程师标准>>>

概述

基于上一节“等距采样法”实现图片放大与缩小的缺点。要对其进行改进,对图像的缩小则可以用“局部均值法”,对于图像的放大则可以用“双线性插值法”。

效果如下:

     

2048*1536缩小为100*80时的效果               100*80放大到600*400的效果

局部均值法缩小图像

(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),则有原图像局部子块为

f’(x,y) = f(ii*i, jj*j)        …… f(ii*i + ii-1, jj*j)

……                   ……

f(ii*i, jj*j+jj-1) …… f(ii*i + ii-1, jj*j+jj-1)

(3)求出缩小的图像

G(x, y) = f’(x,y)的均值

例:

缩小后的图像

例如g11=(f11 +f12 + f21 + f22)/4

算法源代码(java)

/*** 局部均值的图像缩小* @param img 要缩小的图像对象* @param m 缩小后图像的宽* @param n 缩小后图像的高* @return 返回处理后的图像对象*/public static BufferedImage shrink(BufferedImage img, int m, int n) {float k1 = (float)m/img.getWidth();float k2 = (float)n/img.getHeight();      return shrink(img, k1, k2);}/*** 局部均值的图像缩小* @param img 要缩小的图像对象* @param k1 要缩小的列比列* @param k2 要缩小的行比列* @return 返回处理后的图像对象*/public static BufferedImage shrink(BufferedImage img, float k1, float k2) {if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");return null;} float ii = 1/k1;  //采样的行间距float jj = 1/k2; //采样的列间距      int dd = (int)(ii*jj); //int m=0 , n=0;              int imgType = img.getType();int w = img.getWidth();int h = img.getHeight();int m = (int) (k1*w);int n = (int) (k2*h);int[] pix = new int[w*h];pix = img.getRGB(0, 0, w, h, pix, 0, w);System.out.println(w + " * " + h);System.out.println(m + " * " + n);int[] newpix = new int[m*n];for(int j=0; j<n; j++) {for(int i=0; i<m; i++) {int r = 0, g=0, b=0;ColorModel cm = ColorModel.getRGBdefault();               for(int k=0; k<(int)jj; k++) {for(int l=0; l<(int)ii; l++) {r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);}}r = r/dd;g = g/dd;b = b/dd;newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;//255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是//以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red//所以"<<24" "<<16" "<<8"分别表示左移24,16,8位//newpix[j*m + i] = new Color(r,g,b).getRGB();}}BufferedImage imgOut = new BufferedImage( m, n, imgType);imgOut.setRGB(0, 0, m, n, newpix, 0, m);          return imgOut;}
/*** 局部均值的图像缩小* @param img 要缩小的图像对象* @param m 缩小后图像的宽* @param n 缩小后图像的高* @return 返回处理后的图像对象*/public static BufferedImage shrink(BufferedImage img, int m, int n) {float k1 = (float)m/img.getWidth();float k2 = (float)n/img.getHeight();       return shrink(img, k1, k2);}/*** 局部均值的图像缩小* @param img 要缩小的图像对象* @param k1 要缩小的列比列* @param k2 要缩小的行比列* @return 返回处理后的图像对象*/public static BufferedImage shrink(BufferedImage img, float k1, float k2) {if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");return null;} float ii = 1/k1;  //采样的行间距float jj = 1/k2; //采样的列间距      int dd = (int)(ii*jj); //int m=0 , n=0;              int imgType = img.getType();int w = img.getWidth();int h = img.getHeight();int m = (int) (k1*w);int n = (int) (k2*h);int[] pix = new int[w*h];pix = img.getRGB(0, 0, w, h, pix, 0, w);System.out.println(w + " * " + h);System.out.println(m + " * " + n);int[] newpix = new int[m*n];for(int j=0; j<n; j++) {for(int i=0; i<m; i++) {int r = 0, g=0, b=0;ColorModel cm = ColorModel.getRGBdefault();               for(int k=0; k<(int)jj; k++) {for(int l=0; l<(int)ii; l++) {r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);}}r = r/dd;g = g/dd;b = b/dd;newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;//255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是//以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red//所以"<<24" "<<16" "<<8"分别表示左移24,16,8位//newpix[j*m + i] = new Color(r,g,b).getRGB();}}BufferedImage imgOut = new BufferedImage( m, n, imgType);imgOut.setRGB(0, 0, m, n, newpix, 0, m);          return imgOut;}

双线性差值法放图像

子块四个顶点的坐标分别设为(0,0)、(1,0)、(0,1)、(1,1),对应的带处理的像素的坐标(c1,c2),0<c1<1, 0<y<1.则f(x,y)由上到下得到

f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))
f(x,1) = f(0,1) + c1*(f(1,1)-f(0,1))
f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))

例,原图的像素矩阵如下。

将其放大成2.5*1.2倍,双线性插值发,填充顶点如下:

(1)

(2)

1  2  3  4  5  6  7  7

2  3  4  5  7  8  8  8

3  4  5  6  7  8  9  9

3  4  5  6  7  8  9  9

(3)

算法源代码(java)

/*** 双线性插值法图像的放大* @param img 要缩小的图像对象* @param k1 要缩小的列比列* @param k2 要缩小的行比列* @return 返回处理后的图像对象*/public static BufferedImage amplify(BufferedImage img, float k1, float k2) {if(k1 <1 || k2<1) {//如果k1 <1 || k2<1则是图片缩小,不是放大System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");return null;} float ii = 1/k1;  //采样的行间距float jj = (1/k2); //采样的列间距        int dd = (int)(ii*jj); //int m=0 , n=0;int imgType = img.getType();int w = img.getWidth();     //原图片的宽int h = img.getHeight();    //原图片的宽int m = Math.round(k1*w);   //放大后图片的宽int n = Math.round(k2*h); //放大后图片的宽int[] pix = new int[w*h];pix = img.getRGB(0, 0, w, h, pix, 0, w);/*System.out.println(w + " * " + h);System.out.println(m + " * " + n);*/int[] newpix = new int[m*n];for(int j=0; j<h-1; j++){for(int i=0; i<w-1; i++) {int x0 = Math.round(i*k1);int y0 = Math.round(j*k2);int x1, y1;if(i == w-2) {x1 = m-1;} else {x1 = Math.round((i+1)*k1);}                if(j == h-2) {y1 = n-1;} else {y1 = Math.round((j+1)*k2);}             int d1 = x1 - x0;int d2 = y1 - y0;if(0 == newpix[y0*m + x0]) {newpix[y0*m + x0] =  pix[j*w+i];}if(0 == newpix[y0*m + x1]) {if(i == w-2) {newpix[y0*m + x1] = pix[j*w+w-1];} else {newpix[y0*m + x1] =  pix[j*w+i+1];}                   }if(0 == newpix[y1*m + x0]){if(j == h-2) {newpix[y1*m + x0] = pix[(h-1)*w+i];} else {newpix[y1*m + x0] =  pix[(j+1)*w+i];}                  }if(0 == newpix[y1*m + x1]) {if(i==w-2 && j==h-2) {newpix[y1*m + x1] = pix[(h-1)*w+w-1];} else {newpix[y1*m + x1] = pix[(j+1)*w+i+1];}                   }int r, g, b;float c;ColorModel cm = ColorModel.getRGBdefault();               for(int l=0; l<d2; l++) {for(int k=0; k<d1; k++) {if(0 == l) {//f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))if(j<h-1 && newpix[y0*m + x0 + k] == 0) {c = (float)k/d1;r = cm.getRed(newpix[y0*m + x0]) + (int)(c*(cm.getRed(newpix[y0*m + x1]) - cm.getRed(newpix[y0*m + x0])));//newpix[(y0+l)*m + k]g = cm.getGreen(newpix[y0*m + x0]) + (int)(c*(cm.getGreen(newpix[y0*m + x1]) - cm.getGreen(newpix[y0*m + x0])));b = cm.getBlue(newpix[y0*m + x0]) + (int)(c*(cm.getBlue(newpix[y0*m + x1]) - cm.getBlue(newpix[y0*m + x0])));newpix[y0*m + x0 + k] = new Color(r,g,b).getRGB();}if(j+1<h && newpix[y1*m + x0 + k] == 0) {c = (float)k/d1;r = cm.getRed(newpix[y1*m + x0]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y1*m + x0])));g = cm.getGreen(newpix[y1*m + x0]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y1*m + x0])));b = cm.getBlue(newpix[y1*m + x0]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y1*m + x0])));newpix[y1*m + x0 + k] = new Color(r,g,b).getRGB();}//System.out.println(c);} else {//f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))c = (float)l/d2;r = cm.getRed(newpix[y0*m + x0+k]) + (int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k])));g = cm.getGreen(newpix[y0*m + x0+k]) + (int)(c*(cm.getGreen(newpix[y1*m + x0+k]) - cm.getGreen(newpix[y0*m + x0+k])));b = cm.getBlue(newpix[y0*m + x0+k]) + (int)(c*(cm.getBlue(newpix[y1*m + x0+k]) - cm.getBlue(newpix[y0*m + x0+k])));newpix[(y0+l)*m + x0 + k] = new Color(r,g,b).getRGB(); //System.out.println((int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k]))));}             }                   if(i==w-2 || l==d2-1) { //最后一列的计算//f(1,y) = f(1,0) + c2*f(f(1,1)-f(1,0))c = (float)l/d2;r = cm.getRed(newpix[y0*m + x1]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y0*m + x1])));g = cm.getGreen(newpix[y0*m + x1]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y0*m + x1])));b = cm.getBlue(newpix[y0*m + x1]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y0*m + x1])));newpix[(y0+l)*m + x1] = new Color(r,g,b).getRGB(); }}}}/*for(int j=0; j<50; j++){for(int i=0; i<50; i++) {System.out.print(new Color(newpix[j*m + i]).getRed() + "\t");             }System.out.println();}*/BufferedImage imgOut = new BufferedImage( m, n, imgType);imgOut.setRGB(0, 0, m, n, newpix, 0, m);     return imgOut;}

转载于:https://my.oschina.net/verynix/blog/365861

图像的放大与缩小(2)——双线性插值放大与均值缩小相关推荐

  1. 双线性内插怎么缩小_图像的放大与缩小(2)——双线性插值放大与均值缩小

    概述 基于上一节"等距采样法"实现图片放大与缩小的缺点.要对其进行改进,对图像的缩小则可以用"局部均值法",对于图像的放大则可以用"双线性插值法&qu ...

  2. 图像的放大与缩小——双线性插值放大与均值缩小

    原文地址:http://blog.csdn.net/luoweifu/article/details/8069883 概述 基于上一节"等距采样法"实现图片放大与缩小的缺点.要对其 ...

  3. Android之实现点击布局缩小然后再放大动画

    1.需求 现在需要实现点击View先缩小然后再放大效果 2.代码实现 在res的anim目录下面,写anim_small.xml文件 <?xml version="1.0" ...

  4. html之div整体缩小,如何整体放大或缩小div元素

    满意答案 xiaocat9 2014.08.20 采纳率:52%    等级:7 已帮助:211人 实现div层的放大与缩小,参考实例如下: .content { border: 1px solid ...

  5. php 如何缩小一张图片,放大和缩小图片的技巧_PHP

    获得一幅原始的图片后,感觉尺寸不符合要求,这时就要想办法把图片放大或缩小了.当然你也可以用photoshop之类的软件来达到自己的要求,但是如果要经常做这种事情,就显的太繁琐了,所以还是编一个程序来的 ...

  6. 基于mschart控件,绘制工控采集类曲线,可对图像进行缩放,拖动滚动条显示放大后的图像

    基于mschart控件,绘制工控采集类曲线,可对图像进行缩放,拖动滚动条显示放大后的图像,并动态显示曲线上的数值点 在工控.采集.测试类项目中经常需要对采集接收回来的数据进行图像.曲线显示,本人在项目 ...

  7. 图像插值算法:最近邻插值、双线性插值

    插值算法:最近邻插值.双线性插值 文章目录 插值算法:最近邻插值.双线性插值 最近邻插值法(nearest_neighbor) 线性插值 单线性插值法 双线性插值 插值算法有很多种,这里列出关联比较密 ...

  8. body div js 放大图片_jquery图片放大插件鼠标悬停图片放大效果

    都知道jquery都插件是非常强大的,最近分享点jquery插件效果,方便效果开发使用. 一.HTML代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHT ...

  9. 扫除模电障碍(一):基本放大电路和差模放大电路

    目录 前言: 一.基本放大电路 1).共射极放大电路: 2).共集极放大电路: 3).共基极放大电路: 基本放大电路的知识总结: 二.多级放大电路: 1.多级放大电路的耦合方式: 2.差动放大电路 这 ...

最新文章

  1. LINUX自旋锁详解
  2. Spring(七)持久层
  3. java在面板中点击按钮后弹出对话框
  4. 混合高斯模型_高斯混合模型(GMM)
  5. Maven Tomcat 部署
  6. 网络安全系列之二十五 配置SSH
  7. python的模块导入问题_python的模块导入问题
  8. 4. jQuery 事件
  9. 通俗理解什么是隐马尔科夫模型(hmm)
  10. C# 截图ScreenCapture,保存
  11. 迷宫里抓神兽Java游戏_塞尔达传说荒野之息全神兽迷宫进入方法 四大神兽怎么打?-游侠网...
  12. Android插件化开发指南——实践之ViewPager+Fragment优化(预加载和懒加载)
  13. DeepMind重磅开源强化学习框架!覆盖28款游戏,24多个算法
  14. 架构师更多的是和人打交道,说说我见到和听说到的架构师升级步骤和平时的工作内容
  15. 豆瓣的开发语言:无所不能的python
  16. CDATA 数据处理
  17. 【超融合】超融合产品怎么选?
  18. 规范化理论:如何求属性集X关于F的闭包?
  19. C++11精要学习:decltype的功能与使用
  20. 小米电视可以刷android,小米电视不支持安装APK,还敢叫智能电视?一招轻松解除限制...

热门文章

  1. mysql实现组队_TiDB Hackathon 参考选题扩充,组队参赛走起!
  2. POJ2155二维线段树
  3. hdu2363 枚举最短路
  4. 【Java 虚拟机原理】Dalvik 虚拟机 ( 打包 Jar 文件和 Dex 文件 | 反编译 Dex 文件 | 分析 Dex 文件反编译结果 )
  5. 【错误记录】AS 编译报错 ( Android Support plugin 版本太高 | 升级 Android Studio 到最新版本 )
  6. 【Flutter】Image 组件 ( Image 组件简介 | Image 构造函数 | Image.network 构造函数 | Image.asset 构造函数 )
  7. 【RecyclerView】 十五、使用 ItemTouchHelper 实现 RecyclerView 拖动排序 ( ItemTouchHelper 简介 )
  8. 【Android RTMP】Android Studio 集成 x264 开源库 ( Ubuntu 交叉编译 | Android Studio 导入函数库 )
  9. [CentOS7] systemd
  10. arm linux下编译库System.Net.Primitives.dll和System.Xml.XmlSerializer.dll