IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

GD Traitement d'image, Traits horizontaux


Sujet :

PHP & Base de données

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut GD Traitement d'image, Traits horizontaux
    Bonjour

    Voici un script qui, pour une image noir et blanc, remplir de gris toutes les formes blanches inférieures à $limit pixels, en l'occurence 700 :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    <?php
     
    	$begin = microtime(true); 
     
    	$image = imagecreatefrompng("8.png"); 
      	$white = imagecolorallocate($image, 255, 255, 255);
      	$lightGrey = imagecolorallocate($image, 160, 160, 160);
      	$darkGrey = imagecolorallocate($image, 80, 80, 80);
     
      	list($width, $height) = getimagesize('8.png');
     
    	$limit = 700;
     
    	for ($i=1; $i<$width; $i++) {
     
    		for ($j=1; $j<$height; $j++) {
     
    			if (imagecolorat($image, $i, $j) == $white)  
    			{
    				$stack = array(
    					array($i, $j)
    				);
     
    				$toFill = array();
     
    				while (count($stack) > 0) {
     
    					$current = array_pop($stack);
     
    					array_push($toFill, $current); 
     
    					// gros bug à cause de cette condition
    					if (count($toFill) > $limit)
    						break;
     
    					imagesetpixel($image, $current[0], $current[1], $lightGrey); 
     
    					$north = array($current[0], $current[1]-1);
    					$south = array($current[0], $current[1]+1);
    					$west = array($current[0]-1, $current[1]);
    					$east = array($current[0]+1, $current[1]);
     
    					if ($north[1] > 0 && imagecolorat($image, $north[0], $north[1]) == $white)
    						array_push($stack, $north);
     
    					if ($south[1] < $height && imagecolorat($image, $south[0], $south[1]) == $white) 
    						array_push($stack, $south);
     
    					if ($west[0] > 0 && imagecolorat($image, $west[0], $west[1]) == $white) 
    						array_push($stack, $west);
     
    					if ($east[0] < $width && imagecolorat($image, $east[0], $east[1]) == $white) 
    						array_push($stack, $east);
    				}
     
    				if (count($toFill) < $limit) { 
     
    					while (count($toFill) > 0) {
     
    						$current = array_pop($toFill);
     
    						imagesetpixel($image, $current[0], $current[1], $darkGrey); 
     
    					}
     
    				}
     
    				unset($stack);
    				unset($toFill);
     
    			}
    		}
    	}
     
    	imagepng($image, 'result.png');
    	imagedestroy($image);
     
    	$end = microtime(true);
     
    	echo ($end - $begin);
     
    ?>

    Lorsque je ne mets pas la condition suivante :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (count($toFill) > $limit)
    	break;

    Le rendu est nikel, mais mon algo est forcément plus long car les boucles vont au bout, y compris pour les formes > 700 pixels. Je pensais justement mettre cette condition pour optimiser, et donc stopper la boucle au lieu de la faire tourner inutilement.

    Mais en laissant la condition donc, je me retrouve avec des traits sur mon image finale, qui ressemblent à un problème de gestion de mémoire..
    https://drive.google.com/drive/folde...u1?usp=sharing

    Qu'en pensez vous ? Où ai-je fait une bêtise ?

    Merciiii

  2. #2
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 597
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 597
    Par défaut
    quand vous parlez de 700 pixels, vous cherchez les surfaces inférieures à cette valeur ?

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut
    Tout à fait

  4. #4
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 597
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 597
    Par défaut
    je n'ai pas encore eu le temps de tester mais j'ai une piste : quand vous comptez les cases, vous mettez en même temps les coordonnées dans $toFill.
    et si vous arrêtez de compter à 700, vous n'aurez pas tous les pixels de la zone dans $toFill et donc vous allez seulement colorier les 700 premiers pixels.

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut
    Citation Envoyé par mathieu Voir le message
    je n'ai pas encore eu le temps de tester mais j'ai une piste : quand vous comptez les cases, vous mettez en même temps les coordonnées dans $toFill.
    et si vous arrêtez de compter à 700, vous n'aurez pas tous les pixels de la zone dans $toFill et donc vous allez seulement colorier les 700 premiers pixels.
    Nous parlons bien ici du cas des surfaces > 700 pixels, dont il ne faut pas tenir compte ? (et donc à colorier en gris clair)
    Hum oui vous avez tout à fait raison mais pour moi ce n'est pas grave, ma loop "de base" itère sur chaque pixel, il y a bien un moment où je vais retomber sur un pixel blanc, à partir duquel je vais refaire un flood de 700 pixels, ou moins. Je pense notamment à tout le blanc de "fond" qui est traité (enfin je pense.. !) de cette manière ?

    EDIT : je crois que je suis sur la voie.. En rajoutant un goto qui joue un role d'exit après 2 formes de < 700 pixels détectées j'obtiens l'image attachée. Je pense que le bug vient de l'algorithme de flood

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    $limit = 700;
     
    	$times = 0;
     
    	for ($i=1; $i<$width; $i++) {
     
    		for ($j=1; $j<$height; $j++) {
     
    			if (imagecolorat($image, $i, $j) == $white)  
    			{
    				$stack = array(
    					array($i, $j)
    				);
     
    				$toFill = array();
     
    				while (count($stack) > 0) {
     
    					$current = array_pop($stack);
     
    					array_push($toFill, $current); 
     
     
    					// gros bug à cause de cette condition
    					if (count($toFill) > $limit) {
     
    						imagesetpixel($image, $current[0], $current[1], $white); 
     
    						break;
    					}
     
     
     
    					imagesetpixel($image, $current[0], $current[1], $lightGrey); 
     
    					$north = array($current[0], $current[1]-1);
    					$south = array($current[0], $current[1]+1);
    					$west = array($current[0]-1, $current[1]);
    					$east = array($current[0]+1, $current[1]);
     
    					if ($north[1] > 0 && imagecolorat($image, $north[0], $north[1]) == $white)
    						array_push($stack, $north);
     
    					if ($south[1] < $height && imagecolorat($image, $south[0], $south[1]) == $white) 
    						array_push($stack, $south);
     
    					if ($west[0] > 0 && imagecolorat($image, $west[0], $west[1]) == $white) 
    						array_push($stack, $west);
     
    					if ($east[0] < $width && imagecolorat($image, $east[0], $east[1]) == $white) 
    						array_push($stack, $east);
    				}
     
    				if (count($toFill) < $limit) { 
     
    					while (count($toFill) > 0) {
     
    						$current = array_pop($toFill);
     
    						imagesetpixel($image, $current[0], $current[1], $darkGrey); 
     
    					}
     
    					if ($times++ >= 1)
     
    						goto end;
     
    				}
     
     
     
     
     
    				unset($stack);
    				unset($toFill);
     
    			}
    		}
    	}
     
    	end:
     
    	imagepng($image, 'result.png');
    	imagedestroy($image);
    Images attachées Images attachées  

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Par défaut
    Finalement je n'ai pas voulu perdre de temps à réinventer la roue :

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    <?php
     
        $image = imagecreatefrompng("0.png"); 
    	$width = imagesx($image);
      	$height = imagesy($image);
     
      	$white = imagecolorallocate($image, 255, 255, 255);
      	$lightGrey = imagecolorallocate($image, 160, 160, 160);
      	$red = imagecolorallocate($image, 255, 0, 0);
      	$green = imagecolorallocate($image, 0, 255, 0);
     
        $command = 'convert 0.png                                           \
            -define connected-components:verbose=true                       \
            -connected-components 4 null: | grep "srgba(255,255,255,1)"';
     
        $result = shell_exec($command);
        $array = explode(" srgba(255,255,255,1)", $result);
     
        for ($i=0; $i<count($array); $i++) {
     
            preg_match('/([0-9]*).[0-9],([0-9]*).[0-9] ([0-9]*)/', $array[$i], $match);
     
            if ($match[3] < 700 && $match[3] > 50) {
     
                $stack = array(
        			array($match[1], $match[2])
        		);
     
        		while (count($stack) > 0) {
     
        			$current = array_pop($stack);
     
        			imagesetpixel($image, $current[0], $current[1], $lightGrey); 
     
        			$north = array($current[0], $current[1]-1);
        			$south = array($current[0], $current[1]+1);
        			$west = array($current[0]-1, $current[1]);
        			$east = array($current[0]+1, $current[1]);
     
        			if ($north[1] >= 0 && imagecolorat($image, $north[0], $north[1]) == $white)
        				array_push($stack, $north);
     
        			if ($south[1] < $height && imagecolorat($image, $south[0], $south[1]) == $white) 
        				array_push($stack, $south);
     
        			if ($west[0] >= 0 && imagecolorat($image, $west[0], $west[1]) == $white) 
        				array_push($stack, $west);
     
        			if ($east[0] < $width && imagecolorat($image, $east[0], $east[1]) == $white) 
        				array_push($stack, $east);
     
        		}
     
            }
     
        }
     
        imagepng($image, 'result.png');
    	imagedestroy($image);
     
     
     
     
        //echo implode("</br>", $array);;
     
    ?>

    Et ça fonctionne nikel !!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Traitement d'images : quel langage?
    Par belasri dans le forum Langages de programmation
    Réponses: 19
    Dernier message: 07/10/2005, 09h59
  2. Réponses: 5
    Dernier message: 15/01/2005, 18h29
  3. commande c++ pour le traitement d'images
    Par mateo.14 dans le forum MFC
    Réponses: 2
    Dernier message: 12/01/2005, 10h46
  4. [lib] Traitement d'images
    Par Gogoye dans le forum Multimédia
    Réponses: 4
    Dernier message: 19/11/2004, 16h15
  5. Traitements d'image sur PNG avec transparence
    Par Ingham dans le forum Langage
    Réponses: 16
    Dernier message: 02/08/2004, 16h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo