First initial detection system for DDR scores using pixel checking algorithm (#1)

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
main
sigonasr2, Sig, Sigo 2 years ago
parent 8eb9edb71a
commit 0f3c03be58
  1. 2
      ArcadeReader.java
  2. 125
      readers/DDRReader.java
  3. 81
      readers/fonts/Font.java
  4. 56
      readers/fonts/Glyph.java
  5. BIN
      result.png
  6. 2
      sigPlace.java

@ -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);
}
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;
}
}

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…
Cancel
Save