千图成像(用图片拼图片)的java教程

来源:互联网 发布:淘宝被投诉商标侵权 编辑:程序博客网 时间:2024/05/06 08:54

大题思路我在知乎有回答

在这里大概讲下代码。我实现的比较粗糙,只能使用正方形的图片,如有其他需要可以自行改动。

下面是主要代码。
这里面有俩自定义的类,VectorParser(实现AimParser接口,用于像素替代算法的实现,其中parse()函数输入原料图片的rgb数组和目标图片对象,返回一个二维数组,其中每个数代表一个原料图片在其数组中的索引,将用该图片替换相应像素)和DefaultSamping(实现PicSampling接口,返回采样后的图片对象,我只是简单的用默认的采样方法改变了图片大小,大家可以根据需要修改)

public class ImageStitch {    public static int len = 25;    BufferedImage aim = null;    BufferedImage work = null;    BufferedImage srcsOld[] = null;    BufferedImage srcs[] = null;    int rgbs[][] = null;    int aimOfSrc[][];    int numSrc = 0;    public ImageStitch(File aim, File[] srcs) throws IOException {        //原料图片个数        numSrc = srcs.length;        // 初始化插值后原料图片数组        this.srcs = new BufferedImage[numSrc];                               //初始化原料图片的数组        srcsOld = new BufferedImage[numSrc];        //初始化图片的rgb数组        this.rgbs = new int[numSrc][];        // 读入目标图片(要拼的图片)        this.aim = ImageIO.read(aim);                                                       DefaultSampling sampling = new DefaultSampling();        for (int i = 0; i < numSrc; ++i) {            // 读入源(材料)图片并获取rgb数组            srcsOld[i] = ImageIO.read(srcs[i]);            //对图片进行插值            this.srcs[i]     = sampling.sampling(srcsOld[i]);            int width = this.srcs[i].getWidth();            int height = this.srcs[i].getHeight();            this.rgbs[i] = new int[width * height];            //获取图片的rgb数组            this.rgbs[i] = this.srcs[i].getRGB(0, 0, width, height, this.rgbs[i], 0, width);        }    }    public void parseAim(AimParser aimParser) {        //得到替换像素的图片的索引的数组        aimOfSrc = aimParser.parse(rgbs, aim);        //作品图片初始化        work = new BufferedImage(aim.getWidth() * len, aim.getHeight() * len, BufferedImage.TYPE_INT_RGB);        int x = 0, y = 0;        for(int i = 0; i < aimOfSrc.length; ++i){            x = 0;            for(int j = 0; j < aimOfSrc[i].length; ++j){                //将小图片填入大图片中                work.setRGB(x, y, len, len, rgbs[aimOfSrc[j][i]], 0, len);                x += len;            }            y += len;        }        //写图片到硬盘        FileOutputStream ops;        try {            ops = new FileOutputStream(new File("D:/Photo/stitch/znh.jpg"));            ImageIO.write(work, "jpg", ops);            ops.flush();            ops.close();            System.out.println("Success!");        } catch (Exception e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws IOException {        File aim = new File("D:/Photo/stitch/z5.jpg");        File[] srcs = new File[6];        srcs[0] = new File("D:/Photo/stitch/s1.jpg");        srcs[1] = new File("D:/Photo/stitch/s4.jpg");        srcs[2] = new File("D:/Photo/stitch/s3.jpg");        srcs[3] = new File("D:/Photo/stitch/s5.jpg");        srcs[4] = new File("D:/Photo/stitch/5.jpg");        srcs[5] = new File("D:/Photo/stitch/2.jpg");        ImageStitch imageStitch = new ImageStitch(aim, srcs);        imageStitch.parseAim(new VectorParser());    }}

AimParser接口和PicSampling接口

public interface AimParser {    public int[][] parse(int[][] rgbs, BufferedImage aim);}public interface PicSampling {    public BufferedImage sampling(BufferedImage aim);}

VectorParser 回答中取平均色值和选取替换图片的过程

public class VectorParser implements AimParser {    int[][] rgbs = null;    int[] averageR = null;    int[] averageG = null;    int[] averageB = null;    @Override    public int[][] parse(int[][] r, BufferedImage aim) {        int width = aim.getWidth();        int height = aim.getHeight();        int[][] aimOfSrc = new int[height][width];        rgbs = r;        averageR = new int[rgbs.length];        averageG = new int[rgbs.length];        averageB = new int[rgbs.length];        for (int i = 0; i < rgbs.length; ++i) {            for (int j = 0; j < rgbs[i].length; ++j) {                averageR[i] += (rgbs[i][j] & 0xff0000) >> 16;                averageG[i] += (rgbs[i][j] & 0xff00) >> 8;                averageB[i] += rgbs[i][j] & 0xff;            }            averageR[i] /= rgbs[i].length;            averageG[i] /= rgbs[i].length;            averageB[i] /= rgbs[i].length;        }        for (int j = 0; j < height; ++j) {            for (int i = 0; i < width; ++i) {                int rgb = aim.getRGB(i, j);                aimOfSrc[j][i] = choose(rgb);            }        }        return aimOfSrc;    }    private int choose(int rgb) {        int index = 0;        int min = 2147483647;        int r = (rgb & 0xff0000) >> 16;        int g = (rgb & 0xff00) >> 8;        int b = rgb & 0xff;        for (int i = 0; i < rgbs.length; ++i) {            int temp = (int)(Math.pow(averageR[i] - r, 2) + Math.pow(averageG[i] - g, 2) + Math.pow(averageB[i] - b, 2));            if(temp < min){                min = temp;                index = i;            }        }        return index;    }}

DefaultSampling

public class DefaultSampling implements PicSampling{    @Override    public BufferedImage sampling(BufferedImage aim) {        BufferedImage ret = new BufferedImage(ImageStitch.len, ImageStitch.len, BufferedImage.TYPE_INT_RGB);        ret.getGraphics().drawImage(aim, 0, 0, ImageStitch.len, ImageStitch.len, null);        return aim;    }}

That’s all.
有什么说的不清楚的地方随时提问。

0 0
原创粉丝点击