rony2006 Posted May 19, 2016 Share Posted May 19, 2016 Can somebody provide me a solution to compare 2 images and then to see how much is the difference between them in %? I found this: But I cannot make it to work. I put in folder a.jpg and b.jpg but the $compare[0] and $compare[1] is -1.#IND I use the following script: expandcollapse popup;~ #include <_PixelGetColor.au3> #include <GDIPlus.au3> #include <inet.au3> #include <array.au3> $hDll = DllOpen("gdi32.dll") _GDIPlus_Startup() Global $image1, $image2 $f1 = binary("/a.jpg") ;image 1 $f2 = binary("/b.jpg") ;image 2 brighter Msgbox(0, "", $f1) Msgbox(0, "", $f2) ;here we use the default step options $t1 = TimerInit() $image1 = _Capturepixels($f1) ;get image 1 pixel _arraydisplay($image1, "fdsfds") $t1 = TimerInit() $image2 = _CapturePixels($f2) ;get image 2 pixels _arraydisplay($image2, "fdsfds") $timer = TimerInit() $compare = _datacompare($image1[0], $image2[0]);compare them ConsoleWrite($compare[0]&'% Different(Localized) '&$compare[1]&'% Different(Global)'&@CRLF&'Took '&(TimerDiff($timer)/1000)&' seconds. Default Step'&@CRLF) Msgbox(0, "diferenta locala", $compare[0]) Msgbox(0, "diferenta globala", $compare[1]) Msgbox(0, "timp", (TimerDiff($timer)/1000)) ;here we double them, notice the preformance increase $t1 = TimerInit() $image1 = _Capturepixels($f1, 4, 8) ;get image 1 pixels ConsoleWrite(TimerDiff($t1)/1000 &' Double Step'&@CRLF) $t1 = TimerInit() $image2 = _CapturePixels($f2,4 , 8) ;get image 2 pixels ConsoleWrite(TimerDiff($t1)/1000& ' Double Step'&@CRLF) $timer = TimerInit() $compare = _datacompare($image1[0], $image2[0]) ConsoleWrite($compare[0]&'% Different(Localized) '&$compare[1]&'% Different(Global)'&@CRLF&'Took '&(TimerDiff($timer)/1000)&' seconds. Default Step'&@CRLF) sleep(5000) ;~ $t1 = TimerInit() ;~ $diffarray = _mapchange($image1[0], $image2[0], $image1[1], $image1[2]) ;compare two images for difference ;~ ConsoleWrite(TimerDiff($t1)/1000& ' _mapchange'&@CRLF) ;~ $t1 = TimerInit() ;~ $image = _toimage($diffarray) ;here we turn the array of colors back into an image ;~ ConsoleWrite(TimerDiff($t1)/1000& ' _toimage'&@CRLF) ;~ _GDIPlus_ImageSaveToFile($image, @scriptdir&'\test.jpg') ;write it to a file ;~ shellexecute(@scriptdir&'\test.jpg') #cs Function _datacompare($data1, $data2, [$declimal]) -$data1: A string of data, any length. -$data2: A string of data, must be the same length as $data1 -$decimal: 1=Binary 9=Base-10, 15=Base-16, 31=Base-32 Note: If you just want to compare two sets of binary data you probably want to use base-16. Unless you are sure your binary is in 1's and 0's. Returns: An array containing two floats. The first value is the localized change, and the second is the global change #ce func _datacompare($data1, $data2, $decimal=15) Local $difference $data1 = StringSplit($data1, "") $data2 = StringSplit($data2, "") $difference = 0 $found = 0 for $i=1 to $data1[0] if $data1[$i] <> $data2[$i] Then $temp = Abs(_tonum($data1[$i]) - _tonum($data2[$i])) $difference += $temp $found +=1 EndIf Next dim $ret[2] $ret[0] = ((($difference/$found))/$decimal)*100 $ret[1] = ((($difference/$data1[0]))/$decimal)*100 Return $ret EndFunc #cs Function: _mapchange($base, $new, $x, $y, [$decimal]) $base: Base data to compare from $new: Data to compare $x: Width of output data (should be returned by capturepixels) $y: Height of outout data (should be returned by capturepixels) $decimal: Decimal system, you shouldn't change this Note: Use _toimage on data returned by this function to visually see a image of the change. (The lighter the color the more change the occured) Returns an 2D array of data. Each value of the array represents one pixel of the image. Each value is a percent between 0-100 representing the change that occured in that pixel #ce func _mapchange($base, $new, $y, $x, $decimal = 10) Local $difference, $xx = 0, $yy = 0 dim $result[1][$x+1] $t1 = TimerInit() $data1 = _StringequalSplit($base, 8) $data2 = _StringequalSplit($new, 8) $difference = 0 for $i=1 to UBound($data1)-1 if $xx > $x Then $xx=0 $yy+=1 ConsoleWrite($yy&'/'&$y&' ('&($yy/$y)*100&') '&@CRLF) redim $result[$yy+1][$x+1] EndIf if $data1[$i] <> $data2[$i] Then $values1 = StringSplit($data1[$i], "") $values2 = stringSplit($data2[$i], "") $diff = "" for $ix=1 to $values1[0] $diff += round((Abs(_tonum($values1[$ix]) - _tonum($values2[$ix]))/$decimal)*100) Next $diff = Round($diff/$values1[0]) $result[$yy][$xx] = $diff Else $result[$yy][$xx] = 0 EndIf $xx += 1 Next return $result EndFunc #cs Function _tonum($info) -$info: A single digit or carachter. Returns: A 0-based value. #ce func _tonum($info) if $info+0 > 0 Then Return $info $info = StringLower($info) $return = asc($info)-87 switch $return Case -39 Return 0 Case Else Return $return EndSwitch EndFunc #cs Function _CapturePixels($data, [[$stepy], $stepx]) -$data: Binary Data -$stepy: How often to skip a row of pixelxs. 1 = Never -$stepx: How often to skip a single pixel. 1 = Nevere Note: Use higher steps for larger images and lower steps for smaller images. #ce Func _CapturePixels($data, $stepy = 2, $stepx = 2) $ret = "" $HBITMAP2 = _GDIPlus_BitmapCreateFromMemory($data) $y=_GDIPlus_ImageGetWidth($HBITMAP2) $x=_GDIPlus_ImageGetHeight($HBITMAP2) For $iY = 0 To $x step $stepy For $iX = 0 To $y step $stepx $rety = StringRight(hex(_GDIPlus_BitmapGetPixel($hBitmap2, $ix, $iy)),8) ;get current pixel color $ret &= $rety ;~ ConsoleWrite($iy&'/'&$x&' '&$rety&@CRLF) Next Next ;For $x = 0 To _GDIPlus_ImageGetWidth($HBITMAP2) ; For $y = 0 To _GDIPlus_ImageGetHeight($HBITMAP2) ; $ret &= _PixelGetColor_GetPixel($vDC, $x, $y, $hDll) ; Next ;Next _WinAPI_DeleteObject($HBITMAP2) dim $retx[3] $retx[0] = $ret $retx[1] = $x/$stepx $retx[2] = $y/$stepy Return $retx EndFunc ;==>Capturepixels Func _toimage($colors) _GDIPlus_Startup() Local $hBitmap = _GDIPlus_BitmapCreateFromScan0(UBound($colors, 2), UBound($colors, 1)) ;create an empty bitmap Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the graphics context of the bitmap _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hBmpCtxt, 0x00000000) ;clear bitmap with color white for $i=0 to UBound($colors)-1 for $i2=0 to UBound($colors,2 )-1 ;~ if $colors[$i][$i2] > 30 Then ;~ ConsoleWrite($i&","&$i2&' - '&$colors[$i][$i2]&@CRLF) _GDIPlus_BitmapSetPixel($hBitmap, $i2, $i, $colors[$i][$i2]&'0') ;~ ConsoleWrite($i2&','&$i&' '&$colors[$i][$i2]&@CRLF) ;~ EndIf Next Next return $hBitmap ;return bitmap ;cleanup GDI+ resources _GDIPlus_GraphicsDispose($hBmpCtxt) EndFunc ;==>Example Func _StringEqualSplit($sString, $iNumChars) If (Not IsString($sString)) Or $sString = "" Then Return SetError(1, 0, 0) If (Not IsInt($iNumChars)) Or $iNumChars < 1 Then Return SetError(2, 0, 0) Return StringRegExp($sString, "(?s).{1," & $iNumChars & "}", 3) EndFunc I also found another script but here I only see what is the difference between 2 image, I dont get the difference in %. expandcollapse popup#include <GDIPlus.au3> #include <GDIPlusConstants.au3> #include <StructureConstants.au3> #include <WinAPI.au3> ; quick and dirty.... Global $stride, $ptr, $pixeldata global $bitmapfile1, $width1, $height1, $stride1, $pbitmap1 global $bitmapfile2, $width2, $height2, $stride2, $pbitmap2 local $numberdiff = 0 ;number of differences between the 2 pics $pic1 = "1.bmp" ;the image....24bit per pixel, could be a JPG $pic2 = "3.bmp" $pic3 = "dif.bmp" ;a bitmapfile with the differences _GDIPlus_Startup() $pixelstruct1 = getbmpdata($pic1, $width1, $height1, $stride1, $pbitmap1) ;get all data from the 2 files $pixelstruct2 = getbmpdata($pic2, $width2, $height2, $stride2, $pbitmap2) $lenght = DllStructGetSize($pixelstruct1) ;get lenght of bitmapdata $pixelstruct3 = dllstructcreate("ubyte["&$lenght&"]") ;compare for $i=1 to $lenght ; consolewrite (dllstructgetdata($pixelstruct1,1,$i)&" "&dllstructgetdata($pixelstruct1,1,$i)&@crlf) $diff=dllstructgetdata($pixelstruct1,1,$i)-dllstructgetdata($pixelstruct2,1,$i) ;difference"colour" between the bytes if $diff<>0 Then ;bytes are different $numberdiff+=1 ;count dllstructsetdata($pixelstruct3,1,$diff,$i) ;write the difference into the difference-file, bottom-up isnt funny but we´ll mirror it later :o) endif next $head=DllStructcreate("ubyte[54]") ;lets create a bitmapfile with the given data $Bmpheader = DllStructCreate("align 1;char BM[2];uint Size;uint res;uint Offset;uint BMHI;uint Width;uint Height;short Planes;short BPP;uint BIcomp;int SizeImg;uint reshor;uint resver;uint col;uint colused", dllstructgetptr($head)) ;struct of bytes = header of bitmap #1 ;fill struct(bitmapheader) with data DllStructSetData($bmpheader,"BM","BM") DllStructSetData($bmpheader,"Size",54+$lenght) DllStructSetData($bmpheader,"Offset",54) DllStructSetData($bmpheader,"BMHI",40) DllStructSetData($bmpheader,"Width",$width1) DllStructSetData($bmpheader,"Height",-$height1) ;negativ because "bottom up" DllStructSetData($bmpheader,"Planes",1) DllStructSetData($bmpheader,"BPP",24) DllStructSetData($bmpheader,"BIcomp",0) DllStructSetData($bmpheader,"SizeImg",$lenght) $header = dllstructgetdata($head,1) ;headerdata ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $header = ' & $header & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console $pixeldata = stringtrimleft(DllStructGetData($pixelstruct3, 1),2) ;pixeldata $bitmap = $header&$pixeldata ;all together is the bitmap-file $filehandle = FileOpen($pic3, 18) ;write file FileWrite($filehandle,BinaryToString($bitmap)) FileClose($filehandle) _GDIPlus_ImageDispose($pBitmap1) ;not in the function, because ImageDispose destroys the struct _GDIPlus_ImageDispose($pBitmap2) ;lets have a look what we have done... GUICreate("Difference pixel",800,500) GUICtrlCreatePic($pic1, 10, 10, 170, 170 / $width1 * $height1) GUICtrlCreatePic($pic2, 200, 10, 170, 170 / $width2* $height2) GUICtrlCreatePic($pic3, 400, 10, 170, 170 / $width2* $height2) GUISetState() Do Until GUIGetMsg() = -3 Func getbmpdata($bmpfile, ByRef $width, ByRef $height, ByRef $stride, Byref $pbitmap) ;returns a struct with the data of the pixel $pbitmap = _GDIPlus_BitmapCreateFromFile($bmpfile) ;_GDIPlus_BitmapLockBits gibt $tagGDIPBITMAPDATA-Struktur zurück $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB) If @error Then MsgBox(0, "", "Error locking region " & @error) $stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up. $width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap. $height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap. ;$pixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap. $pixeldata = DllStructCreate("ubyte[" & (Abs($stride) * ($height)) & "]", $Scan0) $BMPData = DllStructGetData($pixeldata, 1) _WinAPI_DeleteObject($pbitmap) _GDIPlus_BitmapUnlockBits($pBitmap, $BmpData) ;_GDIPlus_ImageDispose($pBitmap) ;destroys the pixeldatastruct, have to be done at end of the script! return $pixeldata EndFunc ;==>getbmpdata Can somebody help me please? Link to comment Share on other sites More sharing options...
UEZ Posted May 19, 2016 Share Posted May 19, 2016 Have a look here: Pass "False" to the $bFastCmp parameter. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
rony2006 Posted May 19, 2016 Author Share Posted May 19, 2016 Can you be more specific please? I dont have $bFastCmp parameter in first script. Link to comment Share on other sites More sharing options...
UEZ Posted May 19, 2016 Share Posted May 19, 2016 If you follow the link to the other thread you will see there a function called _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp = True). If you call that function call it with $bFastCmp = False. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
rony2006 Posted May 19, 2016 Author Share Posted May 19, 2016 @UEZ Sorry but I dont understand. Do you mean that the code from will help me to compare 2 pictures and get the difference in % between them?? If not, i repeat that I dont use _GDIPlus_ImageCompare in my first script. Link to comment Share on other sites More sharing options...
UEZ Posted May 19, 2016 Share Posted May 19, 2016 1 minute ago, rony2006 said: Do you mean that the code from Yes. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
rudi Posted May 19, 2016 Share Posted May 19, 2016 Hi. Simply pass "False" as the 3rd parameter, when calling the function. Regards, Rudi. Earth is flat, pigs can fly, and Nuclear Power is SAFE! Link to comment Share on other sites More sharing options...
rony2006 Posted May 19, 2016 Author Share Posted May 19, 2016 Now I understand, but I tried the code comparing bb.jpg and cc.jpg from script directory and the message box is empty. I did something wrong? expandcollapse popup#include <GDIPlus.au3> Global $hImage1 = ("/bb.jpg") Global $hImage2 = ("/cc.jpg") MsgBox(0, "fdsfds", _GDIPlus_ImageCompare($hImage1, $hImage2)) Func _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp = False) Local Const $iW = _GDIPlus_ImageGetWidth($hImage1), $iH = _GDIPlus_ImageGetHeight($hImage1) If ($iW <> _GDIPlus_ImageGetWidth($hImage2)) Then Return SetError(1, 0, 0) If ($iH <> _GDIPlus_ImageGetHeight($hImage2)) Then Return SetError(2, 0, 0) Local $t = TimerInit() Local $tBitmapData1 = _GDIPlus_BitmapLockBits($hImage1, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local $tBitmapData2 = _GDIPlus_BitmapLockBits($hImage2, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB) Local $iScan1 = DllStructGetData($tBitmapData1, "Scan0") Local $tPixel1 = DllStructCreate("int[" & $iW * $iH & "];", $iScan1) Local $iStride = Abs(DllStructGetData($tBitmapData1, "Stride")) Local $iScan2 = DllStructGetData($tBitmapData2, "Scan0") Local $tPixel2 = DllStructCreate("int[" & $iW * $iH & "];", $iScan2) If $bFastCmp Then $iResult = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $iScan1, "ptr", $iScan2, "int", ($iH - 1) * $iStride + ($iW - 1) * 4)[0] Else Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $aDiff[$iW * $iH + 1][3], $c = 1 For $iY = 0 To $iH - 1 $iRowOffset = $iY * $iW + 1 For $iX = 0 To $iW - 1 $iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color $iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color If $iPixel1 <> $iPixel2 Then $aDiff[$c][0] = $iX & ", " & $iY $aDiff[$c][1] = "0x" & Hex($iPixel1, 8) $aDiff[$c][2] = "0x" & Hex($iPixel2, 8) $c += 1 EndIf Next Next $aDiff[0][0] = TimerDiff($t) $aDiff[0][1] = $iW $aDiff[0][2] = $iH EndIf _GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1) _GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2) If $bFastCmp Then Return SetError(0, Int(TimerDiff($t)), $iResult = 0) ReDim $aDiff[$c][3] Return $aDiff EndFunc Link to comment Share on other sites More sharing options...
UEZ Posted May 19, 2016 Share Posted May 19, 2016 (edited) Yes, $hImage1 and $hImage2 must be GDI+ image handles not a path. Use something like this here: _GDIPlus_Startup() Global $hImage1 = _GDIPlus_ImageLoadFromFile("/bb.jpg") Global $hImage2 = _GDIPlus_ImageLoadFromFile("/cc.jpg") Check out the correct path to the images! Edited May 19, 2016 by UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
rony2006 Posted May 19, 2016 Author Share Posted May 19, 2016 I tried and still empty. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now