Récupérer les coordonnées d'une couleur a l'ecran [Résolu]

Dudul86 2 Messages postés dimanche 14 février 2010Date d'inscription 15 février 2010 Dernière intervention - 14 févr. 2010 à 18:38 - Dernière réponse : Dudul86 2 Messages postés dimanche 14 février 2010Date d'inscription 15 février 2010 Dernière intervention
- 15 févr. 2010 à 18:27
Bonjour à tous.
J'ai comme idée de faire un programme qui détecte la présence d'une couleur à l'écran (par exemple du vert) et renvoi les coordonnées du 1er pixel de cette couleur qu'il a rencontré. Je n'ai pas de langage particulier en vue, j'aime bien le java et le c++ mais d'autres propositions sont les bienvenues (du moment que c'est une application locale et pas web ^^).

J'ai déjà pensé a une solution simple: prendre tout les pixel un par un grâce a deux boucles, et comparer leur couleur avec la couleur désirée. J'ai deux programmes qui marchent, un en C++ et un en java:

Java :

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Robot;
import java.lang.Object;

public class Main {

    
    public static void main(String[] args) throws AWTException {
        // TODO code application logic here
       Robot rob1 = new Robot();
       Color couleur = null;
       int i=0, j=0;
       while (i < 100 /*&& (couleur == null || couleur.getGreen() != 254)*/)
       {
           j = 0;
           while (j < 100 /*&& (couleur == null || couleur.getGreen() != 254)*/)
           {
               couleur = rob1.getPixelColor(i,j);
               System.out.println(couleur+" x "+i+"  y "+j);
               j++;
           }
           i++;
       }
       System.out.println(couleur);
       System.out.println(i+" "+j);
    }
}



C++:

#include <stdio.h>
#include <stdafx.h>
#include <stdlib.h>
#include <windows.h>
#include <richedit.h>

int main(int argc, char *argv[])
{long R,G,B;
 HDC dc = GetDC(NULL);
COLORREF pix;
int x = 200;
int y = 100;
bool stop = false;
while (x < 1480 && stop != true)
{
y = 100;
while (y < 1000 && stop != true)
{
pix = GetPixel(dc, x, y);
R = GetRValue(pix);
G = GetGValue(pix);
B = GetBValue(pix);
if(R 255 && G 255 && B == 255)
{
stop = true;
}
y++;
printf("ROUGE :%ld\n",R);
printf("VERT :%ld\n",G);
printf("BLEU :%ld\n\n",B);
printf("X :%d\n",x);
printf("Y :%d\n",y);
}
x++;
}
system("pause");
return (0);  
} 



Le principal soucis de ces deux codes, c'est qu'ils sont très lents, je m'explique, dans l'idéal j'aimerai pouvoir scanner tout l'écran en moins de 10 secondes, voir quasi instantanément. La ça prend plusieurs minutes, d'autant que je suis en 1680*1100. Quelqu'un aurait une idée, par exemple si il existe une manière de trouver directement une couleur a l'écran de manière instantanée, ou s'il y a une manière de récupérer la couleur de chaque pixel beaucoup plus rapidement...


J'espère que mon problème est clairement expliqué et que mon code n'est pas trop brouillon ^^ Merci d'avance.
Afficher la suite 

Votre réponse

3 réponses

Meilleure réponse
cs_jojolemariole 519 Messages postés mercredi 21 mars 2007Date d'inscription 19 décembre 2016 Dernière intervention - 15 févr. 2010 à 10:19
2
Merci
Re, voilà j'ai fait un petit code rapide.

J'ai intégré la notion de marge d'erreur (on ne cherche pas la couleur exacte mais on tolère une petite différence), de plus pour booster la vitesse de traitement on peut tester seulement une partie des pixel en quadrillant. Le traitement se fait non pas sur l'écran mais sur une capture faite en début d'algo. Si tu cherches un objet qui fait 4 x 4 pixels de large tu peux mettre le paramètre step à 4, tu le louperas pas et de plus tes performances seront considérablement améliorées (16x moins de pixels à tester).

Fais-moi un retour, c'est le genre de trucs qui m'intéressent.



package bot;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Set;


/**
 * @author GUEHENNEUX
 */
public class ColorFinder {

    private Robot robot;

    private Toolkit toolkit;

    /**
     * @throws AWTException
     */
    public ColorFinder() throws AWTException {

        robot = new Robot();
        toolkit = Toolkit.getDefaultToolkit();

    }

    /**
     * @param color
     * @param margin
     * @param step
     * @return
     */
    public Set getPixels(Color color, double margin, int step) {

        Dimension screenSize = toolkit.getScreenSize();

        int screenWidth = screenSize.width;
        int screenHeight = screenSize.height;

        /*
         * on fait une capture d'ecran afin d'optimiser le traitement
         */

        Rectangle zoneCapture = new Rectangle(screenSize);
        BufferedImage capture = robot.createScreenCapture(zoneCapture);

        int x, y;

        Color pixelColor;

        Set pixels = new HashSet();

        double colorDistance;

        for (x = 0; x < screenWidth; x += step) {

            for (y = 0; y < screenHeight; y += step) {

                pixelColor = new Color(capture.getRGB(x, y));

                /*
                 * on regarde si la couleur du pixel est proche de celle
                 * attendue
                 */

                colorDistance = getDistance(color, pixelColor);

                if (colorDistance <= margin) {
                    pixels.add(new Point(x, y));
                }

            }

        }

        return pixels;

    }

    /**
     * @param color1
     * @param color2
     * @return the distance between the two colors
     */
    public static double getDistance(Color color1, Color color2) {

        int r1 = color1.getRed();
        int r2 = color2.getRed();
        int g1 = color1.getGreen();
        int g2 = color1.getGreen();
        int b1 = color1.getBlue();
        int b2 = color2.getBlue();

        int rDistance = Math.abs(r1 - r2);
        int gDistance = Math.abs(g1 - g2);
        int bDistance = Math.abs(b1 - b2);

        double rDistanceCube = Math.pow(rDistance, 3);
        double gDistanceCube = Math.pow(gDistance, 3);
        double bDistanceCube = Math.pow(bDistance, 3);

        double distance = Math.pow(rDistanceCube + gDistanceCube + bDistanceCube, 1.0 / 3);

        return distance;

    }

    /**
     * methode de test
     * 
     * @param args
     * @throws AWTException
     */
    public static void main(String[] args) throws AWTException {

        ColorFinder colorFinder = new ColorFinder();

        System.out.println("Il y a " + colorFinder.getPixels(Color.BLUE, 2, 2).size()
            + " pixel(s) dont la couleur est proche de celle demandée.");

    }

}


Jonathan

Merci cs_jojolemariole 2

codes-sources a aidé 81 internautes ce mois-ci

Commenter la réponse de cs_jojolemariole
cs_jojolemariole 519 Messages postés mercredi 21 mars 2007Date d'inscription 19 décembre 2016 Dernière intervention - 15 févr. 2010 à 09:46
0
Merci
Salut,

Ça sent le cheat, graçon!
D'ores et déjà, ce qui plombe tes chronos sont les sorties sur la console (System.out.print...). Refais un test sans pour voir, je regarde de mon côté.
Commenter la réponse de cs_jojolemariole
Dudul86 2 Messages postés dimanche 14 février 2010Date d'inscription 15 février 2010 Dernière intervention - 15 févr. 2010 à 18:27
0
Merci
Merci de ta réponse, en effet ton algorithme est bien plus rapide... plus que les affichages, je pense que ce qui me retardait principalement c'était le fait de traiter l'immage telle qu'elle apparaissait a l'écran au lieu de faire un screenshot et de le traiter ensuite. Je vais adapter ta solution a mon idée et je posterai ici une solution plus détaillée ^^.
Commenter la réponse de Dudul86

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.