Page 1 sur 2

Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 12:08
par celtic88
salut les pure :D
Voila un exemple d utiliser Gdiplus pour comparer deux images et extraire la différence en image, peut-être idéal pour la création d un logiciel pour camera de surveillance 8)

amusez vous bien ;)

première image
img0.jpg:
Image

deuxième image
img.jpg
Image

résultat
Image

code:

Code : Tout sélectionner

EnableExplicit

;////////////////////////////////////
;          Author Celtic88(c)
;///////////////////////////////////

Prototype GdiplusStartup(a,b,c)
Prototype GdipDisposeImage(a)
Prototype GdiplusShutdown(a)
Prototype GdipSaveImageToFile(a,b.s,c,d)
Prototype GdipCreateBitmapFromHicon(a, b)
Prototype GdipGetImageWidth(a,b)
Prototype GdipGetImageHeight(a,b)
Prototype GdipCreateBitmapFromFile(a.s,b)
Prototype GdipSetInterpolationMode(a,b)
Prototype GdipDrawImageRect(a,b,c.f,d.f,e.f,f.f)
Prototype GdipCreateFromHDC(a,b)
Prototype GdipCreateBitmapFromHBITMAP(a, b, c)
Prototype GdipDeleteGraphics(a)
Global  lib_gdiplus = OpenLibrary(#PB_Any, "GDIPlus.dll") 
; Prototype GdiTransparentBlt(a,b,c,d,e,f,g,h,k,l,m)
; Global  lib_gdi32 = OpenLibrary(#PB_Any, "gdi32.dll") 
; Global  GdiTransparentBlt_.GdiTransparentBlt=GetFunction(lib_gdi32,"GdiTransparentBlt")
Global  GdiplusStartup_.GdiplusStartup=GetFunction(lib_gdiplus,"GdiplusStartup")
Global  GdiplusShutdown_.GdiplusShutdown=GetFunction(lib_gdiplus,"GdiplusShutdown")
Global  GdipCreateBitmapFromHBITMAP_.GdipCreateBitmapFromHBITMAP=GetFunction(lib_gdiplus,"GdipCreateBitmapFromHBITMAP")
Global  GdipSaveImageToFile_.GdipSaveImageToFile=GetFunction(lib_gdiplus,"GdipSaveImageToFile")
Global  GdipDisposeImage_.GdipDisposeImage=GetFunction(lib_gdiplus,"GdipDisposeImage")
Global  GdipGetImageWidth_.GdipGetImageWidth=GetFunction(lib_gdiplus,"GdipGetImageWidth")
Global  GdipGetImageHeight_.GdipGetImageHeight=GetFunction(lib_gdiplus,"GdipGetImageHeight")
Global  GdipCreateBitmapFromFile_.GdipCreateBitmapFromFile=GetFunction(lib_gdiplus,"GdipCreateBitmapFromFile")
Global  GdipSetInterpolationMode_.GdipSetInterpolationMode=GetFunction(lib_gdiplus,"GdipSetInterpolationMode")
Global  GdipDrawImageRect_.GdipDrawImageRect=GetFunction(lib_gdiplus,"GdipDrawImageRect")
Global  GdipCreateFromHDC_.GdipCreateFromHDC=GetFunction(lib_gdiplus,"GdipCreateFromHDC")
Global  GdipDeleteGraphics_.GdipDeleteGraphics=GetFunction(lib_gdiplus,"GdipDeleteGraphics")


Structure GdiplusStartupInput 
  GdiPlusVersion.l 
  *EventCallback._EVENT
  SuppressBackgroundThread.l 
  SuppressExternalCodecs.l 
EndStructure 
Structure EncoderParameter
  Guid.GUID
  NumberOfValues.l
  Type.l
  *Value
EndStructure
Structure EncoderParameters
  Count.l
  Parameter.EncoderParameter[1]
EndStructure
Structure ImageCodecInfo
  clsid.CLSID
  formatID.GUID
  *codecName
  *dllName
  *formatDescription
  *filenameExtension
  *mimeType
  flags.l
  version.l
  sigCount.l
  sigSize.l
  *sigPattern
  *sigMask
EndStructure

Procedure.b _Gdiplus_Startup(*token)
  Protected GdiplusStartupInput.GdiplusStartupInput\GdiPlusVersion=1
  ProcedureReturn Bool(GdiplusStartup_(@*token, @GdiplusStartupInput,0)=0)
EndProcedure
Procedure _Gdiplus_GetImageWidth(hImage)
  Protected xw:GdipGetImageWidth_(hImage,@xw):ProcedureReturn xw
EndProcedure
Procedure _Gdiplus_GetImageHeight(hImage)
  Protected xy:GdipGetImageHeight_(hImage,@xy):ProcedureReturn xy
EndProcedure
Procedure CompareImage_CreateDIBSection(iWidth, iHeight)
  Protected tBITMAPINFO.BITMAPINFOHEADER
  tBITMAPINFO\biSize=SizeOf(BITMAPINFOHEADER)
  tBITMAPINFO\biWidth=iWidth
  tBITMAPINFO\biHeight=iHeight
  tBITMAPINFO\biPlanes=1
  tBITMAPINFO\biBitCount=32
  ProcedureReturn CreateDIBSection_(0,@tBITMAPINFO,0,0,0,0)
EndProcedure

Procedure _Gdiplus_CompareImages(hbitmap1,hbitmap2)
  
  Protected iw=_Gdiplus_GetImageWidth(hbitmap1)
  Protected ih=_Gdiplus_GetImageHeight(hbitmap1)
  
  Protected hHBitmap1= CompareImage_CreateDIBSection(iw, ih)
  Protected hd1=GetWindowDC_(0)
  Protected hDC_backbuffer1 = CreateCompatibleDC_(hd1)
  Protected DC_obj1 = SelectObject_(hDC_backbuffer1, hHBitmap1)
  Protected hGraphic1,hGraphic2,hBitmap3
  GdipCreateFromHDC_(hDC_backbuffer1,@hGraphic1)
  GdipSetInterpolationMode_(hGraphic1,5)
  GdipDrawImageRect_(hGraphic1,hbitmap1,0,0,iw, ih)

  Protected hHBitmap2= CompareImage_CreateDIBSection(iw, ih)
  Protected hd2=GetWindowDC_(0)
  Protected hDC_backbuffer2 = CreateCompatibleDC_(hd2)
  Protected DC_obj2 = SelectObject_(hDC_backbuffer2, hHBitmap2)
  GdipCreateFromHDC_(hDC_backbuffer2,@hGraphic2)
  GdipSetInterpolationMode_(hGraphic2,5)
  GdipDrawImageRect_(hGraphic2,hbitmap2,0,0,iw, ih)
  
  Protected hHBitmap3= CompareImage_CreateDIBSection(iw, ih)
  Protected hd3=GetWindowDC_(0)
  Protected hDC_backbuffer3 = CreateCompatibleDC_(hd3)
  Protected DC_obj3 = SelectObject_(hDC_backbuffer3, hHBitmap3)
  
  BitBlt_(hDC_backbuffer3, 0, 0, iw, ih, hDC_backbuffer1, 0, 0, #SRCCOPY)
  BitBlt_(hDC_backbuffer3, 0, 0, iw, ih, hDC_backbuffer2, 0, 0, #MERGEPAINT)

  GdipDisposeImage_(hBitmap1)
  GdipDisposeImage_(hBitmap2)
  GdipCreateBitmapFromHBITMAP_(hHBitmap3,0,@hBitmap3)
  DeleteObject_(hHBitmap3)
  
  GdipDeleteGraphics_(hGraphic1)
  SelectObject_(hD1, DC_obj1)
  DeleteDC_(hDC_backbuffer1)
  DeleteObject_(hHBitmap1)
  ReleaseDC_(0, hD1)
  
  GdipDeleteGraphics_(hGraphic2)
  SelectObject_(hD2, DC_obj2)
  DeleteDC_(hDC_backbuffer2)
  DeleteObject_(hHBitmap2)
  ReleaseDC_(0, hD2)
  
  SelectObject_(hD3, DC_obj3)
  DeleteDC_(hDC_backbuffer3)
  ReleaseDC_(0, hD3)
  ProcedureReturn hBitmap3
EndProcedure


Define token
_Gdiplus_Startup(@token)

Define hbitmap1,hbitmap2,hBitmap3
GdipCreateBitmapFromFile_("img0.jpg",@hbitmap1)
GdipCreateBitmapFromFile_("img.jpg",@hbitmap2)
hBitmap3 =_Gdiplus_CompareImages(hbitmap1,hbitmap2)

GdipSaveImageToFile_(hBitmap3,"def.png",?Png_Clsid,0)
GdipDisposeImage_(hBitmap3)

GdiplusShutdown_(token)

DataSection
  Png_Clsid: ; clsid for png image format
  Data.l $557CF406
  Data.w $1A04
  Data.w $11D3
  Data.b $9A,$73,$00,$00,$F8,$1E,$F3,$2E
EndDataSection

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 12:10
par falsam
Et ben ... il s'éclate le Celtic ^^ Merci pour ce partage.

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 12:17
par celtic88
falsam a écrit :Et ben ... il s'éclate le Celtic ^^ Merci pour ce partage.
:D falsam loll ;;programmer en pb un bon idée Pour lutter contre l'ennui :p

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 12:20
par falsam
celtic88 a écrit :programmer en pb un bon idée Pour lutter contre l'ennui :p
Tu as raison et je préfére coder des trucs qui ne servent à rien plutôt que de tricoter :mrgreen:

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 12:40
par Ar-S
Merci celtic88, sympa ça !

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 18:04
par nico
Génial :D

Je l'ai testé et fonctionne très bien.

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 17/déc./2015 18:10
par nico
Par contre si on veux rapidement par programmation localiser les différences en les entourant d'un rectangle par exemple, comment on peux s'y prendre?

Re: Gdi plus : comparer deux images rapidement..

Publié : ven. 18/déc./2015 10:46
par celtic88
nico a écrit :Par contre si on veux rapidement par programmation localiser les différences en les entourant d'un rectangle par exemple, comment on peux s'y prendre?
pour ça a mon idée:
en premier il faut que te Verrouille les deux images pour lire les pixels avec cette gdip fonction :
http://purebasic.developpez.com/tutorie ... kBits.html

ensuit tu compare les deux images pixel par pixel dans tout les lignes et enfin tu fais ton calcule pour dessiner un rectangle à l'endroit précis

mais le problème ici c'est que la comparaison sera trop long :(!!

Re: Gdi plus : comparer deux images rapidement..

Publié : ven. 18/déc./2015 11:31
par Ar-S
Peut-être peut-on lors de la comparaison noter le 1er pixel haut gauche détecté puis le dernier bas droit ce qui donnerait les références du cadre. ça éviterait des calcules après coup.

Re: Gdi plus : comparer deux images rapidement..

Publié : ven. 18/déc./2015 16:01
par celtic88
en bas

Re: Gdi plus : comparer deux images rapidement..

Publié : sam. 19/déc./2015 10:19
par venom
Merci celtic88,

un code qui pourra servir un jour. 8)






@++

Re: Gdi plus : comparer deux images rapidement..

Publié : lun. 21/déc./2015 20:52
par celtic88
et voila un exemple pour dessinée un réctangle sur la région différente
Image

Code : Tout sélectionner

EnableExplicit

;////////////////////////////////////
;          Author Celtic88(c)
;///////////////////////////////////

Prototype GdiplusStartup(a,b,c)
Prototype GdipDisposeImage(a)
Prototype GdiplusShutdown(a)
Prototype GdipGetImageWidth(a,b)
Prototype GdipGetImageHeight(a,b)
Prototype GdipCreateBitmapFromFile(a.s,b)
Prototype GdipBitmapLockBits(a,b,c,d,e)
Prototype GdipBitmapUnlockBits(a,b)
Prototype GdipGetImageGraphicsContext(a,b)
Prototype GdipDeleteGraphics(a)
Prototype GdipSaveImageToFile(a,b.s,c,d)
Prototype GdipCreatePen1(a,b.f,c,d)
Prototype GdipDrawRectangle(a,b,c.f,d.f,e.f,f.f)
Prototype GdipSetPenDashStyle(a,b)
Prototype GdipDeletePen(a)

Global  lib_gdiplus = OpenLibrary(#PB_Any, "GDIPlus.dll") 

Global  GdiplusStartup_.GdiplusStartup=GetFunction(lib_gdiplus,"GdiplusStartup")
Global  GdiplusShutdown_.GdiplusShutdown=GetFunction(lib_gdiplus,"GdiplusShutdown")
Global  GdipDisposeImage_.GdipDisposeImage=GetFunction(lib_gdiplus,"GdipDisposeImage")
Global  GdipGetImageWidth_.GdipGetImageWidth=GetFunction(lib_gdiplus,"GdipGetImageWidth")
Global  GdipGetImageHeight_.GdipGetImageHeight=GetFunction(lib_gdiplus,"GdipGetImageHeight")
Global  GdipCreateBitmapFromFile_.GdipCreateBitmapFromFile=GetFunction(lib_gdiplus,"GdipCreateBitmapFromFile")
Global  GdipBitmapLockBits_.GdipBitmapLockBits=GetFunction(lib_gdiplus,"GdipBitmapLockBits")
Global  GdipBitmapUnlockBits_.GdipBitmapUnlockBits=GetFunction(lib_gdiplus,"GdipBitmapUnlockBits")
Global  GdipGetImageGraphicsContext_.GdipGetImageGraphicsContext=GetFunction(lib_gdiplus,"GdipGetImageGraphicsContext")
Global  GdipDeleteGraphics_.GdipDeleteGraphics=GetFunction(lib_gdiplus,"GdipDeleteGraphics")
Global  GdipSaveImageToFile_.GdipSaveImageToFile=GetFunction(lib_gdiplus,"GdipSaveImageToFile")
Global  GdipDrawRectangle_.GdipDrawRectangle=GetFunction(lib_gdiplus,"GdipDrawRectangle")
Global  GdipCreatePen1_.GdipCreatePen1=GetFunction(lib_gdiplus,"GdipCreatePen1")
Global  GdipSetPenDashStyle_.GdipSetPenDashStyle=GetFunction(lib_gdiplus,"GdipSetPenDashStyle")
Global  GdipDeletePen_.GdipDeletePen=GetFunction(lib_gdiplus,"GdipDeletePen")


Structure GdiplusStartupInput 
  GdiPlusVersion.l 
  *EventCallback._EVENT
  SuppressBackgroundThread.l 
  SuppressExternalCodecs.l 
EndStructure 

Structure GDIPBITMAPDATA 
  Width.l
  Height.l
  Stride.l
  Format.l
  *Scan0
  Reserved.i
EndStructure

#GDP_Ok=0
#GDIP_ILMREAD = $0001
#GDIP_ILMWRITE = $0002
#GDIP_PXF32RGB = $00022009 ; 32 bpp; 8 bits for each RGB. No alpha.

Procedure.b Gdiplus_Startup(*token)
  Protected GdiplusStartupInput.GdiplusStartupInput\GdiPlusVersion=1
  ProcedureReturn Bool(GdiplusStartup_(@*token, @GdiplusStartupInput,0)=0)
EndProcedure
Procedure Gdiplus_GetImageWidth(hImage)
  Protected xw:GdipGetImageWidth_(hImage,@xw):ProcedureReturn xw
EndProcedure
Procedure Gdiplus_GetImageHeight(hImage)
  Protected xy:GdipGetImageHeight_(hImage,@xy):ProcedureReturn xy
EndProcedure
Procedure Gdiplus_CreateBitmapFromFile(Ipath.s)
  Protected hbitmap:GdipCreateBitmapFromFile_(Ipath,@hbitmap):ProcedureReturn hbitmap
EndProcedure
Procedure Gdiplus_BitmapLockBits(hBitmap, iLeft, iTop, iWidth, iHeight, iFlags , iFormat,*GDIPBITMAPDATA.GDIPBITMAPDATA)
  Protected irec.rect
  irec\left=iLeft
  irec\top=iTop
  irec\right=iWidth
  irec\bottom=iHeight
  ProcedureReturn Bool(GdipBitmapLockBits_(hBitmap,@irec,iFlags , iFormat,*GDIPBITMAPDATA) = #GDP_Ok)
EndProcedure

Define token
Gdiplus_Startup(@token)

Define hbitmap1=Gdiplus_CreateBitmapFromFile("img0.jpg")
Define hbitmap2=Gdiplus_CreateBitmapFromFile("img.jpg")

Define iw=Gdiplus_GetImageWidth(hbitmap1)
Define ih=Gdiplus_GetImageHeight(hbitmap1)

Define  iX, iY,iRowOffset
NewList dpoint.Point()
Define GDIPBITMAPDATA1.GDIPBITMAPDATA,GDIPBITMAPDATA2.GDIPBITMAPDATA

Define timer=ElapsedMilliseconds()

Gdiplus_BitmapLockBits(hbitmap1, 0, 0, iw, ih, #GDIP_ILMREAD, #GDIP_PXF32RGB,@GDIPBITMAPDATA1)
Gdiplus_BitmapLockBits(hbitmap2, 0, 0, iw, ih, #GDIP_ILMREAD, #GDIP_PXF32RGB,@GDIPBITMAPDATA2)
For iY = 0 To ih-1
  iRowOffset=iY*iw*4
  For iX = 0 To iw-1
    If  PeekL(GDIPBITMAPDATA1\Scan0+iRowOffset+iX*4) <> PeekL(GDIPBITMAPDATA2\Scan0+iRowOffset+iX*4)
      AddElement(dpoint())
      dpoint()\x=iX
      dpoint()\y=iY
    EndIf
  Next
Next

MessageRequester(Str(ElapsedMilliseconds()-timer) +" ms",Str((ListSize(dpoint())*100)/(iw* ih)) +" % différences.")

Define a,b,c,d
SortStructuredList(dpoint(),#PB_Sort_Ascending,OffsetOf(Point\x),#PB_Integer)
FirstElement(dpoint())
a=dpoint()\x
LastElement(dpoint())
b=dpoint()\x
SortStructuredList(dpoint(),#PB_Sort_Ascending,OffsetOf(Point\y),#PB_Integer)
FirstElement(dpoint())
c=dpoint()\y
LastElement(dpoint())
d=dpoint()\y

GdipBitmapUnlockBits_(hBitmap1,@GDIPBITMAPDATA1)
GdipBitmapUnlockBits_(hBitmap2,@GDIPBITMAPDATA2)
Define hbgcx,hPen
GdipGetImageGraphicsContext_(hBitmap2,@hbgcx)
GdipCreatePen1_($FFFFFF00,4,2,@hPen)
GdipSetPenDashStyle_(hPen,2)
GdipDrawRectangle_(hbgcx,hPen,a,c,b-a,d-c)
GdipSaveImageToFile_(hBitmap2,"hhhhh.png",?Png_Clsid,0)
GdipDeletePen_(hPen)
GdipDeleteGraphics_(hbgcx)
GdipDisposeImage_(hBitmap1)
GdipDisposeImage_(hBitmap2)

GdiplusShutdown_(token)

DataSection
  Png_Clsid: ; clsid for png image format
  Data.l $557CF406
  Data.w $1A04
  Data.w $11D3
  Data.b $9A,$73,$00,$00,$F8,$1E,$F3,$2E
EndDataSection

Re: Gdi plus : comparer deux images rapidement..

Publié : jeu. 24/déc./2015 11:58
par Kwai chang caine
CELTIC, t'es vraiment un cador de la prog 8O

T'as bien fait de passer ici quand tu as vu de la lumière
En fin de compte j'suis content que tu parles mal l'anglais, ça nous fait une tronche de plus sur le forum FR, t'es vraiment un atout pour ce forum 8)
Celtic88 a écrit :programmer en pb un bon idée Pour lutter contre l'ennui :p
Tu va pas me dire que tu apprends tout seul 8O
J’espère que t'as fait des écoles d'informatique pour avoir ce niveau ? sinon je me jette par la fenêtre :mrgreen:

Bon, ... pour parler de ton bijou, évidemment ça marche pas sur mon XP PRO et la v5.40 surement trop vieux :oops:
J'ai donc pas pu tester, mais il y a quelques temps, j'avais eu besoin de ce genre de code, et WILBERT avait eu la gentillesse de me faire une procedure basé sur un algorithme de mathématicien fou, qui était aussi très efficace.

C'est super interessant ce genre de code, il y a pleins d'applications possibles, comparaison, reconnaissance, OCR et j'en passe

Un grand bravo, et un grand merci de ton partage et de ta sympathie 8)

Re: Gdi plus : comparer deux images rapidement..

Publié : lun. 28/déc./2015 0:43
par celtic88
@Kwai chang caine

merci beaucoup pour votre commentaire très encourageant :)
J’espère que t'as fait des écoles d'informatique pour avoir ce niveau ? sinon je me jette par la fenêtre
alors J'espère pour toi que tu habite dans le sous-sol! :p
ça marche pas sur mon XP PRO
Bizarre? mais ça doit marcher dans tout version Windows qui possède "gdiplus.dll" version 1.0!!

Re: Gdi plus : comparer deux images rapidement..

Publié : lun. 28/déc./2015 9:47
par Patrick88
Kwai.., peux tu mettre un lien vers le fofo anglishe pour la routine de WILBERT... cela évite de chercher, ou la poster à la suite de celle de Celtic...

pat