基本原理:

计算四个点的增长斜率,使用双线性插值实现像素填充。

废话也懒得说啦,自己看代码吧,我从一个地方抄袭+修改了一下

源来的代码,原因是原来的代码太乱了,也太让人费解了。

运行效果:

滤镜源代码:

package com.gloomyfish.filter.study;  import java.awt.Rectangle; import java.awt.image.BufferedImage;  /**  *   * @author gloomy-fish 2013-04-25  *  */ public class PerspectiveFilter extends AbstractBufferedImageOp {  private float x0, y0, x1, y1, x2, y2, x3, y3;   private float dx1, dy1, dx2, dy2, dx3, dy3;     private float A, B, C, D, E, F, G, H, I;    private float a11, a12, a13, a21, a22, a23, a31, a32, a33;     private boolean scaled;     private int width;     private int height;       @Override  public BufferedImage filter(BufferedImage src, BufferedImage dest) {         width = src.getWidth();         height = src.getHeight();         if ( dest == null )             dest = createCompatibleDestImage( src, null );      A = a22*a33 - a32*a23;         B = a31*a23 - a21*a33;         C = a21*a32 - a31*a22;         D = a32*a13 - a12*a33;         E = a11*a33 - a31*a13;         F = a31*a12 - a11*a32;         G = a12*a23 - a22*a13;         H = a21*a13 - a11*a23;         I = a11*a22 - a21*a12;         if ( !scaled ) {             float invWidth = 1.0f/width;             float invHeight = 1.0f/height;              A *= invWidth;             D *= invWidth;             G *= invWidth;             B *= invHeight;             E *= invHeight;             H *= invHeight;         }                int[] inPixels = getRGB( src, 0, 0, width, height, null );         int srcWidth = width;      int srcHeight = height;        int srcWidth1 = width-1;       int srcHeight1 = height-1;         int outX=0, outY=0;       Rectangle transformedSpace = new Rectangle(0, 0, width, height);       transformSpace(transformedSpace);       outX = transformedSpace.x;         outY = transformedSpace.y;         int outWidth = transformedSpace.width;         int outHeight = transformedSpace.height;       // int index = 0;      int[] outPixels = new int[transformedSpace.width];         float[] out = new float[2];        for (int y = 0; y < outHeight; y++) {             for (int x = 0; x < outWidth; x++) {              transformInverse(outX+x, outY+y, out);                int srcX = (int)Math.floor( out[0] );              int srcY = (int)Math.floor( out[1] );              float xWeight = out[0]-srcX;               float yWeight = out[1]-srcY;               int nw, ne, sw, se;                 if ( srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) {                   // Easy case, all corners are in the image                  int i = srcWidth*srcY + srcX;                     nw = inPixels[i];                  ne = inPixels[i+1];                   sw = inPixels[i+srcWidth];                    se = inPixels[i+srcWidth+1];                 } else {                    // Some of the corners are off the image                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight );                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );                     sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );                     se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );              }               outPixels[x] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);            }           setRGB( dest, 0, y, transformedSpace.width, 1, outPixels );         }               return dest;    }       protected void transformSpace( Rectangle rect ) {       if ( scaled ) {             rect.x = (int)Math.min( Math.min( x0, x1 ), Math.min( x2, x3 ) );             rect.y = (int)Math.min( Math.min( y0, y1 ), Math.min( y2, y3 ) );             rect.width = (int)Math.max( Math.max( x0, x1 ), Math.max( x2, x3 ) ) - rect.x;             rect.height = (int)Math.max( Math.max( y0, y1 ), Math.max( y2, y3 ) ) - rect.y;             return;         }    }   final private int getPixel( int[] pixels, int x, int y, int width, int height ) {       if (x < 0 || x >= width || y < 0 || y >= height) {            return pixels[(ImageMath.clamp(y, 0, height-1) * width) + ImageMath.clamp(x, 0, width-1)] & 0x00ffffff;        }       return pixels[ y*width+x ];    }       public PerspectiveFilter() {        this( 0, 0, 1, 0, 1, 1, 0, 1);  }       public PerspectiveFilter(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) {      unitSquareToQuad(x0, y0, x1, y1, x2, y2, x3, y3);   }   protected void transformInverse( int x, int y, float[] out ) {      out[0] = width * (A*x+B*y+C)/(G*x+H*y+I);      out[1] = height * (D*x+E*y+F)/(G*x+H*y+I);     }       public void unitSquareToQuad( float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3 ) {        this.x0 = x0;      this.y0 = y0;      this.x1 = x1;      this.y1 = y1;      this.x2 = x2;      this.y2 = y2;      this.x3 = x3;      this.y3 = y3;              dx1 = x1-x2;       dy1 = y1-y2;       dx2 = x3-x2;       dy2 = y3-y2;       dx3 = x0-x1+x2-x3;        dy3 = y0-y1+y2-y3;                if (dx3 == 0 && dy3 == 0) {             a11 = x1-x0;           a21 = x2-x1;           a31 = x0;          a12 = y1-y0;           a22 = y2-y1;           a32 = y0;          a13 = a23 = 0;        } else {            a13 = (dx3*dy2-dx2*dy3)/(dx1*dy2-dy1*dx2);             a23 = (dx1*dy3-dy1*dx3)/(dx1*dy2-dy1*dx2);             a11 = x1-x0+a13*x1;           a21 = x3-x0+a23*x3;           a31 = x0;          a12 = y1-y0+a13*y1;           a22 = y3-y0+a23*y3;           a32 = y0;      }         a33 = 1;         scaled = false;    }       public void setCorners(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) {        unitSquareToQuad( x0, y0, x1, y1, x2, y2, x3, y3 );         scaled = true;     }      } 

转载请务必注明

转载于:https://blog.51cto.com/gloomyfish/1400301

图像处理之给定任意四点不规则放缩相关推荐

  1. 给定任意字符串,计算一共能组合成多少个单词bing

    CSDN编程挑战里的题目 例如有一个字符串"iinbinbing",截取不同位置的字符'b'.'i'.'n'.'g'组合成单词"bing". 若从1开始计数的话 ...

  2. python,给定任意列表lst和一个任意值item,返回item在lst中第一次出现的位置

    python,给定任意列表lst和一个任意值item,返回item在lst中第一次出现的位置,如果lst中不存在元素item则返回字符串'不存在' 注意时返回字符串 运用list的index,即使有多 ...

  3. 程序员面试金典——解题总结: 9.18高难度题 18.5有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离

    #include <iostream> #include <stdio.h> #include <vector> #include <string> # ...

  4. python编写函数、给定任意字符串_编写函数,给定任意字符串,找出其中只出现一次的字符,如果有多个这样的字符,就全部找出。...

    [简答题]编写程序,实现分段函数计算,如下表所示. x y x<0 0 0<=x<5 x 5<=x<10 3x-5 10<=x<20 0.5x-2 20< ...

  5. 图像处理之卷积---任意卷积核的快速实现

    卷积其实是图像处理中最基本的操作,我们常见的一些算法比如:均值模糊.高斯模糊.锐化.Sobel.拉普拉斯.prewitt边缘检测等等一些和领域相关的算法,都可以通过卷积算法实现.只不过由于这些算法的卷 ...

  6. 圆上任意四点在同一个半圆上的概率

    起因是看到了里神乐的微博(微博),一下激起了我的兴趣,但是作为一个已经大学毕业一年多的打工人,数学知识早还给老师了,于是就想用程序模拟点的情况,通过统计频率,来逼近概率. 代码放在这 import j ...

  7. 图像处理(一)——使用matlab放缩图像

    图像放缩:使用双线性插值法和双三次插值法 Introduction In this experiment, matalb is used to zooming and shrinking an ima ...

  8. java图像处理之实现任意角度图像旋转

    原理及步骤: 1.旋转角度:图像顺时针或逆时针旋转的角度,以θ表示,需要用户输入: 2.旋转中心:一般以图像中心作为旋转中心,周围像素围绕其旋转: 3.画布大小:由于图像旋转后产生的图像宽和高与原始图 ...

  9. 图像处理之计算任意点与轮廓点集中距离最近的点坐标

    opencv中计算任意一点P与轮廓C的距离很简单,可以直接调用pointPolygonTest函数获取,但是想要知道轮廓C中哪个点与点P的距离最近却没有现成的函数可用. 思路一:一个最朴实的想法就是获 ...

最新文章

  1. sqlite php 函数大全,SQLite 表达式
  2. MinHook - 最小化的 x86/x64 API 钩子库
  3. C语言中内联函数的作用 inline
  4. Linux根文件系统的文件镜像,构建小型Linux根文件系统镜像
  5. explain 之 select_type
  6. 排查链接是否失效_Linux服务器入侵检测排查方法
  7. pat1079+1086+1090+1094(树的遍历)感想
  8. Boost:测试BOOST_BIND_NO_PLACEHOLDERS的程序
  9. mysql正则通配符全解_mysql正则表达式与通配符
  10. python3.6安装tensorflow gpu_tensorflow-gpu安装的常见问题及解决方案
  11. FileSystemObject详解
  12. JQuery Jcrop—JQuery Jcrop 图像裁剪工具学习
  13. 数据库MySQL详解(入门学习)
  14. Java8新特性-Optional类
  15. python代码 学生上课签到表_一种上课签到系统的制作方法
  16. bootstrap 让文字显示在响应式图片上
  17. Excel数据透视表排序
  18. 软件战场加速剧变!诚迈科技成为Elektrobit中国区增值代理经销商
  19. 南京大学计算机科学与技术专业博士,南京大学2017年计算机科学与技术系博士招生目录...
  20. 移动增值业务相关知识

热门文章

  1. linux Centos系统下mysql主从配置
  2. RabbitMQ系列(三)RabbitMQ交换器Exchange介绍与实践
  3. MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
  4. (转载)构建public APIs与CORS
  5. iOS 9 适配中出现的坑
  6. Windows服务工程创建、部署
  7. virtualbox导致Windows7重启
  8. MOQL--面向流的统计过滤技术
  9. 关于max(X,Y),min(X,Y)
  10. TypeError: tensor is not a torch image.