图像处理之错切变换

简介: 图像处理之错切变换

图像处理之错切变换

一:基本数学知识:

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

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

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

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

相关文章
|
5月前
|
算法 计算机视觉
图像处理之距离变换
图像处理之距离变换
87 8
|
19天前
|
数据可视化 算法 计算机视觉
什么是傅里叶变换?傅里叶变换处理图像的原理是什么?
傅里叶变换是一种强大的数学工具,能够将信号在时域与频域之间进行转换,广泛应用于物理学、信号处理、图像处理等领域。它能够将复杂信号分解为多个简单的正弦波,从而便于分析和处理。在图像处理中,傅里叶变换可以用于去噪、锐化和压缩等操作,通过滤波器选择性地保留或去除特定频率的信息,提高图像质量。
|
5月前
|
算法 Java 计算机视觉
图像处理之积分图算法
图像处理之积分图算法
64 2
|
5月前
|
算法 计算机视觉
图像处理之倒角距离变换
图像处理之倒角距离变换
73 1
|
5月前
|
算法 计算机视觉
图像处理之USM锐化
图像处理之USM锐化
45 0
|
5月前
|
计算机视觉
图像处理之直方图均衡化
图像处理之直方图均衡化
45 0
|
5月前
|
计算机视觉
图像处理之常见二值化方法汇总
图像处理之常见二值化方法汇总
124 0
|
11月前
|
计算机视觉 Python
图像的傅里叶变换(二)
图像的傅里叶变换(二)
105 0
|
11月前
|
数据安全/隐私保护 Python
图像的傅里叶变换(一)
图像的傅里叶变换
111 0
|
监控 计算机视觉
【图像处理】基于二维FIR的特定角度边缘检测(Matlab代码实现)
【图像处理】基于二维FIR的特定角度边缘检测(Matlab代码实现)