Last active
October 19, 2015 02:13
-
-
Save YSRKEN/9b25897c2a815fd0cd22 to your computer and use it in GitHub Desktop.
やさしい画像認識教室~ゲーム編~ ref: http://qiita.com/YSRKEN/items/819dd3acf750ff5c0e7f
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Dimension; | |
import java.awt.Graphics; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.io.IOException; | |
import javax.imageio.ImageIO; | |
import javax.swing.JFrame; | |
import javax.swing.JOptionPane; | |
import javax.swing.JPanel; | |
public class sample1 extends JPanel{ | |
static BufferedImage image; | |
// main関数 | |
public static void main(String args[]){ | |
if(args.length < 1) return; | |
try{ | |
// 画像を読み込む | |
image = ImageIO.read(new File(args[0])); | |
// フレームを作成して表示する | |
JFrame frame = new JFrame("テスト"); | |
sample1 panel = new sample1(); | |
frame.getContentPane().add(panel); | |
frame.getContentPane().setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setVisible(true); | |
frame.pack(); | |
// 画像を読み取って情報を表示する | |
JOptionPane.showMessageDialog(frame, getInfo(image)); | |
} | |
catch(IOException error){ | |
error.printStackTrace(); | |
} | |
} | |
// 画像を読み取って情報を表示する | |
private static String getInfo(BufferedImage image){ | |
String info = ""; | |
/* 認識処理 */ | |
return info; | |
} | |
// 画面を描画する | |
public void paintComponent(Graphics graphics){ | |
graphics.drawImage(image, 0, 0, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static final int cc_threshold = 500; //カラーピックした際のしきい値(経験上決めた) | |
// カラーピックして指定色と十分に近いと言えるかを判定する | |
private static boolean checkColor(int x, int y, int color){ | |
int argb = image.getRGB(x, y); | |
int r_diff = ((argb & 0xFF0000) >> 16) - ((color & 0xFF0000) >> 16); | |
int g_diff = ((argb & 0xFF00) >> 8) - ((color & 0xFF00) >> 8); | |
int b_diff = (argb & 0xFF) - (color & 0xFF); | |
int diff = r_diff * r_diff + g_diff * g_diff + b_diff * b_diff; | |
if(diff < cc_threshold) return true; else return false; | |
} | |
// 画像を読み取って情報を表示する | |
private static String getInfo(){ | |
String info = ""; | |
/* 認識処理 */ | |
// 艦船数 | |
int[] fleet = {1, 1}; | |
for(int k = 5; k > 0; k--){ | |
if(checkColor(33, 119 + 45 * k, 0x747572)){ | |
fleet[0] = k + 1; | |
break; | |
} | |
} | |
for(int k = 5; k > 0; k--){ | |
if(checkColor(686, 188 + 45 * k, 0x747572)){ | |
fleet[1] = k + 1; | |
break; | |
} | |
} | |
info += "艦船数:" + fleet[0] + "/" + fleet[1] + "\n"; | |
return info; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static final double name_threshold = 127.5; //艦名判定の際のしきい値 | |
static HashMap<Long, String> map = new HashMap<Long,String>(); //艦名検索 | |
// 艦名データを初期化する | |
map.put(0x000ffffffcL, "暁"); //通常 | |
map.put(0x7ffe7fffffL, "響"); //通常 | |
map.put(0x003fffffffL, "雷"); //通常 | |
map.put(0x00dffffffeL, "雷"); //中破 | |
map.put(0x088be7ffffL, "電"); //通常 | |
map.put(0x80e0000003L, "駆逐イ級"); | |
map.put(0x9be7c00000L, "駆逐ロ級"); | |
private static String getInfo(){ | |
(中略) | |
// 艦名 | |
info += "自艦隊:"; | |
for(int k = 0; k < fleet[0]; k++){ | |
// 40ビットの入力データを取得する | |
long unit_data = 0; | |
for(int m = 0; m < 40; m++){ | |
// Yの値を取得する | |
int argb = image.getRGB(97, m + 78 + 45 * k); | |
int r = ((argb & 0xFF0000) >> 16); | |
int g = ((argb & 0xFF00) >> 8); | |
int b = (argb & 0xFF); | |
double y = 0.299 * r + 0.587 * g + 0.114 * b; | |
// しきい値で判断して、unit_dataに加算する | |
unit_data <<= 1; | |
if(y >= name_threshold)unit_data += 1; | |
} | |
if(k != 0)info += "/"; | |
if(map.containsKey(unit_data)){ | |
info += map.get(unit_data); | |
}else{ | |
info += "不明"; | |
} | |
} | |
info += "\n敵艦隊:"; | |
for(int k = 0; k < fleet[1]; k++){ | |
// 40ビットの入力データを取得する | |
long unit_data = 0; | |
for(int m = 0; m < 40; m++){ | |
// Yの値を取得する | |
int argb = image.getRGB(739, m + 147 + 45 * k); | |
int r = ((argb & 0xFF0000) >> 16); | |
int g = ((argb & 0xFF00) >> 8); | |
int b = (argb & 0xFF); | |
double y = 0.299 * r + 0.587 * g + 0.114 * b; | |
// しきい値で判断して、unit_dataに加算する | |
unit_data <<= 1; | |
if(y >= name_threshold)unit_data += 1; | |
} | |
if(k != 0)info += "/"; | |
if(map.containsKey(unit_data)){ | |
info += map.get(unit_data); | |
}else{ | |
info += "不明"; | |
} | |
} | |
info += "\n"; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static HashMap<Integer, String> damage_map = new HashMap<Integer,String>(); //損害判定 | |
// 損害判定を初期化する | |
damage_map.put(0xe3d052, "小破"); | |
damage_map.put(0xc9944a, "中破"); | |
damage_map.put(0x6d2e27, "大破"); | |
damage_map.put(0x4b9fd4, "撃沈"); | |
private static String getInfo(){ | |
(中略) | |
// 損害判定 | |
info += "損害判定:"; | |
for(int k = 0; k < fleet[0]; k++){ | |
if(k != 0)info += "."; | |
boolean flg = false; | |
for(HashMap.Entry<Integer, String> entry : damage_map.entrySet()){ | |
if(checkColor(140, 105 + 45 * k, entry.getKey())){ | |
info += entry.getValue(); | |
flg = true; | |
break; | |
} | |
} | |
if(!flg){ | |
if(checkColor(163, 79 + 45 * k, 0x19FD19)){ | |
info += "無傷"; | |
}else{ | |
info += "軽微"; | |
} | |
} | |
} | |
info += " / "; | |
for(int k = 0; k < fleet[1]; k++){ | |
if(k != 0)info += "."; | |
boolean flg = false; | |
for(HashMap.Entry<Integer, String> entry : damage_map.entrySet()){ | |
if(checkColor(780, 174 + 45 * k, entry.getKey())){ | |
info += entry.getValue(); | |
flg = true; | |
break; | |
} | |
} | |
if(!flg){ | |
if(checkColor(636, 148 + 45 * k, 0x19FD19)){ | |
info += "無傷"; | |
}else{ | |
info += "軽微"; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Dimension; | |
import java.awt.Graphics; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.HashMap; | |
import javax.imageio.ImageIO; | |
import javax.swing.JFrame; | |
import javax.swing.JOptionPane; | |
import javax.swing.JPanel; | |
public class sample1 extends JPanel{ | |
static final int cc_threshold = 500; //カラーピックした際のしきい値(経験上決めた) | |
static final double name_threshold = 127.5; //艦名判定の際のしきい値 | |
static BufferedImage image; //読み込んだ画像 | |
static HashMap<Long, String> unit_map = new HashMap<Long,String>(); //艦名検索 | |
static HashMap<Integer, String> damage_map = new HashMap<Integer,String>(); //損害判定 | |
// main関数 | |
public static void main(String args[]){ | |
if(args.length < 1) return; | |
try{ | |
// 画像を読み込む | |
image = ImageIO.read(new File(args[0])); | |
// フレームを作成して表示する | |
JFrame frame = new JFrame("テスト"); | |
sample1 panel = new sample1(); | |
frame.getContentPane().add(panel); | |
frame.getContentPane().setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setVisible(true); | |
frame.pack(); | |
// 艦名データを初期化する | |
unit_map.put(0x000ffffffcL, "暁"); //通常 | |
unit_map.put(0x7ffe7fffffL, "響"); //通常 | |
unit_map.put(0x003fffffffL, "雷"); //通常 | |
unit_map.put(0x00dffffffeL, "雷"); //中破 | |
unit_map.put(0x088be7ffffL, "電"); //通常 | |
unit_map.put(0x83c000000cL, "駆逐イ級"); | |
unit_map.put(0x9d81e00000L, "駆逐ロ級"); | |
// 損害判定を初期化する | |
damage_map.put(0xe3d052, "小破"); | |
damage_map.put(0xc9944a, "中破"); | |
damage_map.put(0x6d2e27, "大破"); | |
damage_map.put(0x4b9fd4, "撃沈"); | |
// 画像を読み取って情報を表示する | |
JOptionPane.showMessageDialog(frame, getInfo()); | |
} | |
catch(IOException error){ | |
error.printStackTrace(); | |
} | |
} | |
// カラーピックして指定色と十分に近いと言えるかを判定する | |
private static boolean checkColor(int x, int y, int color){ | |
int argb = image.getRGB(x, y); | |
int r_diff = ((argb & 0xFF0000) >> 16) - ((color & 0xFF0000) >> 16); | |
int g_diff = ((argb & 0xFF00) >> 8) - ((color & 0xFF00) >> 8); | |
int b_diff = (argb & 0xFF) - (color & 0xFF); | |
int diff = r_diff * r_diff + g_diff * g_diff + b_diff * b_diff; | |
if(diff < cc_threshold) return true; else return false; | |
} | |
// 画像を読み取って情報を表示する | |
private static String getInfo(){ | |
long start = System.nanoTime(); | |
String info = ""; | |
/* 認識処理 */ | |
// 艦船数 | |
int[] fleet = {1, 1}; | |
for(int k = 5; k > 0; k--){ | |
if(checkColor(33, 119 + 45 * k, 0x747572)){ | |
fleet[0] = k + 1; | |
break; | |
} | |
} | |
for(int k = 5; k > 0; k--){ | |
if(checkColor(686, 188 + 45 * k, 0x747572)){ | |
fleet[1] = k + 1; | |
break; | |
} | |
} | |
info += "艦船数:" + fleet[0] + "/" + fleet[1] + "\n"; | |
// 艦名 | |
info += "自艦隊:"; | |
for(int k = 0; k < fleet[0]; k++){ | |
// 40ビットの入力データを取得する | |
long unit_data = 0; | |
for(int m = 0; m < 40; m++){ | |
// Yの値を取得する | |
int argb = image.getRGB(97, m + 78 + 45 * k); | |
int r = ((argb & 0xFF0000) >> 16); | |
int g = ((argb & 0xFF00) >> 8); | |
int b = (argb & 0xFF); | |
double y = 0.299 * r + 0.587 * g + 0.114 * b; | |
// しきい値で判断して、unit_dataに加算する | |
unit_data <<= 1; | |
if(y >= name_threshold)unit_data += 1; | |
} | |
if(k != 0)info += "/"; | |
if(unit_map.containsKey(unit_data)){ | |
info += unit_map.get(unit_data); | |
}else{ | |
info += "不明"; | |
} | |
} | |
info += "\n敵艦隊:"; | |
for(int k = 0; k < fleet[1]; k++){ | |
// 40ビットの入力データを取得する | |
long unit_data = 0; | |
for(int m = 0; m < 40; m++){ | |
// Yの値を取得する | |
int argb = image.getRGB(737, m + 147 + 45 * k); | |
int r = ((argb & 0xFF0000) >> 16); | |
int g = ((argb & 0xFF00) >> 8); | |
int b = (argb & 0xFF); | |
double y = 0.299 * r + 0.587 * g + 0.114 * b; | |
// しきい値で判断して、unit_dataに加算する | |
unit_data <<= 1; | |
if(y >= name_threshold)unit_data += 1; | |
} | |
if(k != 0)info += "/"; | |
if(unit_map.containsKey(unit_data)){ | |
info += unit_map.get(unit_data); | |
}else{ | |
info += "不明"; | |
} | |
} | |
info += "\n"; | |
// 損害判定 | |
info += "損害判定:"; | |
for(int k = 0; k < fleet[0]; k++){ | |
if(k != 0)info += "."; | |
boolean flg = false; | |
for(HashMap.Entry<Integer, String> entry : damage_map.entrySet()){ | |
if(checkColor(140, 105 + 45 * k, entry.getKey())){ | |
info += entry.getValue(); | |
flg = true; | |
break; | |
} | |
} | |
if(!flg){ | |
if(checkColor(163, 79 + 45 * k, 0x19FD19)){ | |
info += "無傷"; | |
}else{ | |
info += "軽微"; | |
} | |
} | |
} | |
info += " / "; | |
for(int k = 0; k < fleet[1]; k++){ | |
if(k != 0)info += "."; | |
boolean flg = false; | |
for(HashMap.Entry<Integer, String> entry : damage_map.entrySet()){ | |
if(checkColor(780, 174 + 45 * k, entry.getKey())){ | |
info += entry.getValue(); | |
flg = true; | |
break; | |
} | |
} | |
if(!flg){ | |
if(checkColor(636, 148 + 45 * k, 0x19FD19)){ | |
info += "無傷"; | |
}else{ | |
info += "軽微"; | |
} | |
} | |
} | |
long stop = System.nanoTime(); | |
System.out.println(stop - start); | |
return info; | |
} | |
// 画面を描画する | |
public void paintComponent(Graphics graphics){ | |
graphics.drawImage(image, 0, 0, this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment