Recherche de teinte dans une image

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Recherche de teinte dans une image

Message par Le Soldat Inconnu »

Coucou,

Un petit code qui permet d'analyser les teintes de couleur dans une image pour extraire les zones ayant une composante particulière.

Actuellement, je m'en sert pour trouver les zones avec de la peau sur des photos (Visage et autre)

Donc le réglage du filtre permet de trouver la peau. Mais vous pouvez modifier le réglage via l'interface.
Vous avez 3 plages à régler :
La composante blanche de la couleur : (du blanc vers la couleur la plus intense)
La composante noir : (plus ou moins sombre)
La teinte

Il faut que vous indiquiez en début de code un dossier contenant vos images.
Pour passer à l'image suivante, il faut cliquer sur l'image dans l'interface.

Code : Tout sélectionner

#Dossier = "D:\Votre dossier image\"

Global Dim ArcEnCiel_Couleur(3060)
Procedure ArcEnCiel()
	Rouge = 255
	Vert = 0
	Bleu = -1
	y = 0
	For x = 0 To 3060
		Select y
			Case 0
				Bleu + 1
				If Bleu = 255
					y + 1
				EndIf
			Case 1
				Rouge - 1
				If Rouge = 0
					y + 1
				EndIf
			Case 2
				Vert + 1
				If Vert = 255
					y + 1
				EndIf
			Case 3
				Bleu - 1
				If Bleu = 0
					y + 1
				EndIf
			Case 4
				Rouge + 1
				If Rouge = 255
					y + 1
				EndIf
			Case 5
				Vert - 1
				If Vert = 0
					y = 0
				EndIf
		EndSelect
		ArcEnCiel_Couleur(x) = RGB(Rouge, Vert, Bleu)
		; Debug RSet(Hex(ArcEnCiel_Couleur(x)), 6, "0")
	Next
EndProcedure

Procedure TeintePeau(Color, Blanc_Min, Blanc_Max, Noir_Min, Noir_Max, Teinte_Min, Teinte_Max)
	Protected a.d
	Rouge = Color & $FF
	Vert = Color >> 8 & $FF
	Bleu = Color >> 16 & $FF
	
	; Recherche de la teinte
	If Bleu >= Vert And Bleu >= Rouge And Bleu > 0
		a = 255 / Bleu
		Nuance_Noir = 255 - Bleu
		Bleu = 255
		Vert = a * Vert
		Rouge = a * Rouge
	ElseIf Vert >= Bleu And Vert >= Rouge And Vert > 0
		a = 255 / Vert
		Nuance_Noir = 255 - Vert
		Bleu = a * Bleu
		Vert = 255
		Rouge = a * Rouge
	ElseIf Rouge >= Vert And Rouge >= Bleu And Rouge > 0
		a = 255 / Rouge
		Nuance_Noir = 255 - Rouge
		Bleu = a * Bleu
		Vert = a * Vert
		Rouge = 255
	Else
		Nuance_Noir = 255
		Bleu = 255
		Vert = 255
		Rouge = 255
	EndIf
	
	If Bleu < Vert And Bleu < Rouge
		a = 1 - Bleu / 255
		Nuance_Blanc = 255 - Bleu
		Vert = (Vert - Bleu) / a
		Rouge = (Rouge - Bleu) / a
		Bleu = 0
	ElseIf Vert < Bleu And Vert < Rouge
		a = 1 - Vert / 255
		Nuance_Blanc = 255 - Vert
		Bleu = (Bleu - Vert) / a
		Rouge = (Rouge - Vert) / a
		Vert = 0
	ElseIf Rouge < Bleu And Rouge < Vert
		a = 1 - Rouge / 255
		Nuance_Blanc = 255 - Rouge
		Bleu = (Bleu - Rouge) / a
		Vert = (Vert - Rouge) / a
		Rouge = 0
	Else
		Nuance_Blanc = 255
	EndIf
	
	Color = RGB(Rouge, Vert, Bleu)
	For Teinte = 0 To 3060
		If ArcEnCiel_Couleur(Teinte) = Color
			Break
		EndIf
	Next
	
	If (Blanc_Max >= Blanc_Min And (Nuance_Blanc > Blanc_Max Or Nuance_Blanc < Blanc_Min)) Or (Blanc_Min > Blanc_Max And (Nuance_Blanc > Blanc_Min Or Nuance_Blanc < Blanc_Max))
		Color = 0
	EndIf
	If (Noir_Max >= Noir_Min And (Nuance_Noir > Noir_Max Or Nuance_Noir < Noir_Min)) Or (Noir_Min > Noir_Max And (Nuance_Noir > Noir_Min Or Nuance_Noir < Noir_Max))
		Color = 0
	EndIf
	If (Teinte_Max >= Teinte_Min And (Teinte > Teinte_Max Or Teinte < Teinte_Min)) Or (Teinte_Min > Teinte_Max And (Teinte > Teinte_Min Or Teinte < Teinte_Max))
		Color = 0
	EndIf
	
	ProcedureReturn Color
EndProcedure

UseJPEGImageDecoder()
NewList Image.s()
If ExamineDirectory(0, #Dossier, "*.jpg")
	While NextDirectoryEntry(0)
		If DirectoryEntryType(0) = #PB_DirectoryEntry_File
			AddElement(Image())
			Image() = #Dossier + DirectoryEntryName(0)
		EndIf
	Wend
	FinishDirectory(0)
EndIf

ArcEnCiel()

Blanc_Min = 80
Blanc_Max = 160
Noir_Min = 0
Noir_Max = 128
Teinte_Min = 1400
Teinte_Max = 1440

OpenWindow(0, 0, 0, 100, 100, "Image", #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget | #PB_Window_SystemMenu | #PB_Window_Maximize)
Enumeration
	#Blanc_Min
	#Blanc_Max
	#Blanc_Min_Barre
	#Blanc_Max_Barre
	#Noir_Min
	#Noir_Max
	#Noir_Min_Barre
	#Noir_Max_Barre
	#Teinte_Min
	#Teinte_Max
	#Teinte_Min_Barre
	#Teinte_Max_Barre
	#Image
	#ImageOrigine
EndEnumeration
y = 0
TextGadget(#PB_Any, 0, y, 256, 16, "Composante blanche :")
y + 16
TextGadget(#PB_Any, 0, y, 48, 24, "Min : ", #PB_Text_Right)
StringGadget(#Blanc_Min, 48, y, 48, 24, Str(Blanc_Min), #PB_String_ReadOnly)
TrackBarGadget(#Blanc_Min_Barre, 96, y, 160, 24, 0, 255)
SetGadgetState(#Blanc_Min_Barre, Blanc_Min)
y + 24
TextGadget(#PB_Any, 0, y, 48, 24, "Max : ", #PB_Text_Right)
StringGadget(#Blanc_Max, 48, y, 48, 24, Str(Blanc_Max), #PB_String_ReadOnly)
TrackBarGadget(#Blanc_Max_Barre, 96, y, 160, 24, 0, 255)
SetGadgetState(#Blanc_Max_Barre, Blanc_Max)
y + 24
y + 8
TextGadget(#PB_Any, 0, y, 256, 16, "Composante noire :")
y + 16
TextGadget(#PB_Any, 0, y, 48, 24, "Min : ", #PB_Text_Right)
StringGadget(#Noir_Min, 48, y, 48, 24, Str(Noir_Min), #PB_String_ReadOnly)
TrackBarGadget(#Noir_Min_Barre, 96, y, 160, 24, 0, 255)
SetGadgetState(#Noir_Min_Barre, Noir_Min)
y + 24
TextGadget(#PB_Any, 0, y, 48, 24, "Max : ", #PB_Text_Right)
StringGadget(#Noir_Max, 48, y, 48, 24, Str(Noir_Max), #PB_String_ReadOnly)
TrackBarGadget(#Noir_Max_Barre, 96, y, 160, 24, 0, 255)
SetGadgetState(#Noir_Max_Barre, Noir_Max)
y + 24
y + 8
TextGadget(#PB_Any, 0, y, 256, 16, "Teinte :")
y + 16
TextGadget(#PB_Any, 0, y, 48, 24, "Min : ", #PB_Text_Right)
StringGadget(#Teinte_Min, 48, y, 48, 24, Str(Teinte_Min), #PB_String_ReadOnly)
TrackBarGadget(#Teinte_Min_Barre, 96, y, 160, 24, 0, 3060)
SetGadgetState(#Teinte_Min_Barre, Teinte_Min)
y + 24
TextGadget(#PB_Any, 0, y, 48, 24, "Max : ", #PB_Text_Right)
StringGadget(#Teinte_Max, 48, y, 48, 24, Str(Teinte_Max), #PB_String_ReadOnly)
TrackBarGadget(#Teinte_Max_Barre, 96, y, 160, 24, 0, 3060)
SetGadgetState(#Teinte_Max_Barre, Teinte_Max)
y + 24

ForEach Image()
	Repeat
		If LoadImage(#Image, Image())
			ResizeImage(#Image, 400, Int(400 * ImageHeight(#Image) / ImageWidth(#Image)), #PB_Image_Smooth)
			CopyImage(#Image, #ImageOrigine)
			StartDrawing(ImageOutput(#Image))
				For x = 0 To OutputWidth() - 1
					For y = 0 To OutputHeight() - 1
						Couleur = Point(x, y)
						If TeintePeau(Couleur, Blanc_Min, Blanc_Max, Noir_Min, Noir_Max, Teinte_Min, Teinte_Max) = 0
							Plot(x, y, 0)
						EndIf
					Next
				Next
			StopDrawing()
			ImageGadget(#Image, 256, 0, 0, 0, ImageID(#Image))
			ImageGadget(#ImageOrigine, 256 + ImageWidth(#Image), 0, 0, 0, ImageID(#ImageOrigine))
			
			Suivant = 0
			Recalculer = 0
			Repeat
				Event = WaitWindowEvent(50)
				Select Event
					Case #PB_Event_CloseWindow
						End
					Case #PB_Event_Gadget
						Select EventGadget()
							Case #Blanc_Min_Barre
								Blanc_Min = GetGadgetState(#Blanc_Min_Barre)
								SetGadgetText(#Blanc_Min, Str(Blanc_Min))
								Recalculer = 1
							Case #Blanc_Max_Barre
								Blanc_Max = GetGadgetState(#Blanc_Max_Barre)
								SetGadgetText(#Blanc_Max, Str(Blanc_Max))
								Recalculer = 1
							Case #Noir_Min_Barre
								Noir_Min = GetGadgetState(#Noir_Min_Barre)
								SetGadgetText(#Noir_Min, Str(Noir_Min))
								Recalculer = 1
							Case #Noir_Max_Barre
								Noir_Max = GetGadgetState(#Noir_Max_Barre)
								SetGadgetText(#Noir_Max, Str(Noir_Max))
								Recalculer = 1
							Case #Teinte_Min_Barre
								Teinte_Min = GetGadgetState(#Teinte_Min_Barre)
								SetGadgetText(#Teinte_Min, Str(Teinte_Min))
								Recalculer = 1
							Case #Teinte_Max_Barre
								Teinte_Max = GetGadgetState(#Teinte_Max_Barre)
								SetGadgetText(#Teinte_Max, Str(Teinte_Max))
								Recalculer = 1
							Case #Image, #ImageOrigine
								Select EventType()
									Case #PB_EventType_LeftClick
										Suivant = 1
								EndSelect
						EndSelect
					Case 0
						If Recalculer
							Recalculer + 1
						EndIf
				EndSelect
				
			Until Suivant = 1 Or Recalculer > 5
			
			FreeGadget(#Image)
			FreeImage(#Image)
			FreeGadget(#ImageOrigine)
			FreeImage(#ImageOrigine)
		EndIf
	Until Suivant = 1
	
Next
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Recherche de teinte dans une image

Message par Le Soldat Inconnu »

Je viens de penser à un truc, cet algo qui reconnait les zones avec de la peau pourrait servir pour l'image retourner par une webcam, pour suivre la tête de celui qui est devant par exemple :)

Faudra que j'essaie
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Recherche de teinte dans une image

Message par G-Rom »

Ça marche plutôt bien :D
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Recherche de teinte dans une image

Message par Ar-S »

Le début d'une reconnaissance faciale. Excellent LSI.
cet algo qui reconnait les zones avec de la peau pourrait servir pour l'image retourner par une webcam, pour suivre la tête de celui qui est devant par exemple
What else :mrgreen:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Recherche de teinte dans une image

Message par G-Rom »

Faudrais accelerer le traitement avec un fragment shader. Car en soft. Ca rame pas mal. Ceci dit j'ai pas testé sur des petites resolution comme 320x240 ou 640 par 480. a voir combien d'image a la seconde tu peut traiter. Tu peu en dire plus sur ton algo?
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: Recherche de teinte dans une image

Message par Backup »

j'ai testé ton prg , sur .... une image paysage ... ça me ressort le feuillage ... :lol:

tu devrai peut etre ajouter une bande de couleur , avec 2 curseurs Debut-Fin
qui permettrai d'isoler une certaine nuance de couleur :)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Recherche de teinte dans une image

Message par Le Soldat Inconnu »

@Dobro : C'est la teinte. La sélection est pas précise précise, j'ai fait ça vite fait

@G-Rom : pour accélérer, je n'ai pas d'idée supplémentaire.

Le principe de l'algo :

je décompose chaque couleur en teinte, par cela j'entends que je détermine la couleur de l'arc en ciel à la base de la couleur (donc une couleur avec forcément parmis R G et B une valeur à 255, une valeur à 0, une valeur entre 0 et 255, RGB(154, 255, 0) OK, RGB(154, 255, 47) pas OK)
Ensuite je calcul le quantité de blanc et de noir à ajouté à cette teinte pour obtenir la couleur

Donc je filtre ensuite sur le blanc, le noir et la teinte.

pour avoir une idée visuelle, il faut prendre mon sélecteur de couleur sur mon site.
Je réexplique avec l'aperçu
Image

la couleur est au centre du cercle
la teinte, c'est la couleur en haut à droite
Le blanc, c'est le décalage de la droite vers la gauche
le noir, c'est le décalage du haut vers le bas

donc plus il y a du blanc, et plus la couleur se trouve à droite du nuancier
et plus il y a du noir et plus la couleur se trouve vers le bas du nuancier

Donc mon truc filtre sur une plage de teinte d'un arc en ciel, puis sur la saturation (que l'on peu associé à la composante blanche) / luminosité (qui correspond à la composante noire) de la couleur
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Recherche de teinte dans une image

Message par G-Rom »

pour accélérer, je n'ai pas d'idée supplémentaire.

sur chaque pixel de l'image tu fait au maximum 3060 itération , ce qui ralentit pas mal le programme :

Code : Tout sélectionner

 Color = RGB(Rouge, Vert, Bleu)
   For Teinte = 0 To 3060
      If ArcEnCiel_Couleur(Teinte) = Color
         Break
      EndIf
   Next
tu pourrais déjà l'accélérer en utilisant une map , de cette manière il n'y a plus d'itération sur chaque pixel , c'est plus gourmand en ram , mais 10x plus rapide au moins. ;)
pour encore plus de rapidité , tu pourrais aussi utilisé la lib 3d , faire une texture de 1x3060 pixel pour ton arc en ciel , une autre pour l'image à modifier , un matérial qui fait appel à un shader ( le shader est la fonction TeintePeau() , sans le savoir , tu nous a fait un fragment shader software , tu agis sur chaque pixel avant le rendu ) )
voila, commence déjà par l'utilisation de map ;)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: Recherche de teinte dans une image

Message par Le Soldat Inconnu »

Quand tu me parles de texture, shaders, tu me parle chinois :mrgreen:

je vais zieuter pour la rapidité de la map
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre