0

我正在尝试使用 Jpanel 和 Jform 加载图片并对其执行一些操作,到目前为止图片加载,但是当我单击执行操作时,它什么也没做。事实上,它会通过点击事件,但我猜这个问题是,repaint() 可能在那里无法正常工作。这是代码:

    public class SeamCarving 
   {

  static  SeamCarving frame=new SeamCarving();

        public SeamCarving() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException |  IllegalAccessException | UnsupportedLookAndFeelException ex) {
            }

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            frame.add(new TestPane());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}



    public class TestPane extends JPanel {

  private BufferedImage input;
  BufferedImage[] toPaint;

    public TestPane() {
        try {

          input = ImageIO.read(new File("C:\\Users\\SONY\\Desktop\\my-pic\\Fatima.jpg")); 
          toPaint = new BufferedImage[]{input};

            toPaint = new BufferedImage[1];
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        setLayout(new GridBagLayout());
        JButton loadButton = new JButton("Load");
        loadButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                BufferedImage out = input;
                out = input; 
                toPaint[0] = out;
                repaint();
                System.out.println("Do Something Clicked");
            }
        });
        add(loadButton);
      JButton startButton = new JButton("Start");


    add(startButton);
    startButton.addActionListener(new ActionListener() {
    BufferedImage out = input;

            @Override
            public void actionPerformed(ActionEvent ae) {
                 out = deleteVerticalSeam(out);
                 System.out.println("Do Something Clicked");
                toPaint[0]=out;
    repaint();    
            }
        });

    }

我想要的是这一行: out = deleteVerticalSeam(out);

但它根本不影响照片。 编辑 如果像下面这样做,它将起作用。但我想要按钮和面板

public class SeamCarving
{
public static void main(String[] args) throws IOException {
    final BufferedImage input = ImageIO.read(new File(args[0]));


    final BufferedImage[] toPaint = new BufferedImage[]{input};
    final Frame frame = new Frame("Seams") {

        @Override
        public void update(Graphics g) {
            final BufferedImage im = toPaint[0];
            if (im != null) {
                g.clearRect(0,0,getWidth(), getHeight());
                g.drawImage(im,0,0,this);
            }
        }
    };
    frame.setSize(input.getWidth(), input.getHeight());
    frame.setVisible(true);

    BufferedImage out = input;
    for(int i = 0; i < 200; i++) {
        out = deleteVerticalSeam(out);
        toPaint[0]=out;
        frame.repaint();
    }
}

deleteVerticalSeam

    private static BufferedImage deleteVerticalSeam(BufferedImage input) {
    return deleteVerticalSeam(input, findVerticalSeam(input));
}

private static BufferedImage deleteVerticalSeam(final BufferedImage input, final int[] seam) {
    int w = input.getWidth(), h = input.getHeight();
    final BufferedImage out = new BufferedImage(w-1,h, BufferedImage.TYPE_INT_ARGB);

    for(int y = 0; y < h; y++) {
        for(int x = 0; x < seam[y]; x++) {
                out.setRGB(x,y,input.getRGB(x, y));
        }
        for(int x = seam[y]+1; x < w; x++) {
                out.setRGB(x-1,y,input.getRGB(x, y));
        }
    }
    return out;
}

private static int[] findVerticalSeam(BufferedImage input) {
    final int w = input.getWidth(), h = input.getHeight();
    final FloatImage intensities = FloatImage.fromBufferedImage(input);
    final FloatImage energy = computeEnergy(intensities);

    final FloatImage minima = FloatImage.createSameSize(energy);
    //First row is equal to the energy
    for(int x = 0; x < w; x++) {
        minima.set(x,0, energy.get(x,0));
    }

    //I assume that the rightmost pixel column in the energy image is garbage
    for(int y = 1; y < h; y++) {
        minima.set(0,y, energy.get(0,y) + min(minima.get(0, y - 1),
                minima.get(1, y - 1)));

        for(int x = 1; x < w-2; x++) {
            final float sum = energy.get(x,y) + min(min(minima.get(x - 1, y - 1),
                    minima.get(x, y - 1)),minima.get(x + 1, y - 1));
            minima.set(x,y, sum);
        }
        minima.set(w-2,y, energy.get(w-2,y) + min(minima.get(w-2, y - 1),minima.get(w-3, y - 1)));
    }

    //We find the minimum seam
    float minSum = Float.MAX_VALUE;
    int seamTip = -1;
    for(int x = 1; x < w-1; x++) {
        final float v = minima.get(x, h-1);
        if(v < minSum) {
            minSum=v;
            seamTip=x;
        }
    }

    //Backtrace the seam
    final int[] seam = new int[h];
    seam[h-1]=seamTip;
    for(int x = seamTip, y = h-1; y > 0; y--) {
        float left = x>0?minima.get(x-1, y-1):Float.MAX_VALUE;
        float up = minima.get(x, y-1);
        float right = x+1<w?minima.get(x+1, y-1):Float.MAX_VALUE;
        if(left < up && left < right) x=x-1;
        else if(right < up && right < left) x= x+1;
        seam[y-1]=x;
    }

    return seam;
}

floatimage 公共最终类 FloatImage 扩展 JFrame{

private final int width;
private final int height;
private final float[] data;

public FloatImage(int width, int height) {
    this.width = width;
    this.height = height;
    this.data = new float[width*height];
}

public int getWidth() {
    return width;
}

public int getHeight() {
    return height;
}

public float get(final int x, final int y) {
    if(x < 0 || x >= width) throw new IllegalArgumentException("x: " + x);
    if(y < 0 || y >= height) throw new IllegalArgumentException("y: " + y);
    return data[x+y*width];
}

public void set(final int x, final int y, float value) {
    if(x < 0 || x >= width) throw new IllegalArgumentException("x: " + x);
    if(y < 0 || y >= height) throw new IllegalArgumentException("y: " + y);
    data[x+y*width] = value;
}

public static FloatImage createSameSize(final BufferedImage sample) {
    return new FloatImage(sample.getWidth(), sample.getHeight());
}

public static FloatImage createSameSize(final FloatImage sample) {
    return new FloatImage(sample.getWidth(), sample.getHeight());
}

public static FloatImage fromBufferedImage(final BufferedImage src) {
    final int width = src.getWidth();
    final int height = src.getHeight();
    final FloatImage result = new FloatImage(width, height);
    for(int x = 0; x < width; x++) {
        for(int y = 0; y < height; y++) {
            final int argb = src.getRGB(x, y);
            int r = (argb >>> 16) & 0xFF;
            int g = (argb >>> 8) & 0xFF;
            int b = argb & 0xFF;
            result.set(x,y, (r*0.3f+g*0.59f+b*0.11f)/255);
        }
    }
    return result;
}
public BufferedImage toBufferedImage(float scale) {
    final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    for(int x = 0; x < width; x++) {
        for(int y = 0; y < height; y++) {
            final int intensity = ((int) (get(x, y) * scale)) & 0xFF;
            result.setRGB(x,y,0xFF000000 | intensity | intensity << 8 | intensity << 16);
        }
    }
    return result;
}

}

4

1 回答 1

3

我“认为”你的基本问题从这里开始......

startButton.addActionListener(new ActionListener() {
    BufferedImage out = input;

    @Override
    public void actionPerformed(ActionEvent ae) {
        out = deleteVerticalSeam(out);
        System.out.println("Do Something Clicked");
        toPaint[0]=out;
        repaint();    
    }
});

尝试删除实例变量out...

startButton.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent ae) {
        BufferedImage out = deleteVerticalSeam(input);
        System.out.println("Do Something Clicked");
        toPaint[0]=out;
        repaint();    
    }
});

更新

我已经更新了ActionListener工作更像......

startButton.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent ae) {
        BufferedImage out = deleteVerticalSeam(toPaint[0]);
        System.out.println("Do Something Clicked");
        toPaint[0] = out;
        repaint();
    }
});

它将操作的最后结果反馈给自身,从而逐渐减少图像中垂直像素的数量......

更新了工作示例

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static java.lang.Math.abs;
import static java.lang.Math.min;

public class SeamCarving {

    public static void main(String[] args) {
        new SeamCarving();
    }

    public SeamCarving() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage input;
        BufferedImage[] toPaint;

        public TestPane() {
            try {

                input = ImageIO.read(new File("..."));
                toPaint = new BufferedImage[]{input};

                toPaint = new BufferedImage[1];
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            setLayout(new GridBagLayout());
            JButton loadButton = new JButton("Load");
            loadButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    BufferedImage out = input;
                    toPaint[0] = input;
                    repaint();
                    System.out.println("Do Something Clicked");
                }
            });
            add(loadButton);
            JButton startButton = new JButton("Start");

            add(startButton);
            startButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent ae) {
                    BufferedImage out = deleteVerticalSeam(toPaint[0]);
                    System.out.println("Do Something Clicked");
                    toPaint[0] = out;
                    repaint();
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return input == null ? super.getPreferredSize() : new Dimension(input.getWidth(), input.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(toPaint[0], 0, 0, this);
            g2d.dispose();
        }

    }

    private static BufferedImage deleteVerticalSeam(BufferedImage input) {
        return deleteVerticalSeam(input, findVerticalSeam(input));
    }

    private static BufferedImage deleteVerticalSeam(final BufferedImage input, final int[] seam) {
        int w = input.getWidth(), h = input.getHeight();
        final BufferedImage out = new BufferedImage(w - 1, h, BufferedImage.TYPE_INT_ARGB);

        for (int y = 0; y < h; y++) {
            for (int x = 0; x < seam[y]; x++) {
                out.setRGB(x, y, input.getRGB(x, y));
            }
            for (int x = seam[y] + 1; x < w; x++) {
                out.setRGB(x - 1, y, input.getRGB(x, y));
            }
        }
        return out;
    }

    private static int[] findVerticalSeam(BufferedImage input) {
        final int w = input.getWidth(), h = input.getHeight();
        final FloatImage intensities = FloatImage.fromBufferedImage(input);
        final FloatImage energy = computeEnergy(intensities);

        final FloatImage minima = FloatImage.createSameSize(energy);
        //First row is equal to the energy
        for (int x = 0; x < w; x++) {
            minima.set(x, 0, energy.get(x, 0));
        }

        //I assume that the rightmost pixel column in the energy image is garbage
        for (int y = 1; y < h; y++) {
            minima.set(0, y, energy.get(0, y) + min(minima.get(0, y - 1),
                    minima.get(1, y - 1)));

            for (int x = 1; x < w - 2; x++) {
                final float sum = energy.get(x, y) + min(min(minima.get(x - 1, y - 1),
                        minima.get(x, y - 1)), minima.get(x + 1, y - 1));
                minima.set(x, y, sum);
            }
            minima.set(w - 2, y, energy.get(w - 2, y) + min(minima.get(w - 2, y - 1), minima.get(w - 3, y - 1)));
        }

        //We find the minimum seam
        float minSum = Float.MAX_VALUE;
        int seamTip = -1;
        for (int x = 1; x < w - 1; x++) {
            final float v = minima.get(x, h - 1);
            if (v < minSum) {
                minSum = v;
                seamTip = x;
            }
        }

        //Backtrace the seam
        final int[] seam = new int[h];
        seam[h - 1] = seamTip;
        for (int x = seamTip, y = h - 1; y > 0; y--) {
            float left = x > 0 ? minima.get(x - 1, y - 1) : Float.MAX_VALUE;
            float up = minima.get(x, y - 1);
            float right = x + 1 < w ? minima.get(x + 1, y - 1) : Float.MAX_VALUE;
            if (left < up && left < right) {
                x = x - 1;
            } else if (right < up && right < left) {
                x = x + 1;
            }
            seam[y - 1] = x;
        }

        return seam;
    }

    private static FloatImage computeEnergy(FloatImage intensities) {
        int w = intensities.getWidth(), h = intensities.getHeight();
        final FloatImage energy = FloatImage.createSameSize(intensities);
        for (int x = 0; x < w - 1; x++) {
            for (int y = 0; y < h - 1; y++) {
                //I'm aproximating the derivatives by subtraction
                float e = abs(intensities.get(x, y) - intensities.get(x + 1, y))
                        + abs(intensities.get(x, y) - intensities.get(x, y + 1));
                energy.set(x, y, e);
            }
        }
        return energy;
    }

    public static final class FloatImage {

        private final int width;
        private final int height;
        private final float[] data;

        public FloatImage(int width, int height) {
            this.width = width;
            this.height = height;
            this.data = new float[width * height];
        }

        public int getWidth() {
            return width;
        }

        public int getHeight() {
            return height;
        }

        public float get(final int x, final int y) {
            if (x < 0 || x >= width) {
                throw new IllegalArgumentException("x: " + x);
            }
            if (y < 0 || y >= height) {
                throw new IllegalArgumentException("y: " + y);
            }
            return data[x + y * width];
        }

        public void set(final int x, final int y, float value) {
            if (x < 0 || x >= width) {
                throw new IllegalArgumentException("x: " + x);
            }
            if (y < 0 || y >= height) {
                throw new IllegalArgumentException("y: " + y);
            }
            data[x + y * width] = value;
        }

        public static FloatImage createSameSize(final BufferedImage sample) {
            return new FloatImage(sample.getWidth(), sample.getHeight());
        }

        public static FloatImage createSameSize(final FloatImage sample) {
            return new FloatImage(sample.getWidth(), sample.getHeight());
        }

        public static FloatImage fromBufferedImage(final BufferedImage src) {
            final int width = src.getWidth();
            final int height = src.getHeight();
            final FloatImage result = new FloatImage(width, height);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    final int argb = src.getRGB(x, y);
                    int r = (argb >>> 16) & 0xFF;
                    int g = (argb >>> 8) & 0xFF;
                    int b = argb & 0xFF;
                    result.set(x, y, (r * 0.3f + g * 0.59f + b * 0.11f) / 255);
                }
            }
            return result;
        }

        public BufferedImage toBufferedImage(float scale) {
            final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    final int intensity = ((int) (get(x, y) * scale)) & 0xFF;
                    result.setRGB(x, y, 0xFF000000 | intensity | intensity << 8 | intensity << 16);
                }
            }
            return result;
        }
    }
}
于 2014-01-14T01:27:00.463 回答