taietel Posted July 31, 2011 Share Posted July 31, 2011 I'm working on a personal project that involves box counting algorithm and one module, that involves image processing, loads the CPU. I have tried to put a delay between searches, but this decreases the speed in filling the boxes (see the ;Sleep(5)<<<<<<<<<<<<<<<<< in the script), although it decreases the CPU load drastically.Should I stay with this solution or rewrite the whole module (GDI is something (still) new to me) ?expandcollapse popup#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #AutoIt3Wrapper_Run_Tidy=y #Tidy_Parameters=/tc 0 /sfc #include <WindowsConstants.au3> #include <ScreenCapture.au3> #include <GDIP.au3>;Thanks Authenticity! ;================================================================================== ; Application...: Box Counting ; Module........: Image processing ; Last Rev......: August 01, 2011 ; Author........: M. Iancu (taietel at yahoo dot com) ;================================================================================== HotKeySet("{ESC}", "_Exit") Global $sBuffer = "" InetGet("http://sirop-artar.info/images/frunza-artar.jpg", @ScriptDir & "\frunza.jpg") Global $sImTest = @ScriptDir & "\frunza.jpg";test image Global $sImgOutDir = @ScriptDir & "\Images";here we store the snapshots at the end of each step _Box_CountModule($sImTest) Func _Box_CountModule($sIm) If Not FileExists($sImgOutDir) Then DirCreate($sImgOutDir) Local $bFinish = 0 Local $iTimerStart = TimerInit();for testing ;create image container Local $hGUI = GUICreate("BoxCounting", 500, 500, -1, -1, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_TOPMOST) GUISetState() ;for testing __Test("RetVal" & @TAB & "Step" & @TAB & "ImgWidth" & @TAB & "ImgHeight" & @TAB & "Grid(Boxes)" & @TAB & "BoxWidth" & @TAB & "FilledBoxes" & @TAB & "FilledArea") For $i = 0 To 15 $bFinish = _Box_LoadImage($hGUI, $sIm, $i) ;for testing __Test($bFinish[0] & @TAB & $bFinish[1] & @TAB & $bFinish[2] & @TAB & @TAB & $bFinish[3] & @TAB & @TAB & $bFinish[4] & @TAB & @TAB & $bFinish[5] & @TAB & @TAB & $bFinish[6] & @TAB & @TAB & $bFinish[7]) ;if the limit of 1px is reached, exit loop If $bFinish[0] Then ExitLoop Sleep(400);some pause between steps, to see the transitions Next Local $iTimerEnd = TimerDiff($iTimerStart) __Test("Finished in " & Round($iTimerEnd / 1000, 2) & " sec.");for testing Local $sFile = @ScriptDir & "\test.txt";for testing Local $hFile = FileOpen($sFile, 18) FileWrite($hFile, $sBuffer) FileClose($hFile) ShellExecute($sFile) Exit While 1 Sleep(10) Switch GUIGetMsg() Case -3 Exit EndSwitch WEnd EndFunc ;==>_Box_CountModule Func _Box_LoadImage($hWnd, $sImage, $iB = 0) Local $aResults[8] $aResults[1] = $iB + 1;No. of iterations Local $iFilledBoxes = 0 Local $bFilled = False Local $iDimension, $iHeight, $iWidth, $hImage, $hBitmap, $hBrush, $hGraphic, $lColour ;Start GDI+ _GDIPlus_Startup() ;Load image $hImage = _GDIPlus_ImageLoadFromFile($sImage) ; If the image is not squared, it will be by filling the width/height ; (depends which is longer) with the colour of first pixel $iWidth = _GDIPlus_ImageGetWidth($hImage) $iHeight = _GDIPlus_ImageGetHeight($hImage) $aResults[2] = $iWidth $aResults[3] = $iHeight Local $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iWidth, $iHeight, $GDIP_PXF01INDEXED);1px indexed $lColour = _GDIPlus_BitmapGetPixel($hClone, 0, 0) _GDIPlus_ImageDispose($hImage) If $iWidth > $iHeight Then $iDimension = $iWidth Else $iDimension = $iHeight EndIf Local $iBoxes = 2 ^ $iB Local $iBoxWidth = Ceiling($iDimension / $iBoxes) $aResults[4] = $iBoxes ^ 2 $aResults[5] = $iBoxWidth ;reinitialize dimension $iDimension = $iBoxWidth * $iBoxes ;and create a new squared image with dimension x dimension, 1px indexed $hBitmap = _GDIPlus_BitmapCreateFromScan0($iDimension + 1, $iDimension + 1, 0, $GDIP_PXF01INDEXED) $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap) _GDIPlus_GraphicsClear($hGraphic, $lColour) _GDIPlus_GraphicsDrawImageRect($hGraphic, $hClone, 0, 0, $iWidth, $iHeight) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ImageDispose($hClone) ;check if 1px limit is reached; in this case, return True If $iBoxWidth <= 1 Then $aResults[0] = True Else $aResults[0] = False EndIf ;redim the GUI with at width/height of the image WinMove($hWnd, "", (@DesktopWidth - $iWidth) / 2, (@DesktopHeight - $iHeight) / 2, $iWidth, $iHeight) $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) _GDIPlus_GraphicsClear($hGraphic, $lColour) _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2) ;draw the newly created image onto this graphic _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap, 0, 0) ;set the quality of the captured images _ScreenCapture_SetJPGQuality(80) ; capture the first one for later use If $iB = 0 Then _ScreenCapture_CaptureWnd($sImgOutDir & "\img0.jpg", $hWnd, 0, 0, -1, -1, False) ;create a brush for filling the boxes $hBrush = _GDIPlus_BrushCreateSolid() _GDIPlus_BrushSetSolidColor($hBrush, 0x99FF0000) ;start searching for pixels different from the first For $i = 0 To $iDimension - $iBoxWidth Step $iBoxWidth For $j = 0 To $iDimension - $iBoxWidth Step $iBoxWidth If $i > $iHeight Or $j > $iWidth Then ExitLoop ; if width/height is reached, exit loop (now the image is squared and don't know which width/height was shorter/longer) For $m = 0 To $iBoxWidth For $n = 0 To $iBoxWidth ; if scanned colour is different from the background, exit loop If $lColour <> _GDIPlus_BitmapGetPixel($hBitmap, $j + $n, $i + $m) Then $bFilled = True ExitLoop EndIf Next If $bFilled Then ExitLoop Next If $bFilled Then _GDIPlus_GraphicsFillRect($hGraphic, $j, $i, $iBoxWidth, $iBoxWidth, $hBrush) $iFilledBoxes += 1 $bFilled = False EndIf ;Sleep(5); <<<<<<<<<<<<<<<<<<<<<<<<<<<< to reduce CPU usage. Any other way??? :/ Next Next ; capture the filled images for later use _ScreenCapture_CaptureWnd($sImgOutDir & "\img" & $iB + 1 & ".jpg", $hWnd, 0, 0, -1, -1, False) $aResults[6] = $iFilledBoxes $aResults[7] = $iFilledBoxes * ($iBoxWidth ^ 2);filled surface (px^2) ;clean the rest of the resources _GDIPlus_BrushDispose($hBrush) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_Shutdown() Return $aResults EndFunc ;==>_Box_LoadImage Func _Exit() Exit EndFunc ;==>_Exit #region Internal use Func __Test($sT) ConsoleWrite($sT & @CRLF) $sBuffer &= $sT & @CRLF EndFunc ;==>__Test #endregion Internal useThanks in advance for answering to this. Things you should know first...In the beginning there was only ONE! And zero... Progs: Create PDF(TXT2PDF,IMG2PDF) 3D Bar Graph DeskGadget Menu INI Photo Mosaic 3D Text Link to comment Share on other sites More sharing options...
Spiff59 Posted August 1, 2011 Share Posted August 1, 2011 (edited) One small refinement: You might pull the GDI Startup and Shutdown statements from the BoxLoadImage() function and place them instead on both sides of the for/next loop in BoxCountModule(). I'm assuming 15 less calls to GDIStartup will make your CPU vs. speed issue slightly easier to balance. Maybe there is more initialization/termination code that could be moved and executed only once instead of 16 times? Edited August 1, 2011 by Spiff59 Link to comment Share on other sites More sharing options...
taietel Posted August 1, 2011 Author Share Posted August 1, 2011 Spiff59, thank you for the suggestion. The maximum number of calls, as tested so far, was 11 and the cycle stops when 1px limit is reached. I put 15 in case the image is very large. Things you should know first...In the beginning there was only ONE! And zero... Progs: Create PDF(TXT2PDF,IMG2PDF) 3D Bar Graph DeskGadget Menu INI Photo Mosaic 3D Text Link to comment Share on other sites More sharing options...
UEZ Posted August 1, 2011 Share Posted August 1, 2011 (edited) You are calling too much GDI+ functions in the loop which can be move outside the loops.This is just an example not creating Minkowski–Bouligand dimension (box counting algorithm):expandcollapse popup#include <ScreenCapture.au3> If Not FileExists(@ScriptDir & "\frunza.jpg") Then InetGet("http://sirop-artar.info/images/frunza-artar.jpg", @ScriptDir & "\frunza.jpg") If @error Then Exit EndIf _GDIPlus_Startup() $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\frunza.jpg") $iW = _GDIPlus_ImageGetWidth($hBitmap) $iH = _GDIPlus_ImageGetHeight($hBitmap) $hBMP_2bpp = _GDIPlus_BitmapCloneArea($hBitmap, 0 ,0 , $iW, $iH, $GDIP_PXF01INDEXED) $hBrush = _GDIPlus_BrushCreateSolid(0xA0FF0000) $hGUI = GUICreate("Test", $iW, $iH) GUISetState() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) HotKeySet("{ESC}", "_Exit") Global $i = 3, $j = 0 Do _GDIPlus_GraphicsDrawImage($hGraphic, $hBMP_2bpp, 0, 0) Get_BoxCountingDimension(Floor($i), $hGraphic, $iW, $iH, $hBMP_2bpp) _ScreenCapture_CaptureWnd(@ScriptDir & "\Image" & StringFormat("%02i", $j) & ".jpg", $hGUI, 0, 0, -1, -1, False) $j += 1 Sleep(2000) $i *= 1.5 Until $i > 300 MsgBox(0, "Test", "Done", 10) While 1 Switch GUIGetMsg() Case -3 _Exit() EndSwitch WEnd Func Get_BoxCountingDimension($depth, $hContext, $iW, $iH, $hBitmap) Local $x, $y, $draw, $w = Ceiling($iW / $depth), $h = Ceiling($iH / $depth) For $y = 0 To $iH Step $h For $x = 0 To $iW Step $w $draw = CheckPixels($hBMP_2bpp, $x, $y, $w, $h) If $draw Then _GDIPlus_GraphicsFillRect($hGraphic, $x, $y, $w, $h, $hBrush) Next Next Return EndFunc Func CheckPixels($hBitmap, $x, $y, $w, $h, $color = "0xFF000000") Local $px, $py, $c For $py = $y To $y + $h For $px = $x To $x + $w $c = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "hwnd", $hBitmap, "int", $px, "int", $py, "uint*", 0) If $c[4] = $color Then Return True Next Next Return False EndFunc Func _Exit() _GDIPlus_BrushDispose($hBrush) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_BitmapDispose($hBMP_2bpp) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ShutDown() GUIDelete($hGUI) Exit EndFuncBtw, interesting stuff you are doing here.Br,UEZ Edited August 1, 2011 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...
taietel Posted August 1, 2011 Author Share Posted August 1, 2011 (edited) UEZ, I knew you will come up sooner or later. Your script is more than I have expected. Thank you! The main application is based on Minkowski–Bouligand, but I want to extend it to determine area of irregular shapes (like some graphs, maps etc) also, based on a given scale factor. It can be used for a lot of other interesting things. The resulting report will be in pdf format, including the images taken from every step of the process, graphs etc. Thanks again! taietel Edited August 1, 2011 by taietel Things you should know first...In the beginning there was only ONE! And zero... Progs: Create PDF(TXT2PDF,IMG2PDF) 3D Bar Graph DeskGadget Menu INI Photo Mosaic 3D Text Link to comment Share on other sites More sharing options...
UEZ Posted August 1, 2011 Share Posted August 1, 2011 I made some changes that you can follow now how the rect. will get smaller and it will save the image, too. Br, 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...
taietel Posted August 1, 2011 Author Share Posted August 1, 2011 I made some modifications to fit my needs: the box has to be squared, capture just the caret etc. Simple, but briliant, the idea of working on the black&white picture and showing the real picture to the user. expandcollapse popup#include <ScreenCapture.au3> #include <WindowsConstants.au3> Opt("CaretCoordMode",0) If Not FileExists(@ScriptDir & "\frunza.jpg") Then InetGet("http://sirop-artar.info/images/frunza-artar.jpg", @ScriptDir & "\frunza.jpg") If @error Then Exit EndIf _GDIPlus_Startup() $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\frunza.jpg") $iW = _GDIPlus_ImageGetWidth($hBitmap) $iH = _GDIPlus_ImageGetHeight($hBitmap) If $iW>=$iH Then $iD=$iW Else $iD=$iH EndIf $hBMP_2bpp = _GDIPlus_BitmapCloneArea($hBitmap, 0 ,0 , $iW, $iH, $GDIP_PXF01INDEXED) $hBrush = _GDIPlus_BrushCreateSolid(0xA000FF00) $hGUI = GUICreate("Test", $iW, $iH) GUISetState() $iC = WinGetCaretPos() $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsSetSmoothingMode($hGraphic,2) HotKeySet("{ESC}", "_Exit") Global $i = 0, $j = 0, $iBoxes, $iBoxWdth, $iFilled _ScreenCapture_SetJPGQuality(90) __Test("Step" & @TAB & @TAB & "Box Width" & @TAB & "Boxes" & @TAB & @TAB & "Filled");test Do _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0,$iW, $iH) $iBoxes=2^$i $iBoxWdth=$iD/$iBoxes;square box $iFilled=0 If $j=0 Then Sleep(300) _ScreenCapture_CaptureWnd(@ScriptDir & "\Image00.jpg", $hGUI, $iC[0], $iC[1], $iW, $iH, False) $iFilled=1 Else Get_BoxCountingDimension($iBoxes, $hGraphic, $iW, $iH, $hBMP_2bpp) _ScreenCapture_CaptureWnd(@ScriptDir & "\Image" & StringFormat("%02i", $j) & ".jpg", $hGUI, $iC[0], $iC[1], $iW, $iH, False) EndIf __Test($j & @TAB & @TAB & StringFormat("%.2f",$iBoxWdth) & @TAB & @TAB & $iBoxes^2 & @TAB & @TAB & $iFilled);test $j += 1 $i += 1 Sleep(500) Until $iBoxWdth < 1 While 1 Sleep(10) Switch GUIGetMsg() Case -3 _Exit() EndSwitch WEnd Func Get_BoxCountingDimension($depth, $hContext, $iW, $iH, $hBitmap) Local $x, $y, $draw, $w = Ceiling($iD / $depth), $h = Ceiling($iD / $depth) For $y = 0 To $iH Step $h For $x = 0 To $iW Step $w $draw = CheckPixels($hBMP_2bpp, $x, $y, $w, $h) If $draw Then $iFilled += 1 _GDIPlus_GraphicsFillRect($hGraphic, $x, $y, $w, $h, $hBrush) EndIf Next Next Return EndFunc Func CheckPixels($hBitmap, $x, $y, $w, $h, $color = "0xFF000000") Local $px, $py, $c For $py = $y To $y + $h For $px = $x To $x + $w $c = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "hwnd", $hBitmap, "int", $px, "int", $py, "uint*", 0) If $c[4] = $color Then Return True Next Next Return False EndFunc Func _Exit() _GDIPlus_BrushDispose($hBrush) _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_BitmapDispose($hBMP_2bpp) _GDIPlus_GraphicsDispose($hGraphic) _GDIPlus_ShutDown() GUIDelete($hGUI) Exit EndFunc Func __Test($sT) ConsoleWrite($sT & @CRLF) EndFunc ;==>__Test Thanks (again and again and again ...) UEZ! taietel Things you should know first...In the beginning there was only ONE! And zero... Progs: Create PDF(TXT2PDF,IMG2PDF) 3D Bar Graph DeskGadget Menu INI Photo Mosaic 3D Text 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