zoukankan      html  css  js  c++  java
  • 图像处理之错切变换

    图像处理之错切变换

    一:基本数学知识:

    图像错切变换在图像几何形变方面很实用,常见的错切变换分为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); } }

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

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

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

  • 相关阅读:
    GitBook基本使用
    Window 远程桌面漏洞风险,各个厂家的扫描修复方案(CVE-2019-0708)
    应急响应实战笔记(续)
    不同系统下,复制文件时新文件的日期区别
    Window应急响应(六):NesMiner挖矿病毒
    利用python输出000至999中间的数
    揭秘骗局:这是一张会变的图片
    如何查看github排行热度
    zabbix使用自动发现功能批量监控服务器端口的可用性
    使用python脚本批量设置nginx站点的rewrite规则
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5092977.html
Copyright © 2011-2022 走看看