Wandering Elephant
Computer program performs Breadth-First-Search to find color patches in an image and replaces those patches with a pattern along with a corresponding color. The original Github repository can be found here: https://github.com/BitLorax/blackbox/blob/master/src/Main.java
Appendix (Computer Program)
import java.awt.*;import java.io.*;import java.awt.image.BufferedImage;import java.util.*;import javax.imageio.ImageIO;import javax.swing.*;public class Main { private static String refPath = ""; private static String compPath = "database"; private static int INF = 200000000; private static int PIC_CNT = 5640; private static int[][] MAX_RANGE = {{70, 50}, {50, 20}}; //{base, deviation} private static int MAX_HSIZE = 300; private static int LIM = 110; private static int[] dx = {0, 1, 0, -1}; private static int[] dy = {-1, 0, 1, 0}; private static int width, height; private static BufferedImage ref, collage, sections; private static boolean[][] visited; private static File fRef; private static File[] imgs; private static Color[] avgs = new Color[PIC_CNT + 1]; private static JFrame f = new JFrame(); private static JLabel jl; private static JFrame fS = new JFrame(); private static JLabel jSL; public static void main(String[] args) { f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fS.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Scanner sc = new Scanner(System.in); refPath = sc.nextLine(); try { fRef = new File(refPath); ref = ImageIO.read(fRef); System.out.println("Loading success"); } catch (IOException e) { System.out.println("Loading failed"); return; } width = ref.getWidth(); height = ref.getHeight(); visited = new boolean[width + 1][height + 1]; try { File f = new File(compPath); imgs = f.listFiles(); PIC_CNT = imgs.length; BufferedReader in = new BufferedReader(new FileReader("src/avgs.txt")); for (int i = 0; i < PIC_CNT; i++) { StringTokenizer st = new StringTokenizer(in.readLine()); avgs[i] = new Color(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())); } } catch (IOException e) { System.out.println("Failed to load avgs.txt"); return; } collage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); sections = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); jl = new JLabel(new ImageIcon(collage)); jSL = new JLabel(new ImageIcon(sections)); f.getContentPane().add(jl); fS.getContentPane().add(jSL); f.pack(); fS.pack(); f.setVisible(true); fS.setVisible(true); System.out.println("Generating collage"); try { boolean d = false; while (!d) { d = true; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (!visited[i][j]) { bfs(new Coord(i, j)); d = false; } } } } } catch (IOException e) { System.out.println("Failed to generate collage"); return; } System.out.println(); System.out.print("Save? (y/n) "); String s = sc.nextLine(); if (s.equals("y")) { File out = new File("out/production/artwork/" + fRef.getName()); try { ImageIO.write(collage, "jpg", out); System.out.println("Saving success"); } catch (IOException e) { System.out.println("Saving failed"); } } } static void bfs(Coord s) throws IOException { ArrayList<Coord> pixels = new ArrayList<>(); int[] sum = {0, 0, 0}; Coord tl = new Coord(INF, INF), br = new Coord(-INF, -INF); int k = (int)(Math.random() * MAX_RANGE.length); int size = 0; Queue<Coord> q = new LinkedList<>(); q.add(s); while (!q.isEmpty()) { Coord cur = q.remove(); if (visited[cur.x][cur.y]) continue; if (getDist(s, cur) > MAX_RANGE[k][0] + Math.random() * (MAX_RANGE[k][1])) continue; System.out.print("\r"); System.out.print(size); tl.x = Math.min(tl.x, cur.x); tl.y = Math.min(tl.y, cur.y); br.x = Math.max(br.x, cur.x); br.y = Math.max(br.y, cur.y); Color curC = new Color(ref.getRGB(cur.x, cur.y)); size++; pixels.add(cur); changeVisited(cur.x, cur.y, true); sum[0] += curC.getRed(); sum[1] += curC.getGreen(); sum[2] += curC.getBlue(); outer : for (int i = 0; i < 4; i++) { Coord next = new Coord(cur.x + dx[i], cur.y + dy[i]); if (next.x < 0 || next.x >= width || next.y < 0 || next.y >= height) continue; if (visited[next.x][next.y]) continue; for (Coord p : pixels) if (diff(new Color(ref.getRGB(next.x, next.y)), new Color(ref.getRGB(p.x, p.y))) > LIM) continue outer; q.add(next); } } //fill small holes for (int i = tl.x; i <= br.x; i++) { outer : for (int j = tl.y; j <= br.y; j++) { ArrayList<Coord> hPixels = new ArrayList<>(); if (visited[i][j]) continue; int hSize = 0; q = new LinkedList<>(); q.add(new Coord(i, j)); while (!q.isEmpty()) { Coord cur = q.remove(); if (cur.x < 0 || cur.x >= width || cur.y < 0 || cur.y >= height) continue; if (visited[cur.x][cur.y]) continue; hSize++; hPixels.add(cur); changeVisited(cur.x, cur.y, true); if (hSize > MAX_HSIZE) { for (Coord p : hPixels) { changeVisited(p.x, p.y, false); } continue outer; } for (int l = 0; l < 4; l++) { q.add(new Coord(cur.x + dx[l], cur.y + dy[l])); } } for (Coord p : hPixels) { pixels.add(p); } } } Color avg = new Color(sum[0] / size, sum[1] / size, sum[2] / size); BufferedImage img = ImageIO.read(imgs[getPic(avg)]); Coord shift = new Coord(0, 0); shift.x = (int)(Math.random() * Math.max(0, img.getWidth() - br.x - 1)); shift.y = (int)(Math.random() * Math.max(0, img.getHeight() - br.y - 1)); for (Coord p : pixels) { Coord mapped = new Coord(p.x - tl.x + shift.x, p.y - tl.y + shift.y); if (mapped.x >= img.getWidth() || mapped.y >= img.getHeight() || mapped.x < 0 || mapped.y < 0) changeVisited(p.x, p.y, false); else collage.setRGB(p.x, p.y, img.getRGB(mapped.x, mapped.y)); } jl.setIcon(new ImageIcon(collage)); jSL.setIcon(new ImageIcon(sections)); } static int getPic(Color avg) { int ret = 0; for (int i = 0; i < PIC_CNT; i++) if (diff(avgs[i], avg) < diff(avgs[ret], avg)) ret = i; return ret; } static int getDist(Coord a, Coord b) { return (int)Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } static int diff(Color a, Color b) { return Math.abs(a.getRed() - b.getRed()) + Math.abs(a.getGreen() - b.getGreen()) + Math.abs(a.getBlue() - b.getBlue()); } static void changeVisited(int x, int y, boolean s) { visited[x][y] = s; sections.setRGB(x, y, ((s) ? 16077122 : 0)); } static class Coord { int x, y; Coord(int a, int b) { x = a; y = b; } }
