java - Java中的图片转换与矩阵乘法不起作用

标签 java image swing transformation matrix-multiplication

我正在研究用 Java 实现图片转换。到目前为止,我已经实现了以下类:

  • 矩阵(保存一个 3x3 矩阵,用于与 vector 相乘)
  • vector (用于与变换矩阵相乘,为原始图像的像素生成新位置)
  • PictureTransformer(转换图像并将新值存储到临时数组中)
  • Picture(保存图像mImage和像素数组mPixels的成员变量,并提供getter和setter方法)
  • Window(用于测试功能的临时类,因为这些类将成为较大程序的一部分)

在测试程序时,我注意到一些奇怪的行为:

  • 无论我使用什么转换,图片都会一直缩放
  • 无论我触发 MouseEvent 的频率如何,转换仅执行一次

我已经修复了 public static Vectormultiply(Matrix a, Vector v); 中算法中的一些错误,因此乘法应该按预期工作。

在解决这些问题几个小时后,我不知道如何解决这个问题。任何帮助将不胜感激!

我希望可以发布整个代码,因为我不太确定哪些部分将有助于解决错误。

这些是类:

窗口:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Window extends JFrame {
    Matrix m;
    Window(int x, int y){
        setBounds(20, 20, x, y);    
        final JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        Image img;
        int[] pix;
        MemoryImageSource m_ImgSrc;
        FileDialog diag = new FileDialog(this); 
        diag.setVisible(true);
        img = getToolkit().getImage(diag.getDirectory()+diag.getFile());
//      getScaledInstance(x,y, Image.SCALE_SMOOTH);
        diag.setFile("");
        MediaTracker mt = new MediaTracker(this);
        mt.addImage(img,0);
        try {
            mt.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Picture bild = new Picture(img);

        PictureTransformer g = new PictureTransformer(bild);
        p.add(g);
        add(p, BorderLayout.CENTER);
        g.repaint();
        setVisible(true);

        p.addMouseListener(new MouseListener(){
            public void mouseClicked(MouseEvent arg0) {
               System.out.println("Mouse-Event");
               m = Matrix.rotate(45.0); //perform rotation by 45°
//             System.out.println(m.v[0][0]);
               g.transform(m);
               p.repaint();
           }
       });

}
    public static void main(String[] args) {
        new Window(640, 480);

    }

}

图片转换器:

import java.awt.Graphics;
import javax.swing.JComponent;

public class PictureTransformer extends JComponent{
    Picture p;
    PictureTransformer(Picture p){
        this.p = p;
    }
    @Override
    public void paintComponent(Graphics g){
        g.drawImage(p.getImage(), 0, 0, 640, 480, this);
    }

    public void transform(Matrix t){ //p.W/p.H = Dimensions of the current picture to transform
         int[] mPixelsResult = new int[p.getPixels().length]; //The temporary array contains the      transformed pixels.
         for(int x = 0; x < p.W; ++x){
         for(int y = 0; y < p.H; ++y){
             Vector v = Matrix.multiply(t, new Vector(x, y)); //Generates a Vector with new x- and y- values.
             if(v.getVectorX() >= 0 && v.getVectorY() >= 0 && v.getVectorX() < p.W && v.getVectorY() < p.H){
                mPixelsResult[p.W* y + x] = p.getPixels()[p.W * v.getVectorY() + v.getVectorX()]; //Stores the pixels at their new location.
             }else{
                    mPixelsResult[p.W * y + x] = 0xFF000000; //Paint the background black, if not covered by the transformed picture.   

            }
        }
    }
    p.setPixels(mPixelsResult); //Overwrite the original pixel-array with the temporary values.
    p.mImage = createImage(p.mImgSrc);
    p.mImage.flush();
    repaint();

    }
}

图片:

import java.awt.*;
import java.awt.image.*;

public class Picture {
    int[] mPixels;
    MemoryImageSource mImgSrc;
    Image mImage;
    final int W = 640; final int H = 480;

    public Picture(Image img)
    {
        mImage = img;
        mPixels = new int[W*H];

       PixelGrabber pg = new PixelGrabber(mImage ,0,0,W,H,mPixels,0,W);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(mPixels);
        mImgSrc = new MemoryImageSource(W,H,mPixels,0,W);

    }
    public int[] getPixels()
    {
        return this.mPixels;
    } 

    public Image getImage()
    {
        return this.mImage;
    }
    public void setPixels(int[] newPix)
    {
        this.mPixels = newPix;
    }
    public void setImage(Image newImg)
    {
        this.mImage = newImg;
    }
}

矩阵

public class Matrix {
    double[][] v;

    Matrix(double[][] v){
       this.v = v;
    }
    /** Creates an Matrix that will used to translate the picture to the coordinates
    * clicked on the screen. 
    **/
    public static Matrix translate(int dx, int dy){
        double dM[][] = {{1, 0, 0}, {0, 1, 0}, {Math.round(-dx), Math.round(-dy), 1}};
        return new Matrix(dM);
    }
    public static Matrix rotate(double a){
        double rad = -(Math.PI * a / 180);
        double dM[][] = {{Math.cos(rad), Math.sin(rad), 0},{Math.sin(rad), Math.cos(rad), 0}, {0, 0, 1}};

        return new Matrix(dM);
    }
    /** Creates an Matrix that will used to scale the picture by the given factor. **/
    public static Matrix scale(double f){
        double dM[][] = {{1/f, 0, 0}, {0, 1/f, 0}, {0, 0, 1}};
        return new Matrix(dM);
    }
    public static Matrix shearX(double sX){
        double dM[][] = {{1, 0, 0}, {-sX, 1, 0}, {0, 0, 1}};
        return new Matrix(dM);
    }
    public static Matrix shearY(double sY){
        double dM[][] = {{1, -sY, 0}, {0, 1, 0}, {0, 0, 1}};
        return new Matrix(dM);
    }
    public static Matrix multiply(Matrix x, Matrix y){
        double[][] p = new double[3][3];
        for(int i = 0; i < x.v.length; ++i){
            for(int j = 0; j < x.v[i].length; j++){
                for(int k = 0; k < 3; k++){
                    p[i][j] += + x.v[k][j] * y.v[i][k];
                }
             }
         }
         return new Matrix(p);  
     }
     public static Vector multiply(Matrix a, Vector v){
         int[] res = new int[a.v[0].length];
         for(int i = 0; i < a.v[0].length; i++){
             for(int j = 0; j < a.v.length; j++){               
             /* Multiplying the Vector with the Matrix.
              * (x)   [a d g]       (a)       (d)       (g)
              * (y) * [b e h] = x * (b) + y * (e) + z * (h)
              * (z)   [c f i]       (c)       (f)       (i)
              *    (x*a + y*d + z*g)
              *  = (x*b + y*e + z*h)
              *    (x*c + y*f + z*i)
              */
                res[i] += a.v[i][j] * v.getVector(j);
            }
        }
         Vector r = new Vector(res[0], res[1]); //Copying the result which represents the new pixel location into an Vector
         return r;
     }
 }

vector

public class Vector {
     private int[] v;
     Vector(int x, int y){
        v = new int[3]; //We'll always have a 3 Vector...
        v[0] = x;
        v[1] = y;
        v[2] = 1;
 //     System.out.println("NEW VECTOR " + v[0] + " "+ v[1]);
    }
    Vector(){
       v = new int[3];
       v[0] = 0;
       v[1] = 0;
       v[2] = 1;
    }
    public int getVectorX(){
        return v[0];
    }
    public int getVectorY(){
        return v[1];
    }

    public int getVectorZ(){
        return v[2];
    } 
    public void setVector(int i, double d){
        v[i] = (int)d;
    }
    public int getVector(int i){
        return v[i];
    }
    public void setVectorX(int i){
        v[0] = i;
    }
    public void setVectorY(int i){
        v[1] = i;
    }    
}

最佳答案

我发现两件事,在 Matrix 类中,我更改了旋转矩阵:

public static Matrix rotate(final double a) {
    final double rad = Math.PI * a / 180;
    final double dM[][] = { { Math.cos(rad), Math.sin(rad), 0 }, { -Math.sin(rad), Math.cos(rad), 0 }, { 0, 0, 1 } };
    return new Matrix(dM);
}

在 PictureTransformer 类转换方法中,我以不同的方式执行新图像创建:

    // p.mImage = createImage(p.mImgSrc);
    final MemoryImageSource mis = new MemoryImageSource(p.W, p.H, mPixelsResult, 0, p.W);
    final Toolkit tk = Toolkit.getDefaultToolkit();
    p.mImage = tk.createImage(mis);
    p.mImage.flush();

结果是图像在窗口中显示旋转 -45°。 这不是解决方案,而是一个起点。

希望对您有所帮助。

关于java - Java中的图片转换与矩阵乘法不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26778240/

相关文章:

java - 文本方面 JTextArea

java - Java 中 writeUTF 和 readUTF 的意外值

python - 使用 OpenCV 自动调整一张纸的彩色照片的对比度和亮度

image - 如何使用 C++ 或 Python 从图像中读取图像描述?

javascript - Chrome 扩展程序 : add image to DOM

java - 类声明范围不明确

java - 无法实例化 QueryTranslatorFactory : org. hibernate.hql.internal.classic.ClassicQueryTranslatorFactory

Java - 线程变量保留以前的值

java - 如何使用Libcore.os设置环境变量

java - 如何更改另一个 java 类中的变量值?