Jump to content

ImageMagickObject - compare - how to get pics difference in %?


 Share

Recommended Posts

Hi All.

I'm trying to get pics difference in %. I tried to use ImageMagickObject.dll as it is fast enough & free under it's license.

#include <WindowsConstants.au3>

$DllExist = 1

Global $oIM = ObjCreate ("ImageMagickObject.MagickImage.1")

If @error OR NOT IsObj ($oIM) Then
    If NOT FileExists ("ImageMagickObject.dll") Then
        MsgBox (16, "!", "No ImageMagickObject.dll - work impossible.")
        Exit
    EndIf
    RunWait (@ComSpec & " /c regsvr32 /s ImageMagickObject.dll", @ScriptDir , @SW_HIDE)
    $DllExist = 0
    $oIM = ObjCreate ("ImageMagickObject.MagickImage.1")
    If @error OR NOT IsObj ($oIM) Then
        MsgBox (16, "!", "Error using ImageMagickObject.dll - work impossible.")
        Exit
    EndIf
EndIf

$Main = GUICreate ("GUI", 455, 290, 0, 0, $WS_DLGFRAME)
$Quit = GUICtrlCreateButton ("Quit", 345, 167.5, 100)

$Sec_old = -1

GUISetState (@SW_SHOW)

While 1
    $msg = GUIGetMsg()

    If $msg = $Quit Then
        If $DllExist = 1 Then
            RunWait (@ComSpec & " /c regsvr32 /u /s ImageMagickObject.dll", @ScriptDir , @SW_HIDE)
        EndIf
        Exit
    EndIf

    If $Sec_old <> @SEC Then
        $Sec_old = @SEC
        $oIM.Compare ("-metric", "MAE", "old.bmp", "new.bmp", "null:")
    EndIf
WEnd

As you see comparison is made every second, but I can not find the way to get the percentage of difference. $oIM.Compare returns empty string.

When I push "Quit", I see in SciTE's log these strings:

+>00:19:55 AU3Check ended.rc:0
>Running:(3.3.8.0) :D:Program FilesAutoIt3autoit3.exe "D:11.au3"
10.8064 (0.0423779)
10.8064 (0.0423779)
10.8064 (0.0423779)
+>00:19:58 AutoIT3.exe ended.rc:0
+>00:19:59 AutoIt3Wrapper Finished
>Exit code: 0 Time: 4.167

In center there are string with numbers - 1 string per 1 second of execution - which are somehow returned by ImageMagickObject & looks like what I need.

These strings appear in log only when script execution is over - not earlier.

I tried several cases with StderrRead, StdoutRead, ConsoleRead, DllCall, ObjEvent to get these strings while script execution. Tried them while running from SciTE & with compiled script.

No result. May be I cook them in a wrong way.

In attachment you can find code, dll, bmps I use.

Grates to everyone who can offer solution, useful piece of code or helpful link.

1.zip

Link to comment
Share on other sites

Did that work for you Werty?

I always make the mistake of taking on bigger projects than I can handle which leads others to think I'm some kind of coding god.  :P

Edited by jaberwocky6669
Link to comment
Share on other sites

Can you try this (GDI+ version only):

AutoIt version 3.3.10.0 or higher needed!

 

#include <Array.au3>
#include <GDIPlus.au3>
#include <MsgBoxConstants.au3>

_GDIPlus_Startup()
Global $hImage1, $hImage2
Global $sImages = FileOpenDialog("Select 2 images", "", "Image (*.bmp;*.jpg;*.png;*.gif)", $FD_MULTISELECT)
If @error Then _Exit("Nothing selected")
Global $aFiles = StringSplit($sImages, "|", 2)
If (UBound($aFiles) < 3) Then _Exit("Select at least 2 images")
$hImage1 = _GDIPlus_ImageLoadFromFile($aFiles[1])
If @error Then _Exit("Unable to load " & $aFiles[1])
$hImage2 = _GDIPlus_ImageLoadFromFile($aFiles[2])
If @error Then _Exit("Unable to load " & $aFiles[2])
If (_GDIPlus_ImageGetWidth($hImage1) <> _GDIPlus_ImageGetWidth($hImage2)) Then _Exit("Width of both images are different")
If (_GDIPlus_ImageGetHeight($hImage1) <> _GDIPlus_ImageGetHeight($hImage2)) Then _Exit("Height of both images are different")

Global $bFastCmp = True
Global $aDiff = _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp)

If $bFastCmp Then Exit MsgBox($MB_SYSTEMMODAL, "Compared", "Equal: " & $aDiff & " / " & @extended & " ms")

Global $iChk = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_YESNO), "Information", "Found " & Round((UBound($aDiff) - 1) / ($aDiff[0][1] * $aDiff[0][2]) * 100, 2) & " % differences in " & Round($aDiff[0][0], 2) & " ms." & _
                        @CRLF & @CRLF & _
                        "Display the array with information")
If ($iChk = 6) Then _ArrayDisplay($aDiff, "Differences", Default, Default, Default, "Runtime / Coordinate (x,y)|Image1 Color|Image2 Color")

Func _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp = True)
    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 $pScan1 = DllStructGetData($tBitmapData1, "Scan0")
    Local $tPixel1 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan1)
    Local $iStride = Abs(DllStructGetData($tBitmapData1, "Stride"))

    Local $pScan2 = DllStructGetData($tBitmapData2, "Scan0")
    Local $tPixel2 = DllStructCreate("uint[" & $iW * $iH & "];", $pScan2)


    If $bFastCmp Then
        $iResult = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $pScan1, "ptr", $pScan2, "uint", DllStructGetSize($tPixel1))[0]
    Else
        If ($iW * $iH + 1) * 3 > 16 * 1024^2 Then Return SetError(3, 0, 0)
        Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $c = 1, $aDiff[$iW * $iH + 1][3]
        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


Func _Exit($sError = "")
    If $sError <> "" Then MsgBox($MB_ICONERROR, "ERROR", $sError)
    If ($hImage1 <> 0) Then _GDIPlus_ImageDispose($hImage1)
    If ($hImage2 <> 0) Then _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_Shutdown()
    Exit
EndFunc

Br,

UEZ

Edited 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

Try reading post #31 in JabberWockys imagemagickobject thread, maybe it's something.

Link:

Tried this one before & now once again. Many of possible parameters for "-format" work, but "%[distortion]" returns empty string.

By the way (quote from link)

 

Using -: instead of info: appears to only output to the variable, not to the scite console

Seems not to work with "compare" - I get "The requested action with this object has failed." error.

Link to comment
Share on other sites

UEZ:I tried GDI decision - very slow & too straight in comparison. My actual pictures are taken from webcam & are 640x480 pixels - it takes about 10 seconds to compare them, and due to picture quality even with real absence of changes images are reported to be different for about 90%.

I also tried to use PixelGetColor, but result is approximately the same.

Link to comment
Share on other sites

The code detects real differences that means 0xFFFFFFFF is not equal to 0xFFFFFFFE whereas your eye will not detect the difference. It cannot skip "similar" looking pixels.

Comparing 2 640x480 images on my notebook take approx. 1,4 seconds. For one time compare it is ok but too slow for repeated compares, e.g. images from web cams.

Speed for such cases is a bottleneck for AutoIt...

 

Br,

UEZ

Edited 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

 

"compare" sends output to stderr, not stdout.

"%[distortion]" is for "compare". This goes to stdout.

That's what I've got from ImageMagick forum.

I already tried it but got nothing - may be did something wrong, cause never used these functions before. Can someone more familiar with them check them?

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...