[JAVA] I made a mosaic art with Pokemon images

Introduction

In this article, I will introduce how to automatically create mosaic art using images of 18 Pokemon from the input image.

Advance preparation

  1. From Pokédex to 18 animals (aqua, black, blue, fuchsia, silver, green, lime, maroon, navy, olive, purple, red, gray, Select a Pokemon whose color is close to teal, white, yellow, beige, orange).
  2. After adding the background color using photoshop etc., adjust the size to 40x40.
3. Put the Pokemon image in image / or an appropriate directory.

Rough flow of processing

There may be a smarter way, but ...

  1. Divide the input image into 40x40 PhotoMosaic.java
  2. Take the color average of the image created in 1 GetAverage.java 3.2 Color reduction based on the color average of 2 ReduceColor.java Place the Pokemon of the color selected in 4.3 `PhotoMosaic.java`

I will implement it like that.

Implementation

--The image import / export part is omitted.

PhotoMosaic.java


import java.awt.image.*;
import java.awt.Graphics;

public class PhotoMosaic {

	static BufferedImage execute(BufferedImage before_image) {
		int width = before_image.getWidth();
		int height = before_image.getHeight();
		BufferedImage after_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
		Graphics g = after_image.getGraphics();
		BufferedImage image[] = new BufferedImage[18];
        image[0] = JpegFileReader.read("image/white.png ");
        image[1] = JpegFileReader.read("image/fuchsia.png ");
        image[2] = JpegFileReader.read("image/lime.png ");
        image[3] = JpegFileReader.read("image/blue.png ");
        image[4] = JpegFileReader.read("image/black.png ");
        image[5] = JpegFileReader.read("image/maroon.png ");
        image[6] = JpegFileReader.read("image/olive.png ");
		image[7] = JpegFileReader.read("image/silver.png ");
		image[8] = JpegFileReader.read("image/red.png ");
		image[9] = JpegFileReader.read("image/green.png ");
		image[10] = JpegFileReader.read("image/navy.png ");
		image[11] = JpegFileReader.read("image/yellow.png ");
		image[12] = JpegFileReader.read("image/aqua.png ");
		image[13] = JpegFileReader.read("image/gray.png ");
		image[14] = JpegFileReader.read("image/purple.png ");
		image[15] = JpegFileReader.read("image/teal.png ");
		image[16] = JpegFileReader.read("image/beige.png ");
		image[17] = JpegFileReader.read("image/orange.png ");

		//Declare an array to hold the cropped image
		BufferedImage[][] split_image = new BufferedImage[width/40][height/40];

		for ( int i=0; i*40<width; i++ ) {
			for ( int j=0; j*40<height; j++ ) {
				//40 original images*Cut to 40
				split_image[i][j] = before_image.getSubimage( i*40, j*40, 40, 40 );
				//Take the color average of the cropped image
				int color_num = ReduceColor.detectColor(GetAverage.execute(split_image[i][j]));
				g.drawImage(image[color_num], i*40, j*40, null);
			}
		}
		g.dispose();
		return after_image;
  }

}

GetAverage.java


import java.awt.image.*;
import java.awt.Color;

public class GetAverage{
  static int[] execute(BufferedImage image){
    int R = 0, G = 0, B = 0;
    // Average[0]->Red, Average[1]->Green, Average[2]->Blue
    int Average[] = new int[3];

    //Take the RGB values of the pixels to get the total
    for (int i=0; i<40; i++ ) {
      for (int j=0; j<40; j++ ) {
        int tmp_color = image.getRGB(i,j);
        Color color = new Color(tmp_color);
        R += color.getRed();
        G += color.getGreen();
        B += color.getBlue();
      }
    }

    //Find the average value of pixels
    Average[0] = (int)R/1600;
    Average[1] = (int)G/1600;
    Average[2] = (int)B/1600;
    return Average;
  }
}

ReduceColor.java


public class ReduceColor{

  static int detectColor(int[] Average){
    int R = getNearestValue(Average[0]);
    int G = getNearestValue(Average[1]);
    int B = getNearestValue(Average[2]);
    //An array to put the subscripts of the array of images to be converted
    int[][][] v = new int[256][256][256];
    
    v[64][64][64] = 4;    // black
    v[64][64][128] = 10;  // navy
    v[64][64][192] = 3;   // blue
    v[64][64][255] = 3;   // blue

    v[64][128][64] = 9;   // green
    v[64][128][128] = 15; // teal
    v[64][128][192] = 15; // teal
    v[64][128][255] = 3;  // blue

    v[64][192][64] = 2;   // lime
    v[64][192][128] = 15; // teal
    v[64][192][192] = 12; // aqua
    v[64][192][255] = 3;  // blue

    v[64][255][64] = 2;   // lime
    v[64][255][128] = 2;  // lime
    v[64][255][192] = 12; // aqua
    v[64][255][255] = 12; // aqua

    v[128][64][64] = 5;   // maroon
    v[128][64][128] = 14; // purple
    v[128][64][192] = 14; // purple
    v[128][64][255] = 3;  // blue

    v[128][128][64] = 6;  // olive
    v[128][128][128] = 13;// gray
    v[128][128][192] = 3; // blue
    v[128][128][255] = 3; // blue

    v[128][192][64] = 9;  // green
    v[128][192][128] = 2; // lime
    v[128][192][192] = 12;// aqua
    v[128][192][255] = 12;// aqua

    v[128][255][64] = 2;  // lime
    v[128][255][128] = 2; // lime
    v[128][255][192] = 2; // lime
    v[128][255][255] = 12;// aqua

    v[192][64][64] = 8;   // red
    v[192][64][128] = 1;  // fuchsia
    v[192][64][192] = 1;  // fuchsia
    v[192][64][255] = 14; // purple

    v[192][128][64] = 17; // orange
    v[192][128][128] = 16;// beige
    v[192][128][192] = 1; // fuchsia
    v[192][128][255] = 1; // fuchsia

    v[192][192][64] = 11;  // yellow
    v[192][192][128] = 11; // yellow
    v[192][192][192] = 0; // white
    v[192][192][255] = 12;// aqua

    v[192][255][64] = 12; // aqua
    v[192][255][128] = 2; // lime
    v[192][255][192] = 0; // white
    v[192][255][255] = 12;// aqua

    v[255][64][64] = 8;   // red
    v[255][64][128] = 8;  // red
    v[255][64][192] = 1;  // fuchsia
    v[255][64][255] = 1;  // fuchsia

    v[255][128][64] = 17; // orange
    v[255][128][128] = 16;// beige
    v[255][128][192] = 1; // fuchsia
    v[255][128][255] = 1; // fuchsia

    v[255][192][64] = 11; // yellow
    v[255][192][128] = 11;// yellow
    v[255][192][192] = 16;// beige
    v[255][192][255] = 16;// beige

    v[255][255][64] = 11; // yellow
    v[255][255][128] = 11;// yellow
    v[255][255][192] = 0; // white
    v[255][255][255] = 0; // white

    return v[R][G][B];
  }

  public static int getNearestValue(int v){
		int num=0;	//Array subscript
		int difference;	//Array value-Absolute value of RGB value v
    int[] list = {64,128,192,192};
    // System.out.println("The value of v is"+v);
		difference = Math.abs( list[0] - v );
		for ( int i = 1; i < list.length; i++ ) {
			if ( Math.abs( list[i] - v ) < difference ) {
				num = i;
				difference = Math.abs( list[i] - v );
			}
		}
 		return list[num];
  }

}

result

(Click to enlarge)

――It was quite difficult to reduce the color. Especially when it was light blue, it was judged to be white and it didn't work. ――The red color was relatively nice. ――Since there are only 18 colors, landscape photography is difficult.

Helpful articles

--Cut a part of the image using BufferedImage_getSubimage.

-WEB color list

Recommended Posts

I made a mosaic art with Pokemon images
I made a GUI with Swing
I made a risky die with Ruby
I made a rock-paper-scissors app with kotlin
I made a rock-paper-scissors app with android
04. I made a front end with SpringBoot + Thymeleaf
I made a gender selection column with enum
I made a LINE bot with Rails + heroku
I made a portfolio with Ruby On Rails
[Ruby] I made a crawler with anemone and nokogiri.
I made a chat app.
I made a function to register images with API in Spring Framework. Part 1 (API edition)
I made a development environment with rails6 + docker + postgreSQL + Materialize.
I made a plugin to execute jextract with Gradle task
I made a mod that instantly calls a vehicle with Minecraft
I made a function to register images with API in Spring Framework. Part 2 (Client Edition)
Pokemon Go made with Faker Gem
Ruby: I made a FizzBuzz program!
I made a shopify app @java
I made a simple recommendation function.
I made a matching app (Android app)
I made a package.xml generation tool.
[Android] I made a pedometer app.
I made a simple search form with Spring Boot + GitHub Search API.
[Ruby] I made a simple Ping client
I made an app to scribble with PencilKit on a PDF file
I made an eco server with scala
I tried playing with BottomNavigationView a little ①
I made a plugin for IntelliJ IDEA
I made a calculator app on Android
I made a new Java deployment tool
[LINE BOT] I made a ramen BOT with Java (Maven) + Heroku + Spring Boot (1)
I made a bulletin board using Docker 1
I made a site that summarizes information on carbohydrate restriction with Vue.js
Learn Java with Progate → I will explain because I made a basic game myself
I made a Diff tool for Java files
I made a primality test program in Java
I made blackjack with Ruby (I tried using minitest)
I made a rock-paper-scissors game in Java (CLI)
I made a viewer app that displays a PDF
I made a Docker container to run Maven
I made a Ruby extension library in C
[Rails] I made a draft function using enum
I built a Code Pipeline with AWS CDK.
I tried to break a block with java (1)
I made StringUtils.isBlank
I tried deploying a page made with antique Middleman on Azure Static Web Apps
I made a lock pattern using the volume key with the Android app. Fragment edition
I made a simple calculation problem game in Java
I made an iPhone Theremin with Vision framework + AudioKit
A simple CRUD app made with Nuxt / Laravel (Docker)
I made a method to ask for Premium Friday
I made a drawing chat "8bit paint chat" on WebAssembly
I want to monitor a specific file with WatchService
I made a Restful server and client in Spring.
I made a library that works like a Safari tab !!
I tried OCR processing a PDF file with Java
[Beginner] I stumbled upon launching a project with Rails6
I made a library for displaying tutorials on Android.
I made a Wrapper that calls KNP from Java
I made an Android application that GETs with HTTP