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) {
|
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 javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import readers.fonts.Font;
|
||||||
|
import readers.fonts.Glyph;
|
||||||
|
|
||||||
public class DDRReader extends Reader{
|
public class DDRReader extends Reader{
|
||||||
final static int REGION_PADDING = 32;
|
final static int REGION_PADDING = 32;
|
||||||
List<Box> extraRegions = new ArrayList<>();
|
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(577,91,174,36)); //playstyle[12]
|
||||||
readRegions.add(new Box(253,207,357,183)); //grade[13]
|
readRegions.add(new Box(253,207,357,183)); //grade[13]
|
||||||
readRegions.add(new Box(756,432,411,38)); //songname[14]
|
readRegions.add(new Box(756,432,411,38)); //songname[14]
|
||||||
|
readRegions.add(new Box(576,126,185,40)); //difficulty text[15]
|
||||||
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]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorFilter(int[] arr,int region,int width) {
|
void ColorFilter(int[] arr,int region,int width) {
|
||||||
@ -54,120 +45,61 @@ public class DDRReader extends Reader{
|
|||||||
247,255,247,255,247,255,
|
247,255,247,255,247,255,
|
||||||
200,255,200,255,200,255);
|
200,255,200,255,200,255);
|
||||||
}break;
|
}break;
|
||||||
case 400:{
|
|
||||||
process(arr,width,
|
|
||||||
180,255,180,255,180,255,
|
|
||||||
170,255,170,255,170,255);
|
|
||||||
}break;
|
|
||||||
case 1:{
|
case 1:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
180,255,180,255,180,255,
|
180,255,180,255,180,255,
|
||||||
70,255,70,255,70,255);
|
70,255,70,255,70,255);
|
||||||
}break;
|
}break;
|
||||||
case 401:{
|
|
||||||
process(arr,width,
|
|
||||||
240,255,240,255,240,255,
|
|
||||||
130,255,130,255,130,255);
|
|
||||||
}break;
|
|
||||||
case 2:{
|
case 2:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 402:{
|
|
||||||
process(arr,width,
|
|
||||||
50,120,50,120,50,120,
|
|
||||||
0,170,0,160,0,140);
|
|
||||||
}break;
|
|
||||||
case 3:{
|
case 3:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 403:{
|
|
||||||
process(arr,width,
|
|
||||||
60,100,50,100,0,40,
|
|
||||||
0,150,0,150,0,70);
|
|
||||||
}break;
|
|
||||||
case 4:{
|
case 4:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 404:{
|
|
||||||
process(arr,width,
|
|
||||||
10,50,50,170,0,50,
|
|
||||||
0,80,0,115,0,90);
|
|
||||||
}break;
|
|
||||||
case 5:{
|
case 5:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 405:{
|
|
||||||
process(arr,width,
|
|
||||||
30,80,60,110,70,140,
|
|
||||||
0,110,0,130,0,160);
|
|
||||||
}break;
|
|
||||||
case 6:{
|
case 6:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 406:{
|
|
||||||
process(arr,width,
|
|
||||||
50,100,20,70,0,40,
|
|
||||||
0,130,0,110,0,90);
|
|
||||||
}break;
|
|
||||||
case 7:{
|
case 7:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 407:{
|
|
||||||
process(arr,width,
|
|
||||||
40,70,20,50,20,70,
|
|
||||||
0,110,0,90,0,100);
|
|
||||||
}break;
|
|
||||||
case 8:{
|
case 8:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
190,255,190,255,190,255,
|
190,255,190,255,190,255,
|
||||||
140,255,140,255,140,255);
|
140,255,140,255,140,255);
|
||||||
}break;
|
}break;
|
||||||
case 408:{
|
|
||||||
process(arr,width,
|
|
||||||
200,255,200,255,0,90,
|
|
||||||
180,255,170,255,0,90);
|
|
||||||
}break;
|
|
||||||
case 9:{
|
case 9:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 409:{
|
|
||||||
process(arr,width,
|
|
||||||
160,200,200,240,240,255,
|
|
||||||
150,200,170,210,240,255);
|
|
||||||
}break;
|
|
||||||
case 10:{
|
case 10:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
0,50,0,50,0,50,
|
0,50,0,50,0,50,
|
||||||
0,160,0,160,0,160);
|
0,160,0,160,0,160);
|
||||||
}break;
|
}break;
|
||||||
case 410:{
|
|
||||||
process(arr,width,
|
|
||||||
240,255,180,200,220,255,
|
|
||||||
240,255,150,210,220,255);
|
|
||||||
}break;
|
|
||||||
case 11:{
|
case 11:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
190,255,190,255,190,255,
|
190,255,190,255,190,255,
|
||||||
140,255,140,255,140,255);
|
140,255,140,255,140,255);
|
||||||
}break;
|
}break;
|
||||||
case 411:{
|
|
||||||
processBrightness(arr,width,
|
|
||||||
300,275);
|
|
||||||
}break;
|
|
||||||
case 12:{
|
case 12:{
|
||||||
process(arr,width,
|
process(arr,width,
|
||||||
190,255,190,255,190,255,
|
190,255,190,255,190,255,
|
||||||
@ -205,33 +137,8 @@ public class DDRReader extends Reader{
|
|||||||
//System.out.println(i);
|
//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"));
|
//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);
|
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);
|
cutImg.setRGB(0,currentHeight,readRegions.get(i).w,readRegions.get(i).h,arr,0,readRegions.get(i).w);
|
||||||
int leftMost=readRegions.get(i).w;
|
System.out.println(interpretImage(cutImg,i));
|
||||||
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);
|
|
||||||
}
|
|
||||||
currentHeight+=readRegions.get(i).h+REGION_PADDING;
|
currentHeight+=readRegions.get(i).h+REGION_PADDING;
|
||||||
}
|
}
|
||||||
Path output = Paths.get("result.png");
|
Path output = Paths.get("result.png");
|
||||||
@ -253,6 +160,26 @@ public class DDRReader extends Reader{
|
|||||||
//System.out.println(data[2]);
|
//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
|
@Override
|
||||||
void interpretResults(String[] finalData) {
|
void interpretResults(String[] finalData) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
@ -12,24 +12,24 @@ import java.awt.Color;
|
|||||||
public class Font {
|
public class Font {
|
||||||
Glyph[] data = new Glyph[10];
|
Glyph[] data = new Glyph[10];
|
||||||
final static int TRANSPARENT = new Color(0,0,0,0).getRGB();
|
final static int TRANSPARENT = new Color(0,0,0,0).getRGB();
|
||||||
final static Font FONT_DDR_DIFF = LoadFont("ddr_diff");
|
final public static Font FONT_DDR_DIFF = LoadFont("ddr_diff");
|
||||||
final static Font FONT_DDR_EXCOMBO = LoadFont("ddr_excombo");
|
final public static Font FONT_DDR_EXCOMBO = LoadFont("ddr_excombo");
|
||||||
final static Font FONT_DDR_NOTECOUNT = LoadFont("ddr_noteCount");
|
final public static Font FONT_DDR_NOTECOUNT = LoadFont("ddr_noteCount");
|
||||||
final static Font FONT_DDR_SCORE = LoadFont("ddr_score");
|
final public static Font FONT_DDR_SCORE = LoadFont("ddr_score");
|
||||||
final static Font FONT_ITG_DIFF = LoadFont("itg_diff");
|
final public static Font FONT_ITG_DIFF = LoadFont("itg_diff");
|
||||||
final static Font FONT_ITG_EX = LoadFont("itg_ex");
|
final public static Font FONT_ITG_EX = LoadFont("itg_ex");
|
||||||
final static Font FONT_ITG_NOTECOUNT = LoadFont("itg_noteCount");
|
final public static Font FONT_ITG_NOTECOUNT = LoadFont("itg_noteCount");
|
||||||
final static Font FONT_ITG_PCT = LoadFont("itg_pct");
|
final public static Font FONT_ITG_PCT = LoadFont("itg_pct");
|
||||||
final static Font FONT_LOVELIVE_NOTECOUNT = LoadFont("lovelive_noteCount");
|
final public static Font FONT_LOVELIVE_NOTECOUNT = LoadFont("lovelive_noteCount");
|
||||||
final static Font FONT_LOVELIVE_PCT = LoadFont("lovelive_pct");
|
final public static Font FONT_LOVELIVE_PCT = LoadFont("lovelive_pct");
|
||||||
final static Font FONT_LOVELIVE_SCORE = LoadFont("lovelive_score");
|
final public static Font FONT_LOVELIVE_SCORE = LoadFont("lovelive_score");
|
||||||
final static Font FONT_POPN_COMBO = LoadFont("popn_combo");
|
final public static Font FONT_POPN_COMBO = LoadFont("popn_combo");
|
||||||
final static Font FONT_POPN_NOTECOUNT = LoadFont("popn_noteCount");
|
final public static Font FONT_POPN_NOTECOUNT = LoadFont("popn_noteCount");
|
||||||
final static Font FONT_POPN_SCORE = LoadFont("popn_score");
|
final public static Font FONT_POPN_SCORE = LoadFont("popn_score");
|
||||||
final static Font FONT_SDVX_EXSCORE = LoadFont("sdvx_EXScore");
|
final public static Font FONT_SDVX_EXSCORE = LoadFont("sdvx_EXScore");
|
||||||
final static Font FONT_SDVX_LITTLESCORE = LoadFont("sdvx_littleScore");
|
final public static Font FONT_SDVX_LITTLESCORE = LoadFont("sdvx_littleScore");
|
||||||
final static Font FONT_SDVX_NOTECOUNT = LoadFont("sdvx_noteCount");
|
final public static Font FONT_SDVX_NOTECOUNT = LoadFont("sdvx_noteCount");
|
||||||
final static Font FONT_SDVX_BIGSCORE = LoadFont("sdvx_largeScore");
|
final public static Font FONT_SDVX_BIGSCORE = LoadFont("sdvx_largeScore");
|
||||||
|
|
||||||
public static Font LoadFont(String fontName) {
|
public static Font LoadFont(String fontName) {
|
||||||
Path f = Paths.get("readers","fonts",fontName);
|
Path f = Paths.get("readers","fonts",fontName);
|
||||||
@ -146,4 +146,49 @@ public class Font {
|
|||||||
e.printStackTrace();
|
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;
|
package readers.fonts;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Glyph {
|
public class Glyph {
|
||||||
|
final static int TRANSPARENT = new Color(0,0,0,0).getRGB();
|
||||||
int width=0;
|
int width=0;
|
||||||
int height=0;
|
int height=0;
|
||||||
boolean[] data = new boolean[]{};
|
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
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}*/
|
}*/
|
||||||
//ArcadeReader.retrieveData(Paths.get("itg1.png"));
|
ArcadeReader.retrieveData(Paths.get("ddr4.png"));
|
||||||
/* Path secretFile = Paths.get(".clientsecret");
|
/* Path secretFile = Paths.get(".clientsecret");
|
||||||
List<String> data;
|
List<String> data;
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user