原文地址:http://blog.csdn.net/luoweifu/article/details/8069883

概述

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

效果如下:

     

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)

[java] view plaincopy
  1. /**
  2. * 局部均值的图像缩小
  3. * @param img 要缩小的图像对象
  4. * @param m 缩小后图像的宽
  5. * @param n 缩小后图像的高
  6. * @return 返回处理后的图像对象
  7. */
  8. public static BufferedImage shrink(BufferedImage img, int m, int n) {
  9. float k1 = (float)m/img.getWidth();
  10. float k2 = (float)n/img.getHeight();
  11. return shrink(img, k1, k2);
  12. }
  13. /**
  14. * 局部均值的图像缩小
  15. * @param img 要缩小的图像对象
  16. * @param k1 要缩小的列比列
  17. * @param k2 要缩小的行比列
  18. * @return 返回处理后的图像对象
  19. */
  20. public static BufferedImage shrink(BufferedImage img, float k1, float k2) {
  21. if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小
  22. System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
  23. return null;
  24. }
  25. float ii = 1/k1;    //采样的行间距
  26. float jj = 1/k2; //采样的列间距
  27. int dd = (int)(ii*jj);
  28. //int m=0 , n=0;
  29. int imgType = img.getType();
  30. int w = img.getWidth();
  31. int h = img.getHeight();
  32. int m = (int) (k1*w);
  33. int n = (int) (k2*h);
  34. int[] pix = new int[w*h];
  35. pix = img.getRGB(0, 0, w, h, pix, 0, w);
  36. System.out.println(w + " * " + h);
  37. System.out.println(m + " * " + n);
  38. int[] newpix = new int[m*n];
  39. for(int j=0; j<n; j++) {
  40. for(int i=0; i<m; i++) {
  41. int r = 0, g=0, b=0;
  42. ColorModel cm = ColorModel.getRGBdefault();
  43. for(int k=0; k<(int)jj; k++) {
  44. for(int l=0; l<(int)ii; l++) {
  45. r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  46. g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  47. b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  48. }
  49. }
  50. r = r/dd;
  51. g = g/dd;
  52. b = b/dd;
  53. newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;
  54. //255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是
  55. //以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red
  56. //所以"<<24" "<<16" "<<8"分别表示左移24,16,8位
  57. //newpix[j*m + i] = new Color(r,g,b).getRGB();
  58. }
  59. }
  60. BufferedImage imgOut = new BufferedImage( m, n, imgType);
  61. imgOut.setRGB(0, 0, m, n, newpix, 0, m);
  62. return imgOut;
  63. }
[java] view plaincopy
  1. /**
  2. * 局部均值的图像缩小
  3. * @param img 要缩小的图像对象
  4. * @param m 缩小后图像的宽
  5. * @param n 缩小后图像的高
  6. * @return 返回处理后的图像对象
  7. */
  8. public static BufferedImage shrink(BufferedImage img, int m, int n) {
  9. float k1 = (float)m/img.getWidth();
  10. float k2 = (float)n/img.getHeight();
  11. return shrink(img, k1, k2);
  12. }
  13. /**
  14. * 局部均值的图像缩小
  15. * @param img 要缩小的图像对象
  16. * @param k1 要缩小的列比列
  17. * @param k2 要缩小的行比列
  18. * @return 返回处理后的图像对象
  19. */
  20. public static BufferedImage shrink(BufferedImage img, float k1, float k2) {
  21. if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小
  22. System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
  23. return null;
  24. }
  25. float ii = 1/k1;    //采样的行间距
  26. float jj = 1/k2; //采样的列间距
  27. int dd = (int)(ii*jj);
  28. //int m=0 , n=0;
  29. int imgType = img.getType();
  30. int w = img.getWidth();
  31. int h = img.getHeight();
  32. int m = (int) (k1*w);
  33. int n = (int) (k2*h);
  34. int[] pix = new int[w*h];
  35. pix = img.getRGB(0, 0, w, h, pix, 0, w);
  36. System.out.println(w + " * " + h);
  37. System.out.println(m + " * " + n);
  38. int[] newpix = new int[m*n];
  39. for(int j=0; j<n; j++) {
  40. for(int i=0; i<m; i++) {
  41. int r = 0, g=0, b=0;
  42. ColorModel cm = ColorModel.getRGBdefault();
  43. for(int k=0; k<(int)jj; k++) {
  44. for(int l=0; l<(int)ii; l++) {
  45. r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  46. g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  47. b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
  48. }
  49. }
  50. r = r/dd;
  51. g = g/dd;
  52. b = b/dd;
  53. newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;
  54. //255<<24 | r<<16 | g<<8 | b  这个公式解释一下,颜色的RGB在内存中是
  55. //以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red
  56. //所以"<<24" "<<16" "<<8"分别表示左移24,16,8位
  57. //newpix[j*m + i] = new Color(r,g,b).getRGB();
  58. }
  59. }
  60. BufferedImage imgOut = new BufferedImage( m, n, imgType);
  61. imgOut.setRGB(0, 0, m, n, newpix, 0, m);
  62. return imgOut;
  63. }

双线性差值法放图像

子块四个顶点的坐标分别设为(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)

[java] view plaincopy
  1. /**
  2. * 双线性插值法图像的放大
  3. * @param img 要缩小的图像对象
  4. * @param k1 要缩小的列比列
  5. * @param k2 要缩小的行比列
  6. * @return 返回处理后的图像对象
  7. */
  8. public static BufferedImage amplify(BufferedImage img, float k1, float k2) {
  9. if(k1 <1 || k2<1) {//如果k1 <1 || k2<1则是图片缩小,不是放大
  10. System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
  11. return null;
  12. }
  13. float ii = 1/k1;    //采样的行间距
  14. float jj = (1/k2); //采样的列间距
  15. int dd = (int)(ii*jj);
  16. //int m=0 , n=0;
  17. int imgType = img.getType();
  18. int w = img.getWidth();     //原图片的宽
  19. int h = img.getHeight();    //原图片的宽
  20. int m = Math.round(k1*w);   //放大后图片的宽
  21. int n = Math.round(k2*h);   //放大后图片的宽
  22. int[] pix = new int[w*h];
  23. pix = img.getRGB(0, 0, w, h, pix, 0, w);
  24. /*System.out.println(w + " * " + h);
  25. System.out.println(m + " * " + n);*/
  26. int[] newpix = new int[m*n];
  27. for(int j=0; j<h-1; j++){
  28. for(int i=0; i<w-1; i++) {
  29. int x0 = Math.round(i*k1);
  30. int y0 = Math.round(j*k2);
  31. int x1, y1;
  32. if(i == w-2) {
  33. x1 = m-1;
  34. } else {
  35. x1 = Math.round((i+1)*k1);
  36. }
  37. if(j == h-2) {
  38. y1 = n-1;
  39. } else {
  40. y1 = Math.round((j+1)*k2);
  41. }
  42. int d1 = x1 - x0;
  43. int d2 = y1 - y0;
  44. if(0 == newpix[y0*m + x0]) {
  45. newpix[y0*m + x0] =  pix[j*w+i];
  46. }
  47. if(0 == newpix[y0*m + x1]) {
  48. if(i == w-2) {
  49. newpix[y0*m + x1] = pix[j*w+w-1];
  50. } else {
  51. newpix[y0*m + x1] =  pix[j*w+i+1];
  52. }
  53. }
  54. if(0 == newpix[y1*m + x0]){
  55. if(j == h-2) {
  56. newpix[y1*m + x0] = pix[(h-1)*w+i];
  57. } else {
  58. newpix[y1*m + x0] =  pix[(j+1)*w+i];
  59. }
  60. }
  61. if(0 == newpix[y1*m + x1]) {
  62. if(i==w-2 && j==h-2) {
  63. newpix[y1*m + x1] = pix[(h-1)*w+w-1];
  64. } else {
  65. newpix[y1*m + x1] = pix[(j+1)*w+i+1];
  66. }
  67. }
  68. int r, g, b;
  69. float c;
  70. ColorModel cm = ColorModel.getRGBdefault();
  71. for(int l=0; l<d2; l++) {
  72. for(int k=0; k<d1; k++) {
  73. if(0 == l) {
  74. //f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))
  75. if(j<h-1 && newpix[y0*m + x0 + k] == 0) {
  76. c = (float)k/d1;
  77. 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]
  78. g = cm.getGreen(newpix[y0*m + x0]) + (int)(c*(cm.getGreen(newpix[y0*m + x1]) - cm.getGreen(newpix[y0*m + x0])));
  79. b = cm.getBlue(newpix[y0*m + x0]) + (int)(c*(cm.getBlue(newpix[y0*m + x1]) - cm.getBlue(newpix[y0*m + x0])));
  80. newpix[y0*m + x0 + k] = new Color(r,g,b).getRGB();
  81. }
  82. if(j+1<h && newpix[y1*m + x0 + k] == 0) {
  83. c = (float)k/d1;
  84. r = cm.getRed(newpix[y1*m + x0]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y1*m + x0])));
  85. g = cm.getGreen(newpix[y1*m + x0]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y1*m + x0])));
  86. b = cm.getBlue(newpix[y1*m + x0]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y1*m + x0])));
  87. newpix[y1*m + x0 + k] = new Color(r,g,b).getRGB();
  88. }
  89. //System.out.println(c);
  90. } else {
  91. //f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))
  92. c = (float)l/d2;
  93. r = cm.getRed(newpix[y0*m + x0+k]) + (int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k])));
  94. g = cm.getGreen(newpix[y0*m + x0+k]) + (int)(c*(cm.getGreen(newpix[y1*m + x0+k]) - cm.getGreen(newpix[y0*m + x0+k])));
  95. b = cm.getBlue(newpix[y0*m + x0+k]) + (int)(c*(cm.getBlue(newpix[y1*m + x0+k]) - cm.getBlue(newpix[y0*m + x0+k])));
  96. newpix[(y0+l)*m + x0 + k] = new Color(r,g,b).getRGB();
  97. //System.out.println((int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k]))));
  98. }
  99. }
  100. if(i==w-2 || l==d2-1) { //最后一列的计算
  101. //f(1,y) = f(1,0) + c2*f(f(1,1)-f(1,0))
  102. c = (float)l/d2;
  103. r = cm.getRed(newpix[y0*m + x1]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y0*m + x1])));
  104. g = cm.getGreen(newpix[y0*m + x1]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y0*m + x1])));
  105. b = cm.getBlue(newpix[y0*m + x1]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y0*m + x1])));
  106. newpix[(y0+l)*m + x1] = new Color(r,g,b).getRGB();
  107. }
  108. }
  109. }
  110. }
  111. /*
  112. for(int j=0; j<50; j++){
  113. for(int i=0; i<50; i++) {
  114. System.out.print(new Color(newpix[j*m + i]).getRed() + "\t");
  115. }
  116. System.out.println();
  117. }
  118. */
  119. BufferedImage imgOut = new BufferedImage( m, n, imgType);
  120. imgOut.setRGB(0, 0, m, n, newpix, 0, m);
  121. return imgOut;
  122. }

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

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

    2019独角兽企业重金招聘Python工程师标准>>> 概述 基于上一节"等距采样法"实现图片放大与缩小的缺点.要对其进行改进,对图像的缩小则可以用"局 ...

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

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

  3. Android imageview 双击放大缩小手势放大缩小自由滑动

    public class ZoomImageView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener {pri ...

  4. Android实现按住缩小 松开放大的效果

    在开发过程中  我们有时候会使用一种效果,如按钮按下时会缩小,松开变回原大小,下面我们试一下实现这个效果. 主要的思想就是使用view的setScaleX  和setScaleY这两个方法 ,在onT ...

  5. 如何将CAD图纸图形同比例缩小或者放大

    今天记录:如何将CAD图纸图形同比例缩小或者放大,来满足我们一些需需求 近来有一个项目,需要再硅胶面贴做透光,但是我们外包公司的结构图纸灯孔画的偏大,所以就自己改了下,以此记录 1.打开图纸,需要先将 ...

  6. 高德地图多边形覆盖物等间距缩小或者放大算法

    需求: 高德地图多边形覆盖物等间距缩小,效果如下 原理可参考:https://blog.csdn.net/weixin_38169413/article/details/101161891 实现 第一 ...

  7. 常规放大电路和差分放大电路

    常规放大电路和差分放大电路 0.小叙闲言 有一个两相四线的步进电机,需测量其A.B两相的电流大小,电机线圈的电阻为0.6Ω,电感为2.2mH.打算在A.B相各串接一个0.1Ω的采样电阻,然后通过放大电 ...

  8. 【模电笔记】4.多级放大与集成运算放大电路

    目录 一.前言 1.事先声明 2.学习感悟 二.正文 1.集成运算放大器简介 (1)概念 (2)好处 (3)符号 (4)电压传输特性 (5)组成 (6)一个直观感受 2.多级放大电路的耦合方式 (1) ...

  9. R语言ggplot2可视化散点图并使用scale_y_log10函数配置Y轴对数坐标、使用ggforce包的facet_zoom函数将可视化结果中需要突出放大的区域进行放大(Zoom in)

    R语言ggplot2可视化散点图并使用scale_y_log10函数配置Y轴对数坐标.使用ggforce包的facet_zoom函数将可视化结果中需要突出放大的区域进行放大(Zoom in) 目录

最新文章

  1. Swift 中使用 SQLite——批量更新(事务处理)
  2. 微信网页JSDK接口-wx.chooseImage问题
  3. 记录下openstack部署和使用时遇到的一些问题
  4. HTML 的特殊字符转换转义符,的两种方法。
  5. mac下shell给文件名批量加前缀
  6. python合并两个数据框_python 学习的第五天 数据框合并
  7. Fater R-CNN 整体把握
  8. JAVA第三方包导入但找不到类,解决:导入第三方包报错java.lang.NoClassDefFoundError:XXX.XXX,XXXXXX...
  9. 文件上传fileupload文件接收
  10. NYOJ-915 +-字符串(贪心)
  11. 财税打印机LQ 670K+ win10驱动
  12. 完美数简介及算法分析
  13. Java面试——多线程面试题
  14. 趋势(被亚信并购)杀毒软件强制卸载
  15. 逻辑上的“谬误”真的是我们应该所认为的错误吗?
  16. 更换主板后 Office无法激活问题解决
  17. 会议OA项目之我的会议(会议排座送审)
  18. input隐藏边框轮廓、输入框输入提示
  19. SpringBoot从入门到精通-佟刚-专题视频课程
  20. 论项目管理与可行性分析的重要性

热门文章

  1. Oracle 创建表空间与用户
  2. C#中判断服务器图片是否存在
  3. [C++ primer]运行时类型识别(RTTI)
  4. 线程安全和线程不安全理解
  5. ACM之八数码问题----BFS搜索----数独游戏的模拟(下)
  6. ASIHTTPRequest类库简介
  7. 【Java从0到架构师】Spring - IoC 控制反转、DI 依赖注入
  8. Python Type Hint类型注解
  9. 搞不明白老板想要看哪种报表,熬夜做到两点也是白费28
  10. 新零售不简单,当初马云自己都没解释清楚!