bonjour a tous !
Comment faire une comparaison de deux images jpg sous delphi7 ?
j'aimerai pouvoir avoir un resultat en pourcentage de similarité.
si vous avez des solutions, des objets a me proposer, ou autres,
merci.
Krisk
bonjour a tous !
Comment faire une comparaison de deux images jpg sous delphi7 ?
j'aimerai pouvoir avoir un resultat en pourcentage de similarité.
si vous avez des solutions, des objets a me proposer, ou autres,
merci.
Krisk
Bonjour et bienvenue sur les forums de Developpez.com.
Tu pourrais par exemple faire une comparaison pixels par pixels ensuite pour le pourcentage de similarité, tu peux le définir en fonction du nombrede pixels comparé et le nombre de pixels différents.
Je ne pense pas que ce soit la bonne solution, surtout si tes images ne font pas la même taille mais c'est une idée de départ
J'avais justement réfléchi au même problème, et j'étais arrivé à une solution satisfaisante au niveau qualité, mais lourde d'un point de vue performance.
J'espère que tu es familier avec les termes d'imagerie, sinon ça va être dur à comprendre :
- Convertir chaque image en niveau de gris.
- Egaliser l'histogramme.
- Redimensionner les deux images à une taille commune, qui peut être quelconque (ex : 300x300). L'important est qu'elle soit plus petite, par exemple d'un facteur 2 sur chaque dimension. Utiliser une interpolation pour la réduction : ça permet de supprimer le tramage.
- Soustraire les deux images.
- Calculer la moyenne de couleur des pixels de la différence (utiliser un histogramme, c'est plus simple même si c'est un peu plus lent).
- Si cette valeur est inférieure à un certain seuil (ex : <16), tu peux considérer les images comme identiques.
Ca marche pour toutes les images, y compris pour comparer une JPEG avec une GIF... Mais le coût en temps de calcul est assez monstrueux.
Salut,
Il n'existe pas de définition précise du degré de similarité de deux images, et il faudrait donc que tu précises dans quel contexte tu te situes pour connaitre les paramètres importants, pour ton application, dans tes images.
Une méthode générale qui marche assez bien et qui est adaptable au contexte consiste à :
- prendre des descripteurs d'images (spectre de couleurs, corrélations de couleurs, gradients, Canny, ...)
- Passer chacun de ces descripteur à travers un réseau de neurones que tu entraines (ou toute fonction similaire qui te permette d'"évaluer" un descripteur).
- Affecter des poids aux résultats obtenus en fonction de leur importance dans ton contexte (couleurs, textures, formes, ...). Cela peut se faire de façon empirique, ou en entrainant un nouveau réseau.
Il suffit finalement de mesurer le degré de corrélation entre les résultats obtenus pour chaque image.
merci de vos reponses
j'ai enfin trouver une solution.
avec l'objet TImageEnView des objets ImageEn
methode:
TImageEnView.Proc.CompareWith()
si vous connaissez mieux ?
merci a+
-----------------------------
Krisk
Pense alors à cliquer sur en bas à gauche, stp.
j'ai essayer l'objet precedement cité mais il est tres lent et shareware.
j'ai beaucoup d'image a comparer et j'ai entendu parler, pour aller plus vite, qu'il falait cree avant une signature suivant des criteres particulier.
savez vous des choses la dessus ?
merci
------------------------------------------------------
krisk
Pour la lenteur, ça ne m'étonnes absolument pas... Cf. mon premier post.Envoyé par krisk33
Oui, mais ça, c'est très bien pour des comparaisons "binaires" (un simple CRC32 fait des merveilles !).Envoyé par krisk33
Mais pour des images, la signature est plutôt volumineuse... J'utilisais comme "signature" une version réduite de l'image (telle que je te l'ai décrite auparavant), mais ça faisait quand même un gros truc (10.000 octets par image environ), et la comparaison "stricte" est impossible.
La signature dont j'ai entendu parler et plutot su style de ce que parle sovitec dans son message
"descripteurs d'images (spectre de couleurs, corrélations de couleurs, gradients, Canny, ...)"
mais où trouver ces routines mathematiques pour avoir ces informations ?
------------------------------------------------------
krisk
Voilà comment je compare des images (de même taille) pour faire un détecteur de mouvement de webcam
Fonction et procédure utilisées
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 procedure TForm1.ComparerBmp(BmpAvant, BmpApres, BmpResult: TBitmap); var Bmp: TBitmap; begin Bmp := TBitmap.Create; with Bmp do begin Width := BmpAvant.Width; Height := BmpAvant.Height; Canvas.CopyMode := CmSrcInvert; Canvas.CopyRect(ClientRect, BmpAvant.Canvas, ClientRect); Canvas.CopyMode := CmSrcAnd; Canvas.CopyRect(ClientRect, BmpApres.Canvas, ClientRect); end; BmpResult.Assign(Bmp); Bmp.Free; end;BmpCapture et BmpCapturePrecedente sont les images à comparer
Code : 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 function TForm1.BmpLuminosite(Bmp: TBitmap; Niveau: byte): Extended; Const MaxPixelCount = 65536; // 65536 type TRGBTripleArray = Array[0..MaxPixelCount - 1] Of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; var x, y: integer; Ligne: pRGBTripleArray; R, G, B, RGB: byte; begin Result := 0; Bmp.PixelFormat := pf24bit; for y:=0 to Bmp.Height-1 do begin Ligne := Bmp.ScanLine[y]; For x:=0 to Bmp.Width-1 do begin R := Ligne[x].rgbtRed; G := Ligne[x].rgbtGreen; B := Ligne[x].rgbtBlue; RGB := (R+G+B) div 3; // Ligne[x].rgbtRed := RGB; // Niveau de gris // Ligne[x].rgbtGreen := RGB; // Ligne[x].rgbtBlue := RGB; if RGB>Niveau then begin Ligne[x].rgbtRed := 255; // Blanc Ligne[x].rgbtGreen := 255; Ligne[x].rgbtBlue := 255; Result := Result+1; end else begin Ligne[x].rgbtRed := 0; // Noir Ligne[x].rgbtGreen := 0; Ligne[x].rgbtBlue := 0; end; end; end; Result := 100*Result/(Bmp.Height*Bmp.Width); end;
BmpComparaison : image dont les differences apparaissent en blanc
Régler le niveau acceptable de différence (niveau de la fonction BmpLuminosite)
C'est assez fluide et tu peux eviter de retourcher : à toi d'adapter ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 // Image.Picture.Bitmap.Assign(BmpCapture); ComparerBmp(BmpCapture,BmpCapturePrecedente,BmpComparaison); // Image.Picture.Bitmap.Assign(BmpComparaison); ShapeMouvement.Visible := BmpLuminosite(BmpComparaison,64)>0.1; // Image.Picture.Bitmap.Assign(BmpComparaison);
Par exemple mais on peut rien visualiser...
Il faut regler tout ca par la suite
Code : 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 function TForm1.BmpLuminosite(Bmp: TBitmap; Niveau: byte): Extended; Const MaxPixelCount = 65536; // 65536 type TRGBTripleArray = Array[0..MaxPixelCount - 1] Of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; var x, y: integer; Ligne: pRGBTripleArray; R, G, B: byte; begin Result := 0; Bmp.PixelFormat := pf24bit; for y:=0 to Bmp.Height-1 do begin Ligne := Bmp.ScanLine[y]; For x:=0 to Bmp.Width-1 do begin R := Ligne[x].rgbtRed; G := Ligne[x].rgbtGreen; B := Ligne[x].rgbtBlue; if ((R+G+B) div 3>Niveau) then Result := Result+1; end; end; Result := 100*Result/(Bmp.Height*Bmp.Width); end;
Mieux
Code : 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 function DectectionMouvement(BmpAvant, BmpApres, BmpResult: TBitmap; TraitementBmpResult: Boolean ; Niveau: byte): Extended; Const MaxPixelCount = 65536; // 65536 type TRGBTripleArray = Array[0..MaxPixelCount-1] Of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; var Blanc: integer; x, y: integer; LigneAvant, LigneApres, LigneResult: pRGBTripleArray; RGBAvant, RGBApres, RGBResult: byte; begin Blanc := 0; BmpAvant.PixelFormat := pf24bit; BmpApres.PixelFormat := pf24bit; BmpResult.PixelFormat := pf24bit; BmpResult.Width := BmpAvant.Width; BmpResult.Height := BmpAvant.Height; for y:=0 to BmpResult.Height-1 do begin LigneAvant := BmpAvant.ScanLine[y]; LigneApres := BmpApres.ScanLine[y]; LigneResult := BmpResult.ScanLine[y]; For x:=0 to BmpResult.Width-1 do begin RGBAvant := (LigneAvant[x].rgbtRed+LigneAvant[x].rgbtGreen+LigneAvant[x].rgbtBlue) div 3; RGBApres := (LigneApres[x].rgbtRed+LigneApres[x].rgbtGreen+LigneApres[x].rgbtBlue) div 3; RGBResult := Abs(RGBApres-RGBAvant); if RGBResult>Niveau then inc(Blanc,1); if TraitementBmpResult then if RGBResult>Niveau then begin LigneResult[x].rgbtRed := 255; LigneResult[x].rgbtGreen := 255; LigneResult[x].rgbtBlue := 255; end else begin LigneResult[x].rgbtRed := 0; LigneResult[x].rgbtGreen := 0; LigneResult[x].rgbtBlue := 0; end; end; end; Result := 100*Blanc/(BmpResult.Height*BmpResult.Width); end;
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager