【问题标题】:Rotate BufferedImage and remove black bound旋转 BufferedImage 并移除黑边
【发布时间】:2018-07-13 05:56:32
【问题描述】:

我有原图:

我使用以下 Java 代码旋转图像:

BufferedImage bi = ImageHelper.rotateImage(bi, -imageSkewAngle);

ImageIO.write(bi, "PNG", new File("out.png"));

结果我得到了以下图像:

如何去除图像周围的黑色边界并使其成为适当的白色矩形并且不占用太多空间.. 仅使用转换所需的大小...等于原始大小或在需要时更大?

【问题讨论】:

  • 将背景设置为白色是微不足道的,并且可能很快就会得到回答,无论有什么阻碍适当答案的点:不一定可以使图像与原始图像“相同大小”。它将比原来的更宽(尽管这可能只是由于“白色边框”,可以可能被省略 - 但弄清楚这个边框有多宽可能有点繁琐...... )
  • 感谢您的回答。是的,你是对的 - 大小可以更改。那么——如何使尺寸相同或比原来的尺寸大一点,以满足旋转要求?
  • 不完全清楚ImageHelper 究竟做了什么,但它似乎创建了一个新图像,其大小足以包含原始图像,在原始图像旋转后关于它的中心。从示例图像中,可能只需在与原始图像大小相同的新图像的中心绘制旋转图像即可。如果您认为这可以解决您的问题,请给我留言,然后我会将这些 cmets 转换为答案。
  • 是的,您对 ImageHelper 的看法是正确的。这是来自 Tess4j/Tesseract net.sourceforge.tess4j.util.ImageHelper 的帮助器类。关于图像大小-对于这个特定的图像是正确的,但是我要旋转数百个不同的图像,它们的侧面和比例可能会有所不同..所以有一些通用的方法来消除黑边会非常好并且不要花费太多空间..仅使用转换所需的大小...等于原始大小或在需要时更大。谢谢!
  • 如需尽快获得更好的帮助,请发帖minimal reproducible exampleShort, Self Contained, Correct Example

标签: java awt bufferedimage


【解决方案1】:

以下程序包含一个方法rotateImage,它应该等同于问题中使用的rotateImage方法:它计算旋转图像的边界,创建一个具有所需大小的新图像,并绘制原始图像进入新图像的中心。

该方法还接收一个确定背景颜色的Color backgroundColor。在示例中,设置为Color.RED,以说明效果。

该示例还包含一个方法rotateImageInPlace。此方法将始终创建与输入图像大小相同的图像,并将(旋转的)原始图像绘制到该图像的中心。

程序创建了两个面板,左侧显示rotateImage 的结果,右侧显示rotateImageInPlace 的结果,以及一个允许更改旋转角度的滑块。所以这个程序的输出如下所示:

(同样,Color.RED 仅用于说明。将其更改为 Color.WHITE 用于您的应用程序)

正如 cmets 中所讨论的,不改变图像大小的目标可能并不总是可以实现,这取决于图像的内容和旋转角度。因此对于某些角度,旋转后的图像可能不适合生成的图像。但是对于问题的用例,这应该是可以的:用例是原始图像已经包含一个旋转的矩形“感兴趣区域”。所以输出中没有出现的部分通常应该是输入图像中无论如何都不包含相关信息的部分。

(否则,有必要提供有关输入图像结构、边框大小或旋转角度的更多信息,或者必须通过检查图像、像素来手动找出所需的大小按像素,看看哪些像素是黑色的,哪些是白色的)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;

public class RotateImageWithoutBorder
{
    public static void main(String[] args) throws Exception
    {
        BufferedImage image = 
            ImageIO.read(new URL("https://i.stack.imgur.com/tMtFh.png"));


        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ImagePanel imagePanel0 = new ImagePanel();
        imagePanel0.setBackground(Color.BLUE);

        ImagePanel imagePanel1 = new ImagePanel();
        imagePanel1.setBackground(Color.BLUE);

        JSlider slider = new JSlider(0, 100, 1);
        slider.addChangeListener(e -> 
        {
            double alpha = slider.getValue() / 100.0;
            double angleRad = alpha * Math.PI * 2;

            BufferedImage rotatedImage = rotateImage(
                image, angleRad, Color.RED);
            imagePanel0.setImage(rotatedImage);

            BufferedImage rotatedImageInPlace = rotateImageInPlace(
                image, angleRad, Color.RED);
            imagePanel1.setImage(rotatedImageInPlace);

            f.repaint();
        });
        slider.setValue(0);
        f.getContentPane().add(slider, BorderLayout.SOUTH);

        JPanel imagePanels = new JPanel(new GridLayout(1,2));
        imagePanels.add(imagePanel0);
        imagePanels.add(imagePanel1);
        f.getContentPane().add(imagePanels, BorderLayout.CENTER);

        f.setSize(800,500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);

    }

    private static BufferedImage rotateImage(
        BufferedImage image, double angleRad, Color backgroundColor)
    {
        int w = image.getWidth();
        int h = image.getHeight();
        AffineTransform at = AffineTransform.getRotateInstance(
            angleRad, w * 0.5, h * 0.5);
        Rectangle rotatedBounds = at.createTransformedShape(
            new Rectangle(0, 0, w, h)).getBounds();
        BufferedImage result = new BufferedImage(
            rotatedBounds.width, rotatedBounds.height, 
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        g.setColor(backgroundColor);
        g.fillRect(0, 0, rotatedBounds.width, rotatedBounds.height);
        at.preConcatenate(AffineTransform.getTranslateInstance(
            -rotatedBounds.x, -rotatedBounds.y));
        g.transform(at);
        g.setRenderingHint(
            RenderingHints.KEY_INTERPOLATION, 
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return result;        
    }

    private static BufferedImage rotateImageInPlace(
        BufferedImage image, double angleRad, Color backgroundColor)
    {
        int w = image.getWidth();
        int h = image.getHeight();
        AffineTransform at = AffineTransform.getRotateInstance(
            angleRad, w * 0.5, h * 0.5);
        Rectangle rotatedBounds = at.createTransformedShape(
            new Rectangle(0, 0, w, h)).getBounds();
        BufferedImage result = new BufferedImage(
            w, h, 
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        g.setColor(backgroundColor);
        g.fillRect(0, 0, w, h);
        at.preConcatenate(AffineTransform.getTranslateInstance(
            -rotatedBounds.x - (rotatedBounds.width - w) * 0.5, 
            -rotatedBounds.y - (rotatedBounds.height - h) * 0.5));
        g.transform(at);
        g.setRenderingHint(
            RenderingHints.KEY_INTERPOLATION, 
            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return result;        
    }


    static class ImagePanel extends JPanel
    {
        private BufferedImage image;

        public void setImage(BufferedImage image)
        {
            this.image = image;
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            if (image != null)
            {
                g.drawImage(image, 0, 0, null);
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2017-03-31
    • 2013-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多