1

Java では、ある BufferedImage を別の BufferedImage に置き換えようとしています。

たとえば、をinsideにここに画像の説明を入力置き換えると、結果として が生成されます。ここに画像の説明を入力ここに画像の説明を入力ここに画像の説明を入力

別の BufferedImage 内の 1 つの BufferedImage を置き換える関数を記述し、結果の BufferedImage を返すことは可能でしょうか?

public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis){
//In containingImage, replace all occurrences of toBeReplaced with replaceWithThis    
}
4

2 に答える 2

2

以下の方法はトリックを行います。擬似コード:

  • (1) のすべてのピクセルについてcontainingImage ソース:
    • toBeReplaced 交換する(ピクセル単位で) のマッチングを開始します
      • それが見つかった場合 (すべてのピクセルが一致した場合)、すべてのピクセルを次のように置き換えます。replaceWithThis replaceWithThis
      • そうでない場合は、(1) に戻ります。

すべてのパターンが見つかるので、最終的には を返しreturnImage 最後のます。

replaceInsideBufferedImage()コード:

public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis) {
    BufferedImage returnImage = deepCopyImage(containingImage);
    for (int x = 0; x+toBeReplaced.getWidth() < containingImage.getWidth(); x++) {
        for (int y = 0; y+toBeReplaced.getHeight() < containingImage.getHeight(); y++) {
            BufferedImage subImg = containingImage.getSubimage(x, y, toBeReplaced.getWidth(), toBeReplaced.getHeight());
            if (imageEquals(subImg,toBeReplaced)) {
                for (int sx = 0; sx < replaceWithThis.getWidth(); sx++) {
                    for (int sy = 0; sy < replaceWithThis.getHeight(); sy++) {
                        returnImage.setRGB(x+sx, y+sy, replaceWithThis.getRGB(sx, sy));
                    }
                }
            }
        }
    }
    return returnImage;
}

完全な作業コード:

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;

import javax.imageio.ImageIO;

public class ReplacePattern {

    public static void main(String[] args) throws Exception {
        BufferedImage containingImage = ImageIO.read(new File("fourWhites.png"));
        BufferedImage toBeReplaced = ImageIO.read(new File("oneWhite.png"));
        BufferedImage replaceWithThis = ImageIO.read(new File("oneRed.png"));
        BufferedImage replaced = replaceInsideBufferedImage(containingImage, toBeReplaced, replaceWithThis);
        ImageIO.write(replaced, "png", new File("fourReds.png"));
    }

    public static BufferedImage replaceInsideBufferedImage(BufferedImage containingImage, BufferedImage toBeReplaced, BufferedImage replaceWithThis) {
        BufferedImage returnImage = deepCopyImage(containingImage);
        for (int x = 0; x+toBeReplaced.getWidth() < containingImage.getWidth(); x++) {
            for (int y = 0; y+toBeReplaced.getHeight() < containingImage.getHeight(); y++) {
                BufferedImage subImg = containingImage.getSubimage(x, y, toBeReplaced.getWidth(), toBeReplaced.getHeight());
                if (imageEquals(subImg,toBeReplaced)) {
                    for (int sx = 0; sx < replaceWithThis.getWidth(); sx++) {
                        for (int sy = 0; sy < replaceWithThis.getHeight(); sy++) {
                            returnImage.setRGB(x+sx, y+sy, replaceWithThis.getRGB(sx, sy));
                        }
                    }
                }
            }
        }
        return returnImage;
    }

    // http://stackoverflow.com/a/3514297/1850609
    public static BufferedImage deepCopyImage(BufferedImage bi) {
        ColorModel cm = bi.getColorModel();
        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        WritableRaster raster = bi.copyData(null);
        return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
    }

    // http://stackoverflow.com/a/11006474/1850609
    private static boolean imageEquals(BufferedImage image1, BufferedImage image2) {
        int width;
        int height;
        boolean imagesEqual = true;
        if( image1.getWidth()  == ( width  = image2.getWidth() ) && 
            image1.getHeight() == ( height = image2.getHeight() ) ){
            for(int x = 0;imagesEqual == true && x < width; x++){
                for(int y = 0;imagesEqual == true && y < height; y++){
                    if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                        imagesEqual = false;
                    }
                }
            }
        }else{
            imagesEqual = false;
        }
        return imagesEqual;
    }
}
于 2013-06-10T07:57:59.703 に答える
0

可能ですが、そうすることはお勧めしません。

画像が別の画像内に存在するかどうかの検出は非常に遅くなります。

さらに、エンコーディング アーティファクトの可能性があるため、ある画像が別の画像で検出されない可能性があります。このような場合、より柔軟な検出機能を実装する必要がありますが、これにはさらに時間がかかり、誤検知につながる可能性があります。

ほとんどの場合、イメージを最初から再構築するためのデータがあります。画像を操作する代わりに、初期画像の生成に使用されたデータを取得し、それに基づいて新しい画像を作成するだけです。

しかし、本当にそれを行う必要がある場合は、両方の画像をループしてピクセルを比較する必要があります。関数を使用getRGB()して、画像をピクセルごとに比較します。

于 2013-06-10T07:18:04.510 に答える