图像处理之错切变换

一:基本数学知识:

图像错切变换在图像几何形变方面很实用,常见的错切变换分为X方向与Y方向的

错切变换。相应的数学矩阵分别例如以下:

依据上述矩阵如果P(x1, y1)为错切变换之前的像素点。则错切变换以后相应的像素

P’(x2, y2)当X方向错切变换时:

当Y方向错切变换时:

二:程序实现基本思路

实现图像错切变换时,必须考虑图像将目标像素点坐标变为源相点坐标时小数部分对

像素值的影响,这里通过临近点插值算法实现了目标像素值的计算。依据目标像素计

算源像素的公式能够依据上面的数学公式运算以后分别求的x1,y1的值。因为错切以

后图像会在宽或者高上比原图像大,多出来的这些背景像素默认填充颜色为黑色。

类ShearFilter实现了图像水平或者垂直方向的错切变换,支持角度与背景颜色參数

设置。

三:编程关键点解析

?  计算错切以后图像的宽与高

        double angleValue = (angle/180.0d) * Math.PI;
        outh = vertical ? (int)(height + width * Math.tan(angleValue)) : height;
        outw = vertical ? width : (int)(width + height * Math.tan(angleValue));
        System.out.println("after shear, new width : " + outw);
        System.out.println("after shear, new height: " + outh);

?  依据目标像素点坐标计算源像素点坐标

	double prow = vertical ? row + Math.tan(angleValue) * (col - width) : row;
	double pcol = vertical ?

col : col + Math.tan(angleValue) * (row - height);
        int[] rgb = getPixel(inPixels, width, height, prow, pcol);

?  临近点插值计算目标像素点像素值

private int[] getPixel(int[] input, int width, int height,
		double prow, double pcol) {
	double row = Math.floor(prow);
	double col = Math.floor(pcol);
	if(row < 0 || row >= height) {
		return new int[]{backgroundColor.getRed(),
				backgroundColor.getGreen(),
				backgroundColor.getBlue()};
	}
	if(col < 0 || col >= width) {
		return new int[]{backgroundColor.getRed(),
				backgroundColor.getGreen(),
				backgroundColor.getBlue()};
	}
	double u = vertical ? (prow - row) : pcol - col;
	int nextCol = (int)(col + 1);
	int nextRow = (int)(row + 1);
	if((col + 1) >= width) {
		nextCol = (int)col;
	}
	if((row + 1) >= height) {
		nextRow = (int)row;
	}
	int index1 = (int)(row * width + col);
	int index2 = vertical ? (int)(nextRow * width + col) : (int)(row * width + nextCol);

	int tr1, tr2;
	int tg1, tg2;
	int tb1, tb2;

    tr1 = (input[index1] >> 16) & 0xff;
    tg1 = (input[index1] >> 8) & 0xff;
    tb1 = input[index1] & 0xff;

    tr2 = (input[index2] >> 16) & 0xff;
    tg2 = (input[index2] >> 8) & 0xff;
    tb2 = input[index2] & 0xff;

    int tr = (int)(tr1 * (1-u) + tr2 * u);
    int tg = (int)(tg1 * (1-u) + tg2 * u);
    int tb = (int)(tb1 * (1-u) + tb2 * u);

	return new int[]{tr, tg, tb};
}

四:执行效果

五:类ShearFilter完整代码

package com.gloomyfish.filter.study;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;

public class ShearFilter extends AbstractBufferedImageOp {
	private int outw;
	private int outh;
	private double angle;
	private Color backgroundColor;
	private boolean vertical;

	public void setVertical(boolean vertical) {
		this.vertical = vertical;
	}

	public ShearFilter()
	{
		backgroundColor = Color.BLACK;
		vertical = false;
		this.angle = 20;
	}

	public int getOutw() {
		return outw;
	}
	public void setOutw(int outw) {
		this.outw = outw;
	}
	public int getOuth() {
		return outh;
	}
	public void setOuth(int outh) {
		this.outh = outh;
	}
	public double getAngle() {
		return angle;
	}
	public void setAngle(double angle) {
		this.angle = angle;
	}
	public Color getBackgroundColor() {
		return backgroundColor;
	}
	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}
	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		int width = src.getWidth();
        int height = src.getHeight();

        double angleValue = (angle/180.0d) * Math.PI;
        outh = vertical ? (int)(height + width * Math.tan(angleValue)) : height;
        outw = vertical ? width : (int)(width + height * Math.tan(angleValue));
        System.out.println("after shear, new width : " + outw);
        System.out.println("after shear, new height: " + outh);

        int[] inPixels = new int[width*height];
        int[] outPixels = new int[outh*outw];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        for(int row=0; row<outh; row++) {
        	int ta = 0;
        	for(int col=0; col<outw; col++) {
				double prow = vertical ? row + Math.tan(angleValue) * (col - width) : row;
				double pcol = vertical ?

col : col + Math.tan(angleValue) * (row - height);
        		int[] rgb = getPixel(inPixels, width, height, prow, pcol);
        		index = row * outw + col;
        		outPixels[index] = (ta << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
        	}
        }

        if ( dest == null )
        	dest = createCompatibleDestImage( src, null );
        setRGB( dest, 0, 0, outw, outh, outPixels );
        return dest;
	}

	private int[] getPixel(int[] input, int width, int height,
			double prow, double pcol) {
		double row = Math.floor(prow);
		double col = Math.floor(pcol);
		if(row < 0 || row >= height) {
			return new int[]{backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue()};
		}
		if(col < 0 || col >= width) {
			return new int[]{backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue()};
		}
		double u = vertical ? (prow - row) : pcol - col;
		int nextCol = (int)(col + 1);
		int nextRow = (int)(row + 1);
		if((col + 1) >= width) {
			nextCol = (int)col;
		}
		if((row + 1) >= height) {
			nextRow = (int)row;
		}
		int index1 = (int)(row * width + col);
		int index2 = vertical ? (int)(nextRow * width + col) : (int)(row * width + nextCol);

		int tr1, tr2;
		int tg1, tg2;
		int tb1, tb2;

        tr1 = (input[index1] >> 16) & 0xff;
        tg1 = (input[index1] >> 8) & 0xff;
        tb1 = input[index1] & 0xff;

        tr2 = (input[index2] >> 16) & 0xff;
        tg2 = (input[index2] >> 8) & 0xff;
        tb2 = input[index2] & 0xff;

        int tr = (int)(tr1 * (1-u) + tr2 * u);
        int tg = (int)(tg1 * (1-u) + tg2 * u);
        int tb = (int)(tb1 * (1-u) + tb2 * u);

		return new int[]{tr, tg, tb};
	}

    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
        if ( dstCM == null )
            dstCM = src.getColorModel();
        return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(outw, outh), dstCM.isAlphaPremultiplied(), null);
    }

}

下半年事情比較多。博客一直没有更新,感谢众多网友的关注与留言

我会继续努力的!再次声明一下:请不要向我索取源代码!谢谢!

代码我在整理中,终于我会开源让大家自己下载,请耐心等待!

时间: 2024-08-06 06:13:46

图像处理之错切变换的相关文章

Android图像处理之图形特效处理

一.Android变形矩阵--Matricx: 跟Android图像的色彩处理基本一样,只是将ColorMatrix换成了Matrix,ColorMatrix是4*5的矩阵,Matrix是3*3的.每个像素点表达了其坐标的X.Y信息: 当使用变换矩阵去处理每一个像素点的时候,与颜色矩阵的矩阵乘法一样,计算公式如下所示: 通常情况下,会让g=h=0,i=1,这样就使1=gX+hY+i    恒成立.因此,只需着重关注上面几个参数即可. 与色彩变换矩阵的初始矩阵一样,图形变换矩阵也有一个初始矩阵.就

【OpenCV学堂】图像处理开发者基本知识图谱

原创图像处理与机器学习文章,关注微信公众号[OpenCV学堂] 作为一个入门的图像处理开发者与工程师,要掌握的知识点也不少,不要看每个知识点只有几个字,可以说每个都代表一个算法,都有数学知识,都需要你认真领悟学习!不认真的学习一年两年你不可能做到下面的全部领悟与贯通,成为一个合格的图像处理与机器学习开发者,一个人工智能时代的程序员! 图像像素操作 - 几何运算-加减乘除 - 逻辑运算-与或非取反 - 像素读写 - 通道混合与调整 - 对比度与亮度调整 图像变换 - 插值(zoom in或out)

图像处理开发者必读 - 做图像处理开发工程师很容易,只要会这些即可!

小编作为一个图像与计算机视觉的开发者,总结了一下作为图像处理开发工程师应该知道或者掌握的图像处理知识点.跟大家分享一下,以备大家学习方便. 图像像素操作 - 几何运算-加减乘除 - 逻辑运算-与或非取反 - 像素读写 - 通道混合与调整 - 对比度与亮度调整   图像几何变换 - 插值(zoom in或out) - 旋转(rotate) - 透视变换 - 错切变换 - 翻转   像素统计 - 计算均值与方差 - 计算直方图 - 计算最大最小 - 计算像素内方差   色彩空间 - RGB - HS

Matrix进行图像处理

矩阵的规则: 矩阵A与矩阵B能进行乘法操作的条件: 当矩阵A的列数等于矩阵B的行数时,A与B可以相乘. 矩阵C的行数等于矩阵A的行数,C的列数等于B的列数. 乘积C的第  行第  列的元素  等于矩阵A的第  行的元素与矩阵B的第  列对应元素乘积之和. 例如: , 定义矩阵 注意 矩阵乘法一般不满足交换律.即: 一. 平移变换 假定有一个点的坐标是 ,将其移动到 ,再假定在x轴和y轴方向移动的大小分别为: 如下图所示: 不难知道: 如果用矩阵来表示的话,就可以写成:   二. 旋转变换 2.1

图像处理之基础---仿射变换

几种典型的仿射变换: public static AffineTransform getTranslateInstance(doubl 仿射变换-例 e tx, double ty) 平移变换,将每一点移动到(x+tx, y+ty),变换矩阵为: [ 1 0 tx ] [ 0 1 ty ] [ 0 0 1 ] (译注:平移变换是一种“刚体变换”,rigid-body transformation,中学学过的物理,都知道啥叫“刚体”吧,就是不会产生形变的理想物体,平移当然不会改变二维图形的形状.同

他们实际上控制的定义很easy5/12

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 近期龙体欠安.非常多任务都堆着,虽说如此.依然没有停下学习的步伐,尽管偶尔还会有点头痛.可是孤依然在学习--自赞一个~ 在1/3中我们结束了所有的Paint方法学习还略带地说了下Matri的简单使用方法,这两节呢,我们将甩掉第二个陌生又熟悉的情妇:Canvas. Canvas从我们该系列教程的第一节起就嘚啵嘚啵个没完没了.差点儿每一

Android中图像变换Matrix的原理、代码验证和应用(二)

注:本篇文章为转载文章,因为原文格式排版较乱,但是内容非常棒,所以整理一下,方便以后查看. 查看原文请戳:http://blog.csdn.net/pathuang68/article/details/6991988 Matrix介绍文章请戳:http://blog.csdn.net/pathuang68/article/details/6991867 package com.pat.testtransformmatrix; import android.app.Activity; import

Android Matrix(转)

Matrix的数学原理 平移变换 旋转变换 缩放变换 错切变换 对称变换 代码验证 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matrix的对图像的处理可分为四类基本变换: Translate           平移变换 Rotate                旋转变换 Scale                  缩放变换 Skew          

Android Matrix

转自 :http://www.cnblogs.com/qiengo/archive/2012/06/30/2570874.html#code Matrix的数学原理 平移变换 旋转变换 缩放变换 错切变换 对称变换 代码验证 Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下: Matrix的对图像的处理可分为四类基本变换: Translate           平移变