First initial detection system for DDR scores using pixel checking algorithm (#1)
Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
This commit is contained in:
parent
8eb9edb71a
commit
0f3c03be58
@ -59,6 +59,6 @@ public class ArcadeReader {
|
||||
*
|
||||
*/
|
||||
public static void retrieveData(Path img) {
|
||||
new ITGReader().interpretBoxes(img);
|
||||
new DDRReader().interpretBoxes(img);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,9 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import readers.fonts.Font;
|
||||
import readers.fonts.Glyph;
|
||||
|
||||
public class DDRReader extends Reader{
|
||||
final static int REGION_PADDING = 32;
|
||||
List<Box> extraRegions = new ArrayList<>();
|
||||
@ -32,19 +35,7 @@ public class DDRReader extends Reader{
|
||||
readRegions.add(new Box(577,91,174,36)); //playstyle[12]
|
||||
readRegions.add(new Box(253,207,357,183)); //grade[13]
|
||||
readRegions.add(new Box(756,432,411,38)); //songname[14]
|
||||
|
||||
extraRegions.add(new Box(251,393,112,33)); //score text[0]
|
||||
extraRegions.add(new Box(315,565,295,40)); //max combo text[1]
|
||||
extraRegions.add(new Box(315,611,290,42)); //marvelous text[2]
|
||||
extraRegions.add(new Box(315,651,290,42)); //perfect text[3]
|
||||
extraRegions.add(new Box(315,698,290,42)); //great text[4]
|
||||
extraRegions.add(new Box(315,742,290,42)); //good text[5]
|
||||
extraRegions.add(new Box(315,787,290,42)); //OK text[6]
|
||||
extraRegions.add(new Box(315,830,290,42)); //miss text[7]
|
||||
extraRegions.add(new Box(345,874,258,39)); //ex score text[8]
|
||||
extraRegions.add(new Box(805,706,88,30)); //fast text[9]
|
||||
extraRegions.add(new Box(801,793,96,30)); //slow text[10]
|
||||
extraRegions.add(new Box(576,126,185,40)); //difficulty text[11]
|
||||
readRegions.add(new Box(576,126,185,40)); //difficulty text[15]
|
||||
}
|
||||
|
||||
void ColorFilter(int[] arr,int region,int width) {
|
||||
@ -54,120 +45,61 @@ public class DDRReader extends Reader{
|
||||
247,255,247,255,247,255,
|
||||
200,255,200,255,200,255);
|
||||
}break;
|
||||
case 400:{
|
||||
process(arr,width,
|
||||
180,255,180,255,180,255,
|
||||
170,255,170,255,170,255);
|
||||
}break;
|
||||
case 1:{
|
||||
process(arr,width,
|
||||
180,255,180,255,180,255,
|
||||
70,255,70,255,70,255);
|
||||
}break;
|
||||
case 401:{
|
||||
process(arr,width,
|
||||
240,255,240,255,240,255,
|
||||
130,255,130,255,130,255);
|
||||
}break;
|
||||
case 2:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 402:{
|
||||
process(arr,width,
|
||||
50,120,50,120,50,120,
|
||||
0,170,0,160,0,140);
|
||||
}break;
|
||||
case 3:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 403:{
|
||||
process(arr,width,
|
||||
60,100,50,100,0,40,
|
||||
0,150,0,150,0,70);
|
||||
}break;
|
||||
case 4:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 404:{
|
||||
process(arr,width,
|
||||
10,50,50,170,0,50,
|
||||
0,80,0,115,0,90);
|
||||
}break;
|
||||
case 5:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 405:{
|
||||
process(arr,width,
|
||||
30,80,60,110,70,140,
|
||||
0,110,0,130,0,160);
|
||||
}break;
|
||||
case 6:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 406:{
|
||||
process(arr,width,
|
||||
50,100,20,70,0,40,
|
||||
0,130,0,110,0,90);
|
||||
}break;
|
||||
case 7:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 407:{
|
||||
process(arr,width,
|
||||
40,70,20,50,20,70,
|
||||
0,110,0,90,0,100);
|
||||
}break;
|
||||
case 8:{
|
||||
process(arr,width,
|
||||
190,255,190,255,190,255,
|
||||
140,255,140,255,140,255);
|
||||
}break;
|
||||
case 408:{
|
||||
process(arr,width,
|
||||
200,255,200,255,0,90,
|
||||
180,255,170,255,0,90);
|
||||
}break;
|
||||
case 9:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 409:{
|
||||
process(arr,width,
|
||||
160,200,200,240,240,255,
|
||||
150,200,170,210,240,255);
|
||||
}break;
|
||||
case 10:{
|
||||
process(arr,width,
|
||||
0,50,0,50,0,50,
|
||||
0,160,0,160,0,160);
|
||||
}break;
|
||||
case 410:{
|
||||
process(arr,width,
|
||||
240,255,180,200,220,255,
|
||||
240,255,150,210,220,255);
|
||||
}break;
|
||||
case 11:{
|
||||
process(arr,width,
|
||||
190,255,190,255,190,255,
|
||||
140,255,140,255,140,255);
|
||||
}break;
|
||||
case 411:{
|
||||
processBrightness(arr,width,
|
||||
300,275);
|
||||
}break;
|
||||
case 12:{
|
||||
process(arr,width,
|
||||
190,255,190,255,190,255,
|
||||
@ -205,33 +137,8 @@ public class DDRReader extends Reader{
|
||||
//System.out.println(i);
|
||||
//ImageIO.write(originalImg.getSubimage(readRegions.get(i).x, readRegions.get(i).y, readRegions.get(i).w, readRegions.get(i).h),"png",new File("cut.png"));
|
||||
ColorFilter(arr,i,readRegions.get(i).w);
|
||||
//g.drawImage(originalImg, 0,currentHeight,readRegions.get(i).w,readRegions.get(i).h+currentHeight,readRegions.get(i).x, readRegions.get(i).y, readRegions.get(i).x+readRegions.get(i).w, readRegions.get(i).y+readRegions.get(i).h, null);
|
||||
int leftMost=readRegions.get(i).w;
|
||||
for (int j=0;j<arr.length;j++) {
|
||||
if (arr[j]==Color.MAGENTA.getRGB()&&j%readRegions.get(i).w<leftMost) {
|
||||
leftMost=j%readRegions.get(i).w;
|
||||
}
|
||||
}
|
||||
if (i<=11) {
|
||||
int[] arr2 = originalImg.getRGB(extraRegions.get(i).x, extraRegions.get(i).y, extraRegions.get(i).w, extraRegions.get(i).h, null, 0, extraRegions.get(i).w);
|
||||
int rightMost=0;
|
||||
ColorFilter(arr2,400+i,extraRegions.get(i).w);
|
||||
for (int j=0;j<arr2.length;j++) {
|
||||
if (arr2[j]==Color.MAGENTA.getRGB()&&j%extraRegions.get(i).w>rightMost) {
|
||||
rightMost=j%extraRegions.get(i).w;
|
||||
}
|
||||
}
|
||||
//cutImg.setRGB(rightMost-leftMost,currentHeight,readRegions.get(i).w,readRegions.get(i).h,arr,0,readRegions.get(i).w);
|
||||
cutImg.setRGB(0,currentHeight,extraRegions.get(i).w,extraRegions.get(i).h,arr2,0,extraRegions.get(i).w);
|
||||
final int PADDING = 4;
|
||||
for (int x=leftMost;x<readRegions.get(i).w;x++) {
|
||||
for (int y=0;y<readRegions.get(i).h;y++) {
|
||||
cutImg.setRGB(x+rightMost-leftMost+PADDING, y+currentHeight, arr[y*readRegions.get(i).w+x]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cutImg.setRGB(0,currentHeight,readRegions.get(i).w,readRegions.get(i).h,arr,0,readRegions.get(i).w);
|
||||
}
|
||||
System.out.println(interpretImage(cutImg,i));
|
||||
currentHeight+=readRegions.get(i).h+REGION_PADDING;
|
||||
}
|
||||
Path output = Paths.get("result.png");
|
||||
@ -253,6 +160,26 @@ public class DDRReader extends Reader{
|
||||
//System.out.println(data[2]);
|
||||
}
|
||||
|
||||
private String interpretImage(BufferedImage cutImg, int i) {
|
||||
switch (i) {
|
||||
case 0:{
|
||||
Font f = Font.FONT_DDR_SCORE;
|
||||
List<Glyph> glyphs = Glyph.split(cutImg);
|
||||
if (glyphs.size()==9) {
|
||||
//This is a 1,000,000 score.
|
||||
glyphs.remove(5);
|
||||
glyphs.remove(1);
|
||||
} else
|
||||
if (glyphs.size()>4) {
|
||||
//This is a XXX,XXX score.
|
||||
glyphs.remove(3);
|
||||
}
|
||||
return f.convertGlyphs(glyphs);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
void interpretResults(String[] finalData) {
|
||||
// TODO Auto-generated method stub
|
||||
|
@ -12,24 +12,24 @@ import java.awt.Color;
|
||||
public class Font {
|
||||
Glyph[] data = new Glyph[10];
|
||||
final static int TRANSPARENT = new Color(0,0,0,0).getRGB();
|
||||
final static Font FONT_DDR_DIFF = LoadFont("ddr_diff");
|
||||
final static Font FONT_DDR_EXCOMBO = LoadFont("ddr_excombo");
|
||||
final static Font FONT_DDR_NOTECOUNT = LoadFont("ddr_noteCount");
|
||||
final static Font FONT_DDR_SCORE = LoadFont("ddr_score");
|
||||
final static Font FONT_ITG_DIFF = LoadFont("itg_diff");
|
||||
final static Font FONT_ITG_EX = LoadFont("itg_ex");
|
||||
final static Font FONT_ITG_NOTECOUNT = LoadFont("itg_noteCount");
|
||||
final static Font FONT_ITG_PCT = LoadFont("itg_pct");
|
||||
final static Font FONT_LOVELIVE_NOTECOUNT = LoadFont("lovelive_noteCount");
|
||||
final static Font FONT_LOVELIVE_PCT = LoadFont("lovelive_pct");
|
||||
final static Font FONT_LOVELIVE_SCORE = LoadFont("lovelive_score");
|
||||
final static Font FONT_POPN_COMBO = LoadFont("popn_combo");
|
||||
final static Font FONT_POPN_NOTECOUNT = LoadFont("popn_noteCount");
|
||||
final static Font FONT_POPN_SCORE = LoadFont("popn_score");
|
||||
final static Font FONT_SDVX_EXSCORE = LoadFont("sdvx_EXScore");
|
||||
final static Font FONT_SDVX_LITTLESCORE = LoadFont("sdvx_littleScore");
|
||||
final static Font FONT_SDVX_NOTECOUNT = LoadFont("sdvx_noteCount");
|
||||
final static Font FONT_SDVX_BIGSCORE = LoadFont("sdvx_largeScore");
|
||||
final public static Font FONT_DDR_DIFF = LoadFont("ddr_diff");
|
||||
final public static Font FONT_DDR_EXCOMBO = LoadFont("ddr_excombo");
|
||||
final public static Font FONT_DDR_NOTECOUNT = LoadFont("ddr_noteCount");
|
||||
final public static Font FONT_DDR_SCORE = LoadFont("ddr_score");
|
||||
final public static Font FONT_ITG_DIFF = LoadFont("itg_diff");
|
||||
final public static Font FONT_ITG_EX = LoadFont("itg_ex");
|
||||
final public static Font FONT_ITG_NOTECOUNT = LoadFont("itg_noteCount");
|
||||
final public static Font FONT_ITG_PCT = LoadFont("itg_pct");
|
||||
final public static Font FONT_LOVELIVE_NOTECOUNT = LoadFont("lovelive_noteCount");
|
||||
final public static Font FONT_LOVELIVE_PCT = LoadFont("lovelive_pct");
|
||||
final public static Font FONT_LOVELIVE_SCORE = LoadFont("lovelive_score");
|
||||
final public static Font FONT_POPN_COMBO = LoadFont("popn_combo");
|
||||
final public static Font FONT_POPN_NOTECOUNT = LoadFont("popn_noteCount");
|
||||
final public static Font FONT_POPN_SCORE = LoadFont("popn_score");
|
||||
final public static Font FONT_SDVX_EXSCORE = LoadFont("sdvx_EXScore");
|
||||
final public static Font FONT_SDVX_LITTLESCORE = LoadFont("sdvx_littleScore");
|
||||
final public static Font FONT_SDVX_NOTECOUNT = LoadFont("sdvx_noteCount");
|
||||
final public static Font FONT_SDVX_BIGSCORE = LoadFont("sdvx_largeScore");
|
||||
|
||||
public static Font LoadFont(String fontName) {
|
||||
Path f = Paths.get("readers","fonts",fontName);
|
||||
@ -146,4 +146,49 @@ public class Font {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String convertGlyphs(List<Glyph> glyphs) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i=0;i<glyphs.size();i++) {
|
||||
int bestScore=Integer.MIN_VALUE;
|
||||
int bestGlyph=0;
|
||||
for (int j=0;j<data.length;j++) {
|
||||
Glyph g_a = glyphs.get(i);
|
||||
Glyph g_b = data[j];
|
||||
int score=0;
|
||||
for (int x=0;x<g_b.width;x++) {
|
||||
for (int y=0;y<g_b.height;y++) {
|
||||
boolean found=false;
|
||||
//We can be up to 1 pixel off and still be valid.
|
||||
inner:
|
||||
for (int xx=-1;xx<=1;xx++) {
|
||||
for (int yy=-1;yy<=1;yy++) {
|
||||
int a_x=x+xx;
|
||||
int a_y=y+yy;
|
||||
if (a_x>=0&&a_x<g_a.width&&a_y>=0&&a_y<g_a.height) {
|
||||
int a_index=a_y*g_a.width+a_x;
|
||||
if (g_a.data[a_index]==g_b.data[y*g_b.width+x]) {
|
||||
found=true;
|
||||
break inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
score++;
|
||||
} else {
|
||||
score-=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (score>bestScore) {
|
||||
bestScore=score;
|
||||
bestGlyph=j;
|
||||
System.out.println("Glyph "+j+" has a score of "+bestScore+".");
|
||||
}
|
||||
}
|
||||
sb.append(bestGlyph);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,63 @@
|
||||
package readers.fonts;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
|
||||
public class Glyph {
|
||||
final static int TRANSPARENT = new Color(0,0,0,0).getRGB();
|
||||
int width=0;
|
||||
int height=0;
|
||||
boolean[] data = new boolean[]{};
|
||||
|
||||
public static List<Glyph> split(BufferedImage img) {
|
||||
int startX=-1;
|
||||
int endX=-1;
|
||||
List<Glyph> glyphs = new ArrayList<>();
|
||||
outer:
|
||||
for (int x=0;x<img.getWidth();x++) {
|
||||
for (int y=0;y<img.getHeight();y++) {
|
||||
if (img.getRGB(x, y)!=TRANSPARENT) {
|
||||
if (startX==-1) {
|
||||
startX=x;
|
||||
}
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
//If we got to here it means we found transparent on everything.
|
||||
if (startX!=-1) {
|
||||
endX=x;
|
||||
//Create a Glyph out of this.
|
||||
Glyph g = new Glyph();
|
||||
g.width=endX-startX;
|
||||
g.height=img.getHeight();
|
||||
int[] arr = img.getRGB(startX,0,g.width,g.height,null,0,g.width);
|
||||
//Find the min and max Y.
|
||||
int startY=g.height;
|
||||
int endY=0;
|
||||
for (int X=0;X<g.width;X++) {
|
||||
for (int Y=0;Y<g.height;Y++) {
|
||||
if (arr[Y*g.width+X]!=TRANSPARENT&&Y<startY) {
|
||||
startY=Y;
|
||||
}
|
||||
if (arr[Y*g.width+X]!=TRANSPARENT&&Y>endY) {
|
||||
endY=Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
g.height=endY-startY;
|
||||
g.data = new boolean[g.width*g.height];
|
||||
for (int X=0;X<g.width;X++) {
|
||||
for (int Y=0;Y<g.height;Y++) {
|
||||
g.data[Y*g.width+X]=arr[(Y+startY)*g.width+X]!=TRANSPARENT;
|
||||
}
|
||||
}
|
||||
glyphs.add(g);
|
||||
startX=-1;
|
||||
endX=-1;
|
||||
}
|
||||
}
|
||||
return glyphs;
|
||||
}
|
||||
}
|
||||
|
BIN
result.png
BIN
result.png
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 160 KiB |
@ -115,7 +115,7 @@ public class sigPlace {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
//ArcadeReader.retrieveData(Paths.get("itg1.png"));
|
||||
ArcadeReader.retrieveData(Paths.get("ddr4.png"));
|
||||
/* Path secretFile = Paths.get(".clientsecret");
|
||||
List<String> data;
|
||||
try {
|
||||
|
Loading…
x
Reference in New Issue
Block a user