图像处理之给定任意四点不规则放缩
基本原理:
计算四个点的增长斜率,使用双线性插值实现像素填充。
废话也懒得说啦,自己看代码吧,我从一个地方抄袭+修改了一下
源来的代码,原因是原来的代码太乱了,也太让人费解了。
运行效果:
滤镜源代码:
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
图像处理之给定任意四点不规则放缩相关推荐
- 给定任意字符串,计算一共能组合成多少个单词bing
CSDN编程挑战里的题目 例如有一个字符串"iinbinbing",截取不同位置的字符'b'.'i'.'n'.'g'组合成单词"bing". 若从1开始计数的话 ...
- python,给定任意列表lst和一个任意值item,返回item在lst中第一次出现的位置
python,给定任意列表lst和一个任意值item,返回item在lst中第一次出现的位置,如果lst中不存在元素item则返回字符串'不存在' 注意时返回字符串 运用list的index,即使有多 ...
- 程序员面试金典——解题总结: 9.18高难度题 18.5有个内含单词的超大文本文件,给定任意两个单词,找出在这个文件中这两个单词的最短距离
#include <iostream> #include <stdio.h> #include <vector> #include <string> # ...
- python编写函数、给定任意字符串_编写函数,给定任意字符串,找出其中只出现一次的字符,如果有多个这样的字符,就全部找出。...
[简答题]编写程序,实现分段函数计算,如下表所示. x y x<0 0 0<=x<5 x 5<=x<10 3x-5 10<=x<20 0.5x-2 20< ...
- 图像处理之卷积---任意卷积核的快速实现
卷积其实是图像处理中最基本的操作,我们常见的一些算法比如:均值模糊.高斯模糊.锐化.Sobel.拉普拉斯.prewitt边缘检测等等一些和领域相关的算法,都可以通过卷积算法实现.只不过由于这些算法的卷 ...
- 圆上任意四点在同一个半圆上的概率
起因是看到了里神乐的微博(微博),一下激起了我的兴趣,但是作为一个已经大学毕业一年多的打工人,数学知识早还给老师了,于是就想用程序模拟点的情况,通过统计频率,来逼近概率. 代码放在这 import j ...
- 图像处理(一)——使用matlab放缩图像
图像放缩:使用双线性插值法和双三次插值法 Introduction In this experiment, matalb is used to zooming and shrinking an ima ...
- java图像处理之实现任意角度图像旋转
原理及步骤: 1.旋转角度:图像顺时针或逆时针旋转的角度,以θ表示,需要用户输入: 2.旋转中心:一般以图像中心作为旋转中心,周围像素围绕其旋转: 3.画布大小:由于图像旋转后产生的图像宽和高与原始图 ...
- 图像处理之计算任意点与轮廓点集中距离最近的点坐标
opencv中计算任意一点P与轮廓C的距离很简单,可以直接调用pointPolygonTest函数获取,但是想要知道轮廓C中哪个点与点P的距离最近却没有现成的函数可用. 思路一:一个最朴实的想法就是获 ...
最新文章
- sqlite php 函数大全,SQLite 表达式
- MinHook - 最小化的 x86/x64 API 钩子库
- C语言中内联函数的作用 inline
- Linux根文件系统的文件镜像,构建小型Linux根文件系统镜像
- explain 之 select_type
- 排查链接是否失效_Linux服务器入侵检测排查方法
- pat1079+1086+1090+1094(树的遍历)感想
- Boost:测试BOOST_BIND_NO_PLACEHOLDERS的程序
- mysql正则通配符全解_mysql正则表达式与通配符
- python3.6安装tensorflow gpu_tensorflow-gpu安装的常见问题及解决方案
- FileSystemObject详解
- JQuery Jcrop—JQuery Jcrop 图像裁剪工具学习
- 数据库MySQL详解(入门学习)
- Java8新特性-Optional类
- python代码 学生上课签到表_一种上课签到系统的制作方法
- bootstrap 让文字显示在响应式图片上
- Excel数据透视表排序
- 软件战场加速剧变!诚迈科技成为Elektrobit中国区增值代理经销商
- 南京大学计算机科学与技术专业博士,南京大学2017年计算机科学与技术系博士招生目录...
- 移动增值业务相关知识
热门文章
- linux Centos系统下mysql主从配置
- RabbitMQ系列(三)RabbitMQ交换器Exchange介绍与实践
- MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
- (转载)构建public APIs与CORS
- iOS 9 适配中出现的坑
- Windows服务工程创建、部署
- virtualbox导致Windows7重启
- MOQL--面向流的统计过滤技术
- 关于max(X,Y),min(X,Y)
- TypeError: tensor is not a torch image.