Recherche et travaille sur des tuiles

Pour tous ceux qui veulent aller plus plus dans les aspects techniques de Gimp.

Modérateur : Ze Techos

Répondre
Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Recherche et travaille sur des tuiles

Message par Deedolith » sam. mai 28, 2011 9:33 pm

Bonjour,

en fouinnant sur le net, j'ai trouvé beaucoup de tuto sur l'art et la maniere de faire des images repetables a partir d'une seule (tuile), mais j'aimerais faire l'operation inverse.

J'ai rippé (me demandez pas comment, je repondrai pas), une l'image du niveau d'un jeux, et separré sur une 2e images les differentes tuiles qui la constitue.

L'image du niveau fais 4096x4096 et il y a une cinquantaine de tuiles de 16x16.

Sur le fichier tuiles, j'ai crée un 2e calque, et dessiné pour chaque tuile un carré rempli d'une couleur unie et unique.
J'ai egalement crée un 2e calque sur l'image du niveau.

Je voudrais, rechecher dans le niveau les differentes tuiles et dessiner sur le 2e calque les carrés correspondant aux tuiles.

Visiblement gimp ne possede pas ce genre de fonctionalité, donc j'ai pensé a un script.

Dire que je debute avec python est une mot tres, tres, mais alors tres faible, neanmoin, j'ai ecrit quelque chose qui ressemble a ceci:

Code : Tout sélectionner

#!/usr/bin/env python

import gimpfu import *

	#fonction qui compare 2 tuiles 16x16
def tileCmp(tile1, tile2):
	dif = 1			# indicateur de differences
	for (x in range(16):	# parcours les tableau de tuiles
		for (y in range(16):
			if(tile1[x][y] != tile2[x][y]):	#une difference trouvée ? met l'indicateur a 0
				dif=0
	return dif

def getTile(calque, x, y):	#retourne la tuile aux coordonnées X, Y
	tile[16, 16]
	i = 0;
	j = 0;
	for a in range(x, x+16):
		for b in range(y, y+16):
			tile[i, j] = calque.get_pixel(a, b)
			j = j + 1
		i = i + 1
	return tile

def setTile(calque, x, y, tile):	# ecrit une tuile aux coordonnées X, Y
	i=0
	j=0
	for a in range (x, x+16):
		for b in range (y, y+16):
			calque.set_pixel(a, b, tile[i, j])
			j = j + 1
		i = i + 1

	#recherche dans img les tuiles contenues dans tileSet
def tilesCheck(img, tileSet):
	tile1[16, 16]		#tableaux contenant les pixels d'une tuile		
	tile2[16, 16]
	tileColor[16, 16]
	BACK, FONT = 0, 1	# indices des calques, background et foreground

		# parcours tileSet, a la recherche des tuiles
	for x in range(0, tileSet.width, 16):
		for y in range(0, tileSet.height, 16):
				# pixel different de noir ? une tuile trouvée
			if (tileSet.layers[BACK].get_pixel(x, y) != 0):
				tile1 = getTile(tileSet.layers[BACK], x, y)		# sauve la tuile
				tileColor = getTile(tileSet.layers[FRONT], x, y)	# sauve la couleur correspondante
				for (a in range(0, img.width), 16):				#parcours img tuiles a tuiles
					for (b in range(0, img.height, 16):
						tile2 = getTile(img.layers[BACK], a, b)			# sauve la tuile courante
						if (tileCmp(tile1, tile2) == 1):			# tuile courrante et tuile de tileSet identiques ?
							setTile(img.layers[FRONT], a, b, tileColor)		# oui, ecrit le carré de couleur correspondant dans le calque
Suis-je sur la bonne voie ? ou a des années lumieres ?

PS: je n'ai pas encore compris comment enregistrer un script au sein de gimp.

Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Re: Recherche et travaille sur des tuiles

Message par Deedolith » dim. mai 29, 2011 11:42 pm

Ok, j'avais la logique de base, il ne me restais plus qu'a aquerir la logique (bizarre) de python, et la logique (tres bizarre) de python::fu.
Je ne dirais pas que c'est chose faite, neamoin, apres multiples recherche plus ou moin fructueuses, après un nombre illimité d'essais et d'erreurs, j'ai reussi a m'en sortir:

Code : Tout sélectionner

#!/usr/bin/env python



from gimpfu import *

from time import time



	#retourne les valeurs RVB d'un pixel

def getRVB(pixel):

	R, V, B = pixel[0], pixel[1], pixel[2]

	return R, V, B



def getR(pixel):

	return pixel[0]



def getV(pixel):

	return pixel[1]



def getB(pixel):

	return pixel[2]



	#fonction qui compare 2 tuiles 16x16

def tileCmp(tile1, tile2):

	for x in range(16):	# parcours les tableau de tuiles

		for y in range(16):

			if(tile1 != tile2):

				return 0

	return 1



def getTile(calque, x, y):	#retourne la tuile aux coordonnees X, Y

	pr = calque.get_pixel_rgn(x,y,16,16)

	return pr[x : x+16, y : y+16]



def setTile(calque, x, y, tile):	# ecrit une tuile aux coordonnees X, Y

	pr = calque.get_pixel_rgn(x,y,16,16)

	pr[x : x+16, y : y+16] = tile





def python_chercher_les_tuiles(img, layer, tileSetIMG, ltileSetLayerCOLOR, tileSetLayerTILE, imgIMG, imgLayerCOLOR, imgLayerTILE) :

	# Actual plug-in code will go here

	tile1 = []	#tableaux contenant les pixels d'une tuile		

	tile2 = []

	tileColor = []

	tuileTotales = (imgIMG.width/16) * (imgIMG.height/16)

	tuileTraitee = 0;

	tps = time()



	

	for x in range(16):

		tile1.append([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

		tile2.append([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

		tileColor.append([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])



		# parcours la feuille de tuiles, a la recherche des tuiles

	for x in range(0, tileSetIMG.width, 16):

		for y in range(0, tileSetIMG.height, 16):

			if (tuileTraitee != tuileTotales):

					# pixel different de noir ? une tuile trouvee

				if (getRVB(tileSetLayerTILE.get_pixel(x, y)) != (0, 0, 0)):

					pdb.gimp_rect_select(tileSetIMG, x, y, 16, 16, 2, False, 0)

					tile1 = getTile(tileSetLayerTILE, x, y)			# sauve la tuile

					pixelColor = getTile(ltileSetLayerCOLOR, x, y)		# sauve la couleur correspondante

					for a in range(0, imgIMG.width, 16):			#parcours img tuiles a tuiles

						for b in range(0, imgIMG.height, 16):

							if (getRVB(imgLayerCOLOR.get_pixel(a, b)) == (0, 0, 0)):

								tile2 = getTile(imgLayerTILE, a, b)			# sauve la tuile courante

								if (tileCmp(tile1, tile2) == 1):			# tuile courrante et tuile de la feuille de tuiles identiques ?

									setTile(imgLayerCOLOR, a, b, pixelColor)	# oui, ecrit le carre de couleur correspondant dans le calque

									tuileTraitee = tuileTraitee + 1

									print tuileTraitee, "tuiles sur ", tuileTotales

									#pdb.gimp_displays_flush()

	print "image traitee en", time() - tps

	return



register(

	"chercher_les_tuiles",

	"Cherche les tuiles",

	"Cherche les tuiles dans une image a partir d'une feuille de tuiles",

	"Fabrice Lambert, Grinwik",

	"Fabrice Lambert",

	"2011",

	"Chercher les tuiles...",

	"RGB*",

	[

	(PF_IMAGE, "img", "Image: ", None),

	(PF_DRAWABLE, "layer", "Calque: ", None),

	(PF_IMAGE, "tileSetIMG", "Feuille de tuiles", None),

	(PF_DRAWABLE, "tileSetLayerCOLOR", "Calque tileSet COLORS: ", None),

	(PF_DRAWABLE, "tileSetLayerTILE", "Calque tileSet TUILES: ", None),

	(PF_IMAGE, "imgIMG", "Image cible", None),

	(PF_DRAWABLE, "imgLayerCOLOR", "Calque cible COLORS:", None),

	(PF_DRAWABLE, "imgLayerTILE", "Calque cible TUILES:", None)

	],

	[],

	python_chercher_les_tuiles,

		menu="<Image>/Filters/Mes Scripts")



main()
Et le resultat en images:
D'abord ma feuille de tuiles:
Image
Ainsi que, sur le 2e calque, les couleurs de correspondance (choisies par mes soins):
Image
Puis viens l'image de test: (j'ai simplement copié/collé quelques tuiles).
Image
A ce stade, le 2e calque de l'image de test est vide.

Ensuite, laissons le script bosser, on obtient le resultat suivant, sur le 2e calque de l'image de test:
Image

Seul point etrange, lorsque mon script a terminé, je doit desactiver et reactiver la visibilité du 2e calque de l'image de test, aurais-je oublié quelque chose ?


Et enfin, place au sport, avec a la place de l'image de test, mon image de depart (4096x4096) :shock: , je vais me pieuter, les calculs serons peut etre terminés demain matin :l0l: .

Questions et commentaires bienvenus
Dernière modification par Deedolith le ven. juin 03, 2011 3:04 pm, modifié 2 fois.

Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Re: Recherche et travaille sur des tuiles

Message par Deedolith » mar. mai 31, 2011 1:56 pm

Ca marche, mais c'est affreusement lent !!
Après une nuit de travail, environ 3% de l'image a été traitée.

Y existe t'il des solutions plus rapides ?

Avatar de l’utilisateur
Bellette
Maître pisteur
Messages : 1311
Inscription : dim. oct. 23, 2005 4:52 pm
Localisation : Grenoble/Lyon
Contact :

Re: Recherche et travaille sur des tuiles

Message par Bellette » mar. mai 31, 2011 8:50 pm

Je ne sais pas programmer en python, mais à te lire je peux déjà te suggérer quelques optimisations :

- Pour comparer deux tuiles tu compares tous les pixels entre eux, il suffirait de comparer les pixels sur une ou deux diagonales, non ? À première vue tes tuiles ont toutes une diagonale unique. On passe de quand même de 256 comparaisons à entre 16 et 31. Ou alors comparer des pixels qui discriminent bien les images entre elles.
- Pareil, tu compares tous les canaux RVB entre eux, un seul ne suffirait pas ?
- Tu peins pixel par pixel dans ta fonction setTile : probablement qu'un petit rectangle dessiné avec les bonnes coordonnées est (beaucoup?) plus rapide à l'exécution ;)

Voili voilou, mes petits commentaires :)
[b]Administrateur GA[/b]

Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Re: Recherche et travaille sur des tuiles

Message par Deedolith » mar. mai 31, 2011 11:57 pm

Bellette a écrit : - Pour comparer deux tuiles tu compares tous les pixels entre eux, il suffirait de comparer les pixels sur une ou deux diagonales, non ? À première vue tes tuiles ont toutes une diagonale unique. On passe de quand même de 256 comparaisons à entre 16 et 31. Ou alors comparer des pixels qui discriminent bien les images entre elles.
Pour les images que j'ai posté, les diagonales uniques sont peut etre une particularité. Neanmoin je retient l'idée, il faudra cependant que je verifie avec mes autres images (y'en a plein).
Bellette a écrit : - Pareil, tu compares tous les canaux RVB entre eux, un seul ne suffirait pas ?
Effectivement, mon voisin (qui a fais des etudes en video) me conseille de comparer sur le canal vert, et de sortir de la fonction dès que j'ai une difference.
Bellette a écrit : - Tu peins pixel par pixel dans ta fonction setTile : probablement qu'un petit rectangle dessiné avec les bonnes coordonnées est (beaucoup?) plus rapide à l'exécution ;)
A essayer, avec ma prochaine image.

Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Re: Recherche et travaille sur des tuiles

Message par Deedolith » jeu. juin 02, 2011 12:39 am

Bellette a écrit : - Tu peins pixel par pixel dans ta fonction setTile : probablement qu'un petit rectangle dessiné avec les bonnes coordonnées est (beaucoup?) plus rapide à l'exécution ;)
Probleme, je ne trouve pas quel(s) fonction(s) utiliser :(

A part ca, j'ai egalement fais 2 changement supplementaire:
Ma fonction setTile prend maintenant un pixel comme parametre, et peint toute la tuile pixel par pixel (faute de mieux).

Plutot que de sauvegarder la tuile de couleur unie (variable tileColor), je recupere juste 1 pixel que je refile si besoin a ma fonction setTile.
(code edité dans mon 2è poste).

Avatar de l’utilisateur
Bellette
Maître pisteur
Messages : 1311
Inscription : dim. oct. 23, 2005 4:52 pm
Localisation : Grenoble/Lyon
Contact :

Re: Recherche et travaille sur des tuiles

Message par Bellette » jeu. juin 02, 2011 10:21 am

Deedolith a écrit : Probleme, je ne trouve pas quel(s) fonction(s) utiliser :(
Il faut faire une sélection rectangulaire que tu remplis de ta couleur, si c'est ça le souci ;)
[b]Administrateur GA[/b]

Deedolith
Wilber en peluche
Messages : 7
Inscription : sam. mai 28, 2011 8:54 pm

Re: Recherche et travaille sur des tuiles

Message par Deedolith » ven. juin 03, 2011 3:01 pm

On m'a indiqué les regions de pixel .... :o ..... :o ..... :o ......... Grande Magie !!! :D :D

Mon script va environ 60 fois plus vite.
48 minutes contre un peut plus de 36h pour analyser mon image 4096x4096.

Merci pour tout.

Code edité dans mon poste precedent.

Répondre