Gå til innhold

Alternativ til: awt.Robot "getPixelColor" (treg).


Anbefalte innlegg

Hei.

Jeg leter etter alternativ løsning for å finne fargen til en gitt piksel på skjermen.

Grunnlag: Jeg finner Java.awt.Robot sin "getPixelColor" sinnsykt treg.

 

Tidligere, i python så har jeg tatt printscreen av skjermen, for å så søke i bildet etter en bestemt farge, og returnere pikselen hvor den ble funnet.

 

 

Indentation er nok bare "diskusjon.no" som tuller.

Java-søkeversjonen:

public static int[] colorAt(int x, int y) throws Exception {
Robot r = new Robot();
Color c = r.getPixelColor(x, y);
int[] color = {c.getRed(), c.getGreen(), c.getBlue()};
return color;
}

public static Point colorFindSpiral(int[] rgb, int X, int Y, int W, int H) throws Exception {
int x=0, y=0, dx=0, dy=-1;
int t = Math.max(X,Y);
int maxI = t*t;
int old = (int) (System.currentTimeMillis());
for (int i=0; i < maxI; i++){
	if ((-X/2 < x && x <= X/2) && (-Y/2 < y && y <= Y/2)) {
		int[] color = colorAt(x+W,y+H);
		if(color[0]==rgb[0] && color[1]==rgb[1] && color[2]==rgb[2]) {
			return new Point(x+W,y+H);
		}
	}

	if((x == y) || ((x < 0) && (x == -y)) || ((x < 0) && (x == 1-y))){
		t=dx; dx=-dy; dy=t;
	}
	x+=dx; y+=dy;
}
System.out.println((int) (System.currentTimeMillis())-old);
return null;
}

 

Python-variant (nesten tilsvarande) som er flere ti-talls hakk raksere, hvor jeg tar printscreen, for å så søke i bildet:

def FindSpiral(hex, X, Y, W, H, tol):
image = ImageGrab.grab() #Printscreen
r,g,b = hex_to_rgb(hex)
lab = rgb_to_lab(r, g, b)
sx,sy,dx,dy = 0,0,0,-1
WX,HY = (W+X)/2, (H+Y)/2
pix = image.load()
for i in xrange(max((W-X), (H-Y))**2):
	if (-WX < sx <= WX) and (-HY < sy <= HY):
		px = pix[WX+sx, HY+sy]
		px = rgb_to_lab(px[0],px[1],px[2])
		if max(map(lambda a,b: abs(a-b), px, lab)) < tol:
			return WX+sx, HY+sy

	if sx == sy or (sx < 0 and sx == -sy) or (sx < 0 and sx == 1-sy):
		dx, dy = -dy, dx
	sx, sy = sx+dx, sy+dy

 

 

Noen tips til raskere fremgangsmåte?

Endret av warpie
Lenke til kommentar
Videoannonse
Annonse

java.awt.Color har vell ingen metode kalt "colorAt"?

 

Siden eksemplet ditt da ikke kompilerer så vet jeg ikke hva som går tregt hos deg, og du har jo heller ingen benchmarks å måle opp med.

 

Min metode bruker da under 30ms på et bilde som er 1000px*1000px

0ms hvis koden finner farge på første pixel og ca 28ms hvis bilder ikke inneholder fargen i det hele tatt,

 

Jeg skjønner ikke helt hvorfor du sender in x,y,w,h til metoden din, men hvis intensjonen er å kun søke gjennom et rektangel i bilden så kan mitt forslag oppdaters ved å benytte variabler i for løkkene til å minimere søket og da vil selfølgelig søket gå enda raskere..

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.junit.Test;
public class ColorTest {
  @Test
  public void testColorSearch() throws IOException {
  final BufferedImage read = ImageIO.read(new File("D:\\Images\\red.png"));
  final BufferedImage image = new BufferedImage(read.getWidth(), read.getHeight(), BufferedImage.TYPE_INT_ARGB);
  image.getGraphics().drawImage(read, 0, 0, null);
  final long start = System.currentTimeMillis();
  final Point p = searchColor(image, new Color(255, 0, 0).getRGB());
  final long end = System.currentTimeMillis();
  if (p != null) {
	 System.out.println("Found color at x=" + p.x + ", y=" + p.y + "in " + (end - start) + "ms");
  } else {
	 System.out.println("Didnt find color in  " + (end - start) + "ms");
  }
  }
  private static Point searchColor(final BufferedImage image, final int color) {
  final int[] pixels = ((DataBufferInt) (image).getRaster().getDataBuffer()).getData();
  for (int x = 0; x < image.getWidth(); x++) {
	 for (int y = 0; y < image.getHeight(); y++) {
	    final int i = y * image.getWidth() + x;
	    if (pixels[i] == color) {
		   return new Point(x, y);
	    }
	 }
  }
  return null;
  }
}

Lenke til kommentar

Hmm... Ser nå at jeg har surret, men er rettet nå. PS: ~2 sekunder over 400*400, vs python som brukte millisekunder.

 

Selve funksjonen er ikke verd å tenke på. Den er noe spesiell. Jeg passerer X,Y = størrelsen på delen av bilde/skjerm som loopes. W, H er hvilke punkter han skal starte søket. Selve funkjsonen er nermere beskrevet der: http://www.diskusjon...owtopic=1412156

 

Skal se over koden du viser til i løpet av ettermiddagen i morgen, og sansynligvis så har du løst mitt problem.

 

//Edit ser nå at problemet var at jeg tok et nytt printscreen for hver del av loopen. Ved lage en løsning som benytter seg av BufferedImage så var dette løst.

Endret av warpie
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...