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

简介: 基本原理: 计算四个点的增长斜率,使用双线性插值实现像素填充。 废话也懒得说啦,自己看代码吧,我从一个地方抄袭+修改了一下 源来的代码,原因是原来的代码太乱了,也太让人费解了。 运行效果: 滤镜源代码: package com.

基本原理:

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

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

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

运行效果:


滤镜源代码:

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;
	}
    
}

转载请务必注明

目录
相关文章
|
监控 算法 安全
基于伽马变换自适应修正的全景首尾融合算法
基于伽马变换自适应修正的全景首尾融合算法
|
3月前
|
PHP 计算机视觉
罗德里格斯公式推导,以及如何使用cv2.Rodrigues进行旋转矩阵和旋转向量之间的相互转化
罗德里格斯公式推导,以及如何使用cv2.Rodrigues进行旋转矩阵和旋转向量之间的相互转化
100 0
|
5月前
|
计算机视觉
图像处理之给定任意四点不规则放缩
图像处理之给定任意四点不规则放缩
29 3
|
3月前
|
算法
计算空间物体包围球的两种算法实现
计算空间物体包围球的两种算法实现
47 0
|
5月前
|
算法 BI 计算机视觉
图像处理之积分图应用一(半径无关的快速模糊算法)
图像处理之积分图应用一(半径无关的快速模糊算法)
42 0
|
6月前
|
算法
几何原本
几何原本
59 8
|
6月前
|
机器学习/深度学习 算法 C#
C# | 凸包算法之Jarvis,寻找一组点的边界/轮廓
这篇关于凸包算法的文章,本文使用C#和Jarvis算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 凸包算法有什么用呢? 凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
76 0
|
计算机视觉
第三周作业:matlab将一张图片进行顺时针旋转 20°,做水平镜像,做错切变换,缩小图像处理,并采用双线性插值方法
简介:第三周作业:matlab将一张图片进行顺时针旋转 20°,做水平镜像,做错切变换,缩小图像处理,并采用双线性插值方法
第三周作业:matlab将一张图片进行顺时针旋转 20°,做水平镜像,做错切变换,缩小图像处理,并采用双线性插值方法
三维之外的更高维度,数学家发现了无限可能的黑洞形状
三维之外的更高维度,数学家发现了无限可能的黑洞形状
146 0
|
机器学习/深度学习 人工智能 算法
活久见!像素随机打乱的手写字体图像竟能被非监督学习方法全新重建?
活久见!像素随机打乱的手写字体图像竟能被非监督学习方法全新重建?