Dexter1993 Posted November 27, 2021 Share Posted November 27, 2021 Hey guys, is there a simple way to count the number of coloured pixels (for example green) in an area ? e.g. Pos 1: 500x 500y to Pos 2: 600x to 600y PixelCount ??? THX Link to comment Share on other sites More sharing options...
Musashi Posted November 27, 2021 Share Posted November 27, 2021 (edited) 9 hours ago, Dexter1993 said: PixelCount ??? Not a beauty, but may be sufficient . EDIT : new version expandcollapse popup#include <Timers.au3> #include <MsgBoxConstants.au3> HotKeySet("{ESC}", "_Terminate") HotKeySet("+!1", "_PixelCount1") ; Shift-Alt-1 ==> start search using PixelGetColor HotKeySet("+!2", "_PixelCount2") ; Shift-Alt-2 ==> start search using PixelSearch Global $iLeft, $iTop, $iRight, $iBottom ; coordinates of a rectangle Global $sColor, $iVariation, $iChecked, $iFound ; set values : $iLeft = 0 $iTop = 0 $iRight = 200 $iBottom = 200 $sColor = "FFFF00" ; color you are looking for $iVariation = 0 $iChecked = 0 ; Pixels checked $iFound = 0 ; Pixels found While True Sleep(100) WEnd ; 1. using PixelGetColor : Func _PixelCount1() Local $iMsgID Local $hStarttime = _Timer_Init() ConsoleWrite("Process running ..." & @CRLF) $iChecked = 0 $iFound = 0 For $x = $iLeft To $iRight For $y = $iTop To $iBottom If (Hex(PixelGetColor($x, $y), 6)) = $sColor Then $iChecked += 1 $iFound += 1 Else $iChecked += 1 EndIf Next Next ConsoleWrite("Process finished" & @CRLF) $iMsgID = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION, $MB_RETRYCANCEL), _ "PixelGetColor Result :", _ "Pixels checked : " & @CRLF & $iChecked & @CRLF & _ "Pixels found : " & @CRLF & $iFound & @CRLF & @CRLF & _ "Time : " & @CRLF & _Timer_Diff($hStarttime) & " ms" & @CRLF) If $iMsgID = $IDCANCEL Then Exit EndFunc ; 2. using PixelSearch : Func _PixelCount2() Local $iMsgID, $xColor Local $hStarttime = _Timer_Init() ConsoleWrite("Process running ..." & @CRLF) $iChecked = 0 $iFound = 0 For $x = $iLeft To $iRight For $y = $iTop To $iBottom PixelSearch($x, $y, $x, $y, Dec($sColor), $iVariation) If @error Then $iChecked += 1 Else $iFound += 1 $iChecked += 1 EndIf Next Next ConsoleWrite("Process finished" & @CRLF) $iMsgID = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION, $MB_RETRYCANCEL), _ "PixelSearch Result :", _ "Pixels checked : " & @CRLF & $iChecked & @CRLF & _ "Pixels found : " & @CRLF & $iFound & @CRLF & @CRLF & _ "Time : " & @CRLF & _Timer_Diff($hStarttime) & " ms" & @CRLF) If $iMsgID = $IDCANCEL Then Exit EndFunc Func _Terminate() MsgBox(BitOR(4096, 64), "Message :", "Script terminated" & @CRLF) Exit EndFunc Edited November 27, 2021 by Musashi new version "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
Nine Posted November 27, 2021 Share Posted November 27, 2021 You can use my Screen Scraping UDF (see signature). Would be lot faster especially on Win10. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Dexter1993 Posted November 27, 2021 Author Share Posted November 27, 2021 @Nine thx man. Very nice UDF! but can you show me a simple example for this sitation: Thx ! Link to comment Share on other sites More sharing options...
Solution Nine Posted November 27, 2021 Solution Share Posted November 27, 2021 8 minutes ago, Dexter1993 said: Very nice UDF! Thank you. The simplest way would be to use @Musashi 1st example but instead of calling PixelGetColor, you would use _GetScreen_GetPixel. For an even faster way, you can also use _GetScreen_SearchArea repeatedly with the start information set at each loop until you get an error. Put a script together and if you have issues, I will be glad to help you out. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Dexter1993 Posted November 27, 2021 Author Share Posted November 27, 2021 (edited) hm... i dont know bro i test it the last 2 hours. My desktop is full of tests expandcollapse popup#include <MsgBoxConstants.au3> #include <Constants.au3> #include "GetScreen.au3" #include <Array.au3> HotKeySet("{ESC}", "_PixelCount1") Global $iLeft, $iTop, $iRight, $iBottom ; coordinates of a rectangle Global $sColor, $iVariation, $iChecked, $iFound ; set values : $iLeft = 0 $iTop = 0 $iRight = 600 $iBottom = 600 $sColor = 0xD05E5E ; color you are looking for $iVariation = 0 $iChecked = 0 ; Pixels checked $iFound = 0 ; Pixels found _PixelCount1() Func _PixelCount1() $iChecked = 0 $iFound = 0 For $x = $iLeft To $iRight For $y = $iTop To $iBottom If (Hex(_GetScreen_GetPixel($x, $y), 6)) = $sColor Then $iChecked += 1 $iFound += 1 Else $iChecked += 1 EndIf Next Next MsgBox (1,"","Pixels checked :" & $iChecked & " Pixel found: " & $iFound) EndFunc I test it with a red point. Edited November 27, 2021 by Dexter1993 Link to comment Share on other sites More sharing options...
Werty Posted November 27, 2021 Share Posted November 27, 2021 The $iChecked counter in the loop is not needed, it will always be ($iRight-$iLeft)*($iBottom-$iTop). Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Nine Posted November 27, 2021 Share Posted November 27, 2021 Look at examples in the UDF. You need to initialize the buffer and then read the screen. You are not doing it properly. Take a moment to understand what you are doing... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Musashi Posted November 27, 2021 Share Posted November 27, 2021 (edited) 1 hour ago, Dexter1993 said: hm... i dont know bro i test it the last 2 hours. My desktop is full of tests Try : expandcollapse popup#include <Timers.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include "GetScreen.au3" #include <Array.au3> Opt("MustDeclareVars", True) HotKeySet("{ESC}", "_Terminate") HotKeySet("+!1", "_PixelCount1") ; Shift-Alt-1 ==> start search with _GetScreen_GetPixel Global $iLeft, $iTop, $iRight, $iBottom ; coordinates of a rectangle Global $sColor, $iFound ; set values : $iLeft = 0 $iTop = 0 $iRight = 600 $iBottom = 600 $sColor = "D05E5E" ; color you are looking for $iFound = 0 ; Pixels found While True Sleep(100) WEnd Func _PixelCount1() Local $iMsgID Local $hStarttime = _Timer_Init() $iFound = 0 _GetScreen_Initialize(($iRight - $iLeft), ($iBottom - $iTop)) _GetScreen_GetScreen() For $x = $iLeft To $iRight For $y = $iTop To $iBottom If (Hex(_GetScreen_GetPixel($x, $y), 6)) = $sColor Then $iFound += 1 EndIf Next Next $iMsgID = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION, $MB_RETRYCANCEL), _ "PixelSearch Result :", _ "Pixels checked : " & @CRLF & ($iRight-$iLeft)*($iBottom-$iTop) & @CRLF & _ "Pixels found : " & @CRLF & $iFound & @CRLF & @CRLF & _ "Time : " & @CRLF & _Timer_Diff($hStarttime) & " ms" & @CRLF) If $iMsgID = $IDCANCEL Then Exit EndFunc Func _Terminate() MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION), "Message :", "Script terminated" & @CRLF) Exit EndFunc EDIT : As already explained by @Nine : "You need to initialize the buffer and then read the screen." Edited November 27, 2021 by Musashi "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
Musashi Posted November 27, 2021 Share Posted November 27, 2021 @Nine : Besides, a nice UDF "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
Nine Posted November 27, 2021 Share Posted November 27, 2021 The UDF always starts at 0,0 from the top left, you can reduce the read to a lower right bottom but it will save only micro secs. Better read the whole screen. Then you can search for specific area. Musashi 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Nine Posted November 27, 2021 Share Posted November 27, 2021 7 minutes ago, Musashi said: Besides, a nice UDF Thanks. I am using it a lot, and I know it is working very well. Sometimes, you need pixel driven script to ease the complexity of a tool. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Dexter1993 Posted November 28, 2021 Author Share Posted November 28, 2021 THX guys! Very Helpfull. I have now adapted it the way I need it thx @Nine !!!! thx @Musashi #include "GetScreen.au3" MsgBox (1,"Founded pixel",_PixelCountInArea(0,0,500,500,"D05E5E")) Func _PixelCountInArea($left,$top,$right,$bottom,$color) $founded = 0 _GetScreen_Initialize(($right - $left), ($bottom - $top)) _GetScreen_GetScreen() For $x = $left To $right For $y = $top To $bottom If (Hex(_GetScreen_GetPixel($x, $y), 6)) = $color Then $founded += 1 EndIf Next Next Return $founded EndFunc Link to comment Share on other sites More sharing options...
Nine Posted November 28, 2021 Share Posted November 28, 2021 Initialize should say right and bottom, as I said the UDF always starts at 0,0 So code should be : #include "GetScreen.au3" MsgBox (1,"Founded pixel",_PixelCountInArea(0,0,500,500,"D05E5E")) Func _PixelCountInArea($left,$top,$right,$bottom,$color) $founded = 0 _GetScreen_Initialize($right, $bottom) _GetScreen_GetScreen() For $x = $left To $right For $y = $top To $bottom If _GetScreen_GetPixel($x, $y) = $color Then $founded += 1 Next Next Return $founded EndFunc “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Dexter1993 Posted November 28, 2021 Author Share Posted November 28, 2021 I have one more question: i Creat a while and check my red point. I am shown 566 pixels. If I now move a window in front of the point, there are considerably more pixels. How can that be? #include "GetScreen.au3" While 1 ToolTip (_PixelCountInArea(1131, 460,1406, 750,"D05E5E"),600,500) Sleep (100) WEnd Func _PixelCountInArea($left,$top,$right,$bottom,$color) $founded = 0 _GetScreen_Initialize($right, $bottom) _GetScreen_GetScreen() For $x = $left To $right For $y = $top To $bottom If _GetScreen_GetPixel($x, $y) = $color Then $founded += 1 EndIf Next Next Return $founded EndFunc Link to comment Share on other sites More sharing options...
Werty Posted November 28, 2021 Share Posted November 28, 2021 (edited) Here's a fast (and small) C DLL version (attached, or compile with TCC) Takes a file, change it to screencap yourself if needed. #include <GDIPlus.au3> Global Static $CountColorDll = DllOpen("CountColor.dll") Global $hImage, $iLeft = 0, $iTop = 0, $iRight = 1100, $iBottom = 600, $hPixels, $Count = 0, $Color = 0xFFd05e5e _GDIPlus_Startup() $hImage = _GDIPlus_BitmapCreateFromFile("image.png") $Count = _CountColor($hImage, $Color) _GDIPlus_Shutdown() ConsoleWrite("Amount of " & Hex($Color, 8) & " = " & $Count & @crlf) Func _CountColor(ByRef $hImage, $Color) $Pixels = _GDIPlus_BitmapLockBits($hImage, $iLeft, $iTop, $iRight, $iBottom, $GDIP_ILMREAD, $GDIP_PXF32ARGB) $aRet = DllCall($CountColorDLL, "int:cdecl", "CountColor", "ptr", $Pixels.Scan0, "int", ($iRight-$iLeft)*($iBottom-$iTop), "int", $Color) _GDIPlus_BitmapUnlockBits($hImage, $Pixels) _GDIPlus_BitmapDispose($hImage) Return $aRet[0] EndFunc #cs =================================================================================================== C code for the DLL, compile with 'Tiny C Compiler' (TCC) https://bellard.org/tcc/ tcc -shared CountColor.c =================================================================================================== #include <stdlib.h> __declspec(dllexport) int CountColor(int* pixel, int len, int color) { int i, count = 0; for(i=0;i<len;i++){if(pixel[i]==color){count+=1;}} return count;} =================================================================================================== #ce Btw, there are WAY more than 566 pixels that have color d05e5e, I count 28661 of them (and the edge of the circle is antialiased so they dont count) CountColor.dll Edited November 28, 2021 by Werty Musashi 1 Some guy's script + some other guy's script = my script! Link to comment Share on other sites More sharing options...
Musashi Posted November 28, 2021 Share Posted November 28, 2021 1 hour ago, Werty said: Btw, there are WAY more than 566 pixels that have color d05e5e, I count 28661 of them True ! For width and height I have given the complete screen (for trial purposes). I still use _GetScreen_GetPixel. Screenshot without overlaying the area (the red dot) opened with Irfanview ==> 22291 Pixels found Screenshot with overlaying the area (the red dot) opened with Irfanview ==> 6706 Pixels found expandcollapse popup#include <Timers.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include "GetScreen.au3" #include <Array.au3> Opt("MustDeclareVars", True) HotKeySet("{ESC}", "_Terminate") HotKeySet("+!1", "_PixelCount1") ; Shift-Alt-1 ==> start search with _GetScreen_GetPixel Global $iWidth, $iHeight, $sColor, $iFound ; set values : $iWidth = @DesktopWidth ; Width of the primary display in pixels $iHeight = @DesktopHeight ; Height of the primary display in pixels $sColor = "D05E5E" ; color you are looking for $iFound = 0 ; Pixels found While True Sleep(100) WEnd Func _PixelCount1() Local $iMsgID Local $hStarttime = _Timer_Init() $iFound = 0 _GetScreen_Initialize($iWidth, $iHeight) _GetScreen_GetScreen() For $x = 0 To $iWidth For $y = 0 To $iHeight If (Hex(_GetScreen_GetPixel($x, $y), 6)) = $sColor Then $iFound += 1 EndIf Next Next $iMsgID = MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION, $MB_RETRYCANCEL), _ "PixelSearch Result :", _ "Pixels checked : " & @CRLF & ($iWidth * $iHeight) & @CRLF & _ "Pixels found : " & @CRLF & $iFound & @CRLF & @CRLF & _ "Time : " & @CRLF & _Timer_Diff($hStarttime) & " ms" & @CRLF) If $iMsgID = $IDCANCEL Then Exit EndFunc Func _Terminate() MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONINFORMATION), "Message :", "Script terminated" & @CRLF) Exit EndFunc "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
junkew Posted November 28, 2021 Share Posted November 28, 2021 https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_BitmapGetHistogramEx.htm FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
Dexter1993 Posted November 28, 2021 Author Share Posted November 28, 2021 (edited) The red dot is only a test. I dont want to scan image files. So it's not possible to scan an area in a repeat loop and count the pixels? And if the number of employees changes, the new number of employees should be output live. @Nine Can't you do a magic trick? #include "GetScreen.au3" While 1 ToolTip (_PixelCountInArea(1131, 460,1406, 750,"D05E5E"),600,500) Sleep (100) WEnd Func _PixelCountInArea($left,$top,$right,$bottom,$color) $founded = 0 _GetScreen_Initialize($right, $bottom) _GetScreen_GetScreen() For $x = $left To $right For $y = $top To $bottom If _GetScreen_GetPixel($x, $y) = $color Then $founded += 1 EndIf Next Next Return $founded EndFunc Edited November 28, 2021 by Dexter1993 Link to comment Share on other sites More sharing options...
Nine Posted November 28, 2021 Share Posted November 28, 2021 (edited) 20 minutes ago, Dexter1993 said: So it's not possible to scan an area in a repeat loop and count the pixels? Of course it is possible. Btw do not initialize repeatedly if the size of the screen does not change. Just do it once at the beginning of the script and only read the screen when you want to count the pixels. #include "..\GetScreen\GetScreen.au3" Local $hWnd = WinActivate("[CLASS:YourWindowClassHere]") If Not $hWnd Then Exit MsgBox($MB_SYSTEMMODAL, "Error", "Unable to find window") _GetScreen_Initialize(@DesktopWidth, @DesktopHeight) While True ToolTip(_PixelCountInArea(700, 460, 800, 750, "D05E5E"), 600, 500) Sleep(100) WEnd Func _PixelCountInArea($left, $top, $right, $bottom, $color) Local $founded = 0 _GetScreen_GetScreen() For $x = $left To $right For $y = $top To $bottom If Hex(_GetScreen_GetPixel($x, $y), 6) = $color Then $founded += 1 Next Next Return $founded EndFunc ;==>_PixelCountInArea Edited November 28, 2021 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy 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