Jump to content

Recommended Posts

Greetings friends!

I have been searching the help file and Google, with no success, to find a way to validate images from a folder and mark them somehow in a spreadsheet.

My context is: I made a code with the help of the community that captures images from SAP and saves them in a folder.  Now I'd like to identify which ones are black, if it's even possible. I read about PixelSearch, but did not get it to work. If someone could point me in the right direction, I'd appreciate it.

The code I'm using:

#include <File.au3>
#include <ScreenCapture.au3>

$x = InputBox("Title", "Amount of Images To Capture", "", "", 320, 150)
If @error Then Exit
$x = Number($x)

$y = InputBox("Title", "Batch Name", "", "", 320, 150)
If @error Then Exit
$y = String($y)

HotKeySet("{HOME}", "printscreen")

Func printscreen()
$FilePath =("C:\Fiscalizacao\Fotos"&"/")
$FileName = $y & " - "
$FileList = _FileListToArray($FilePath, $FileName & '*.jpg', 1)

If Not IsArray($FileList) Then
    $FileName&= '1.jpg'
Else
        $FileName &= $FileList[0] + 1 & '.jpg'
EndIf
_ScreenCapture_Capture($FilePath & "\" & $FileName, 354, 196, 673, 436)
EndFunc

HotKeySet("{BS}", "Terminate")
Func Terminate()
    Exit 0
EndFunc

For $i = 1 to $x

Opt("WinTitleMatchMode",2)
If NOT WinExists("Relatorio") Then
   MsgBox(0, "Atenção!", "Relatório do MOM deve estar aberto!")
   Call("Terminate")
EndIf
Opt("WinTitleMatchMode",2)
WinActivate("Relatorio")
Sleep (250)
Opt("WinTitleMatchMode",2)
SendKeepActive("Relatorio")
Send("{ENTER}")
Sleep (1000)
Send("{HOME}")
Sleep (200)
Opt("WinTitleMatchMode",2)
WinActivate("Relatorio")
Send("{DOWN}")

Next

 

Link to post
Share on other sites

If it is pure black I believe you could use PixelCheckSum when the image is displayed.  But you could also use GDI+ to load the image in memory and check if pixels are black.  I trust that the second option would be faster, especially if you have a large number of images.

Link to post
Share on other sites

Actually the images aren't always pure black. Sometimes lighter tones do appear. Right now what I'm doing is loading them up in a VBA form, to display them, then manually validate, the black ones.

 

Say, how could I use GDI+ with my code?

Link to post
Share on other sites

You can try with _GDIPlus_BitmapLockBits. There is an example in the help file  To me it is not clear if you only need to validate black images or also ones that are not pure black. If it is the second case then it would be a good idea to define "black color"

Link to post
Share on other sites

Here a basic example of how to check a specific pixel color of an image.jpg.   Now you will have to manage the different shades of black.  It will depend on how those shades appear in your images.  You could separate the pixels into RGB values and identify if it is close to black.  Anyway it will start you up...

#include <GDIPlus.au3>

Const $sFile = "Test.jpg"

_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
If @error Then
  _GDIPlus_Shutdown()
  Exit MsgBox($MB_SYSTEMMODAL, "", "An error has occured - unable to load image!")
EndIf

Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)     ;get width and height of the image
Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)     ;locks the bitmap for reading
Local $iScan0 = DllStructGetData($tBitmapData, "Scan0")     ;get scan0 (pixel data) from locked bitmap
Local $iSearchPixel = 0xFFFFFFFF     ; pure black
Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0)
Local $iPixel, $iRowOffset

For $iY = 0 To $iH - 1
  $iRowOffset = $iY * $iW + 1
  For $iX = 0 To $iW - 1       ;get each pixel in each line and row
    $iPixel = DllStructGetData($tPixel, 1, $iRowOffset + $iX)         ;get pixel color
    If $iPixel = $iSearchPixel Then ConsoleWrite("color found" & @CRLF)
  Next
Next
_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)     ;unlocks the bitmap that was locked by _GDIPlus_BitmapLockBits

;cleanup resources
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()

 

Link to post
Share on other sites

@ahmet the images are pictures taken on a field operation. Whey they are taken outside the parameters, they turn out "black", but not always pure black. Sometimes the result is a lighter shade of black. Nevertheless they have no content, which is what I'm trying to automate.

 

@Nine I have a large amount of files to analyze. I didn't quite get how to use your code to achieve that (I'm somewhat new to scripting in AutoIt). As far as I understood, the example covers one file at a time?

Link to post
Share on other sites
1 minute ago, AnRios said:

As far as I understood, the example covers one file at a time?

Yes you will need to adapt the code for multiple files.  It is kind of easy to do, but for now make it work for one file.  Try different images, and when it is all good, then change it for multiple files.  Good luck. 

Link to post
Share on other sites

Sorry, I tried to run it, but nothing happens. I used the location from which the images are stored. 

#include <GDIPlus.au3>

Const $sFile = "C:\Fiscalizacao\Fotos\Lote 01 - 1.jpg" ; here don't know if it's correct

_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
If @error Then
  _GDIPlus_Shutdown()
  Exit MsgBox($MB_SYSTEMMODAL, "", "An error has occured - unable to load image!")
EndIf

 

Link to post
Share on other sites

You copied just a few lines of code of my example !  And you say nothing happens ? What did you expect, some miracle ?  Copy my whole script, study it, open help file, read the explanations of each function, run all the examples of the help file related to those functions.  If it is still not clear, redo it until you have enough knowledge to modify the script in accordance of your needs.

Edited by Nine
Link to post
Share on other sites

wouldnt there be noticeable difference in file size?  thought being: who cares what the data actually is, just throw out the ones that dont have enough of it? 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to post
Share on other sites

Maybe this is something worth to investigate:

Edit:

It's really fast :). Here's a sample code which calculates the average color for every picture in a given directory.

16777216 = 0x000000 = black
33554431 = 0xFFFFFF = white

Set a threshold (try and error), maybe everything below 16777216 + 1000000 = 17777216 is black enough for you.

_ASM_BitmapGetAverageColorValue_Ex.zip

Edited by KaFu
Link to post
Share on other sites
8 hours ago, AnRios said:

Obviously I used the entire script.

No it was not obvious.  Beside your statement saying "Nothing happens" proves that you don't understand the basics of the script.

Link to post
Share on other sites
18 hours ago, Nine said:

No it was not obvious.  Beside your statement saying "Nothing happens" proves that you don't understand the basics of the script.

Your statement proves you have no education. I ran your code changing exclusively the file and nothing happened, I didn't know you were so senstitive to facts.

Edited by AnRios
Link to post
Share on other sites
  • Developers

Guys, please slow down and stop making this personal. 

Just stick to the facts or don't reply.

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to post
Share on other sites
On 11/6/2019 at 3:18 PM, AnRios said:

Sorry, I tried to run it, but nothing happens. I used the location from which the images are stored. 

#include <GDIPlus.au3>

Const $sFile = "C:\Fiscalizacao\Fotos\Lote 01 - 1.jpg" ; here don't know if it's correct

_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
If @error Then
  _GDIPlus_Shutdown()
  Exit MsgBox($MB_SYSTEMMODAL, "", "An error has occured - unable to load image!")
EndIf

 

please provide a sample image so i can test with your code. thanks. we can help you adapt @Nine's code. is this the total script that isn't working?

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to post
Share on other sites
11 minutes ago, Earthshine said:

please provide a sample image so i can test with your code. thanks. we can help you adapt @Nine's code.

Sure mate, thanks!

I know they all look pitch black, but some present slightly different shades.

No, I just posted the beggining because I didn't know If I put the source file in the right place. I tried the full code posted before.

#include <GDIPlus.au3>

Const $sFile = "Test.jpg" ; I just changed here from what I understood.

_GDIPlus_Startup()
Local $hImage = _GDIPlus_ImageLoadFromFile($sFile)
If @error Then
  _GDIPlus_Shutdown()
  Exit MsgBox($MB_SYSTEMMODAL, "", "An error has occured - unable to load image!")
EndIf

Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)     ;get width and height of the image
Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)     ;locks the bitmap for reading
Local $iScan0 = DllStructGetData($tBitmapData, "Scan0")     ;get scan0 (pixel data) from locked bitmap
Local $iSearchPixel = 0xFFFFFFFF     ; pure black
Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0)
Local $iPixel, $iRowOffset

For $iY = 0 To $iH - 1
  $iRowOffset = $iY * $iW + 1
  For $iX = 0 To $iW - 1       ;get each pixel in each line and row
    $iPixel = DllStructGetData($tPixel, 1, $iRowOffset + $iX)         ;get pixel color
    If $iPixel = $iSearchPixel Then ConsoleWrite("color found" & @CRLF)
  Next
Next
_GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)     ;unlocks the bitmap that was locked by _GDIPlus_BitmapLockBits

;cleanup resources
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()

Lote 01 - 26.jpg

Lote 01 - 293.jpg

Lote 01 - 415.jpg

 

 

 

Edited by AnRios
Link to post
Share on other sites

can you zip up a directory that has a couple of successful captures alongside some of these failures? 

I am still of the auspice that there is no need to read pixel values, nor even open the files.

 

**Or if sensitive can i see a screenshot of the directory in details view? my continued curiosity is about size discrepancies.

Edited by iamtheky

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to post
Share on other sites
13 minutes ago, iamtheky said:

can you zip up a directory that has a couple of successful captures alongside some of these failures? 

I am still of the auspice that there is no need to read pixel values, nor even open the files.

Ok friend, let's hope you are correct!


Here it goes the zipped directory and a screenshot of the situation. Several "good" images and a black one (failed).

Example.jpg

Pictures.zip

Link to post
Share on other sites

2 failed

2failed.thumb.PNG.379f7edbbc4d4b5c2e8006588ffc8239.PNG

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to post
Share on other sites
  • Jos locked this topic
Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Dave1
      Hello everyone,
      I have several signals on the screen that need to be monitored while a program is running. These signals are scattered around an image which is maximized on 4  equal resolution screens - the AutoIT Window Info does not recognize any objects on the program meaning that I'm left with the PixelSearch() and PixelCheckSum() functions to monitor the signals:
      The signals are as small as a 5x5 pixel area and their coordinates are known.
      I've been digging around for a while now in this forum about the PixelSearch() and PixelCheckSum()  and found some interesting and useful ideas for the use of them. I also came across some other UDF functions like MultiMon(), FastFind(), TtColXY() and the ImageSearch2015 scripts that might be useful for the final output. I don't know if hovering the mouse by using TtColXY() and output its ToolTip() information onto the log file will be faster than using PixelSearch() and/or PixelCheckSum() in a loop for all signals' coordinates.
      The colours of the signals are below:
      red - 0x00FF00 (opaque red)
      green - 0x00FF00 (opaque green)
      yellow - 0xFFFF00 (opaque yellow)
      black - 0x000000 (opaque black, default colour)
      EDIT:
      The desired output is to monitor and record/log the changes and status of each inside a .txt file or a .csv with the below format: 
      Local Machine Time        Signal,      Change,               delta-t
      14:32:07                  Signal1     Green - Yellow         DELTA-t1
      14:34:02                  Signal1     Yellow - Red           DELTA-t1
      14:35:14                  Signal2     Yellow - Red           DELTA-t2
      ...
      Below is the code I came up with. 
      #include <AutoItConstants.au3> #include <MsgBoxConstants.au3> #include <misc.au3> #include <Date.au3> #include <Array.au3> #include <File.au3> #include <ScreenCapture.au3> #include <WinAPI.au3> #include <WinAPIHObj.au3> Global $program_name, $program_open, $Wname, $tCurrent Global $button_xy[2] = [150, 175] Global $iniColour, $ColourCheck, $NewCheck Global $Red, $Green, $Blue, $Nil Global $sFilePath = @ScriptDir & "\Signals_status.txt" Global $SignalID[10] = ["Signal_1", "Signal_2", "Signal_3", "Signal_4", "Signal_5", "Signal_6", "Signal_7", "Signal_8", "Signal_9", "Signal_10"] $program_name = "Signals.exe" $Wname = "Training Task 3" $program_open = ShellExecute($program_name, @ScriptDir) WinWait($Wname) $iniColour = "0x" & Hex(PixelGetColor($button_xy[0], $button_xy[1]), 6) ;~ $iniChecksum = "0x" & Hex(PixelChecksum($button_xy[0], $button_xy[0] - 5, $button_xy[1], $button_xy[1] + 5), 6) $ColourCheck = "0x" & Hex(PixelChecksum($button_xy[0], $button_xy[0] - 5, $button_xy[1], $button_xy[1] + 5, 1, $Wname), 6) ConsoleWrite(_ColourID($iniColour) & " // " & _ColourID($ColourCheck) & @CRLF) ;~ $ColourCheck = "0x " & Hex(PixelGetColor($button_xy[0], $button_xy[1]), 6) $iniColour = $ColourCheck ;$iniChecksum = $currentCheck Do ;~ While 1 _WindowOnTop() _Close_Notepad() $NewCheck = "0x" & Hex(PixelChecksum($button_xy[0], $button_xy[0] - 5, $button_xy[1], $button_xy[1] + 5, 1, $Wname), 6) $tCurrent = _NowCalc() $LogFile = FileOpen($sFilePath, 2) FileWriteLine($LogFile, "Local Machine Time " & "Signal, " & "Change, " & "delta-t") ;~ $ColourCheck = "0x" & Hex(PixelChecksum($button_xy[0], $button_xy[0] - 5, $button_xy[1], $button_xy[1] + 5, 1, $Wname), 6) If $ColourCheck <> $NewCheck Then ;If there's a colour change from the current colour $ColourCheck = $NewCheck Local $tChange, $NewCheckID, $ColourCheckID, $sLogMsg $tChange = _NowCalc() ConsoleWrite("Colour changed!" & @CRLF) $ColourCheckID = _ColourID($ColourCheck) $NewCheckID = _ColourID($NewCheck) $iTimeDiffh = _DateDiff('h', $tChange, $tCurrent) ; time difference in hours $iTimeDiffm = _DateDiff('n', $tChange, $tCurrent) ; time difference in minutes $iTimeDiffs = _DateDiff('s', $tChange, $tCurrent) ; time difference in seconds $durationCheckSum = $iTimeDiffh & ":" & $iTimeDiffm & ":" & $iTimeDiffs ; Timestamp of the signal until PixelCheckSum $sLogMsg = " " & $SignalID[0] & " " & $ColourCheckID & " - " & $NewCheckID & " " & $durationCheckSum _FileWriteLog($LogFile, $sLogMsg) ElseIf $ColourCheck = $NewCheck Then Local $Colour_check = _ColourID("0x" & Hex(PixelChecksum($button_xy[0], $button_xy[0] - 5, $button_xy[1], $button_xy[1] + 5, 1, $Wname), 6)) ConsoleWrite($tCurrent & " " & $Colour_check & @CRLF) EndIf FileClose($sFilePath) Until Not ProcessExists($program_name) And Not WinExists($Wname) _IsProgramOpen() Func _Close_Notepad() $notepad_open = ProcessExists("notepad.exe") ? ProcessClose("notepad.exe") : ProcessClose("notepad.exe") $notepad_open = WinActive("[CLASS:Notepad]") ? WinClose("[CLASS:Notepad]") : ProcessClose("notepad.exe") EndFunc ;==>_Close_Notepad Func _ColourID($sColour) $Red = Int("0x" & StringRegExpReplace($sColour, "(..)(..)(..)(..)", "\2")) $Green = Int("0x" & StringRegExpReplace($sColour, "(..)(..)(..)(..)", "\3")) $Blue = Int("0x" & StringRegExpReplace($sColour, "(..)(..)(..)(..)", "\4")) If $Green > $Blue And $Red > $Blue And $Green >= 0xB0 And $Red >= 0xB0 Then $sCol = "Yellow" ElseIf $Blue > 0xE0 And $Green > 0xE0 And $Red > 0xE0 Then $sCol = "White" ElseIf $Blue > 0x50 And $Blue = $Green And $Blue = $Red Then $sCol = "Grey" ElseIf $Red > $Green And $Red > $Blue And $Red > 0x70 Then $sCol = "Red" ElseIf $Green > $Red And $Green >= $Blue And $Green > 0x70 Then $sCol = "Green" ElseIf $Blue > $Red And $Blue > $Green And $Blue > 0x70 Then $sCol = "Blue" Else $sCol = "Nil" EndIf Return $sCol EndFunc ;==>_ColourID Func _WindowOnTop() WinActivate($Wname) WinSetOnTop($Wname, "", $WINDOWS_ONTOP) Opt("MouseCoordMode", 0) EndFunc ;==>_WindowOnTop Func _IsProgramOpen() If Not ProcessExists($program_name) And Not WinExists($Wname) Then Break(1) EndIf EndFunc ;==>_IsProgramOpen When the program is running, the window opens in the centre of the screen however, the PixelChecksum function is not looking at the correct area. In addition:
      1 - I'm not sure about how to put the message into the log file.
      2 - I tested this script but it is not recording the message into the log file.
      3 - Is there other way to calculate the duration in these lines?
      $iTimeDiffh = _DateDiff('h', $tChange, $tCurrent) ; time difference in hours $iTimeDiffm = _DateDiff('n', $tChange, $tCurrent) ; time difference in minutes $iTimeDiffs = _DateDiff('s', $tChange, $tCurrent) ; time difference in seconds $durationCheckSum = $iTimeDiffh & ":" & $iTimeDiffm & ":" & $iTimeDiffs ; Timestamp of the signal until PixelCheckSum $sLogMsg = " " & $SignalID[0] & " " & $ColourCheckID & " - " & $NewCheckID & " " & $durationCheckSum _FileWriteLog($LogFile, $sLogMsg) Thanks in advance!
    • By Zaoka
      I'm trying to create script that would login on my SAP WEBI "web page" and replace some uploaded excel files. But i'm having problem on even the log in.
      These are user fill elements with Firefox Inspector
      <input type="text" id="_id0:logon:CMS" name="_id0:logon:CMS"> <input type="text" id="_id0:logon:USERNAME" name="_id0:logon:USERNAME"> <input type="password" id="_id0:logon:PASSWORD" name="_id0:logon:PASSWORD"> LogOnButton
      <input type="submit" id="_id0:logon:logonButton" value="Log On" class="logonButtonNoHover logon_button_no_hover" onmouseover="this.className = 'logonButtonHover logon_button_hover';" onmouseout="this.className = 'logonButtonNoHover logon_button_no_hover';">  
       
      My example, I tried _IEGetObjByName and _IEGetObjById but the script only open page but will not even fill out the form
        #include <IE.au3> Call("signIn") Func signIn() Global $oIE = _IECreate("http://192.xxx.xxx.xx:xxx/BOE/BI") Sleep (5000) Local $server = _IEGetObjByName($oIE, "_id0:logon:CMS") Local $username = _IEGetObjByName($oIE, "_id0:logon:USERNAME") Local $password = _IEGetObjByName($oIE, "_id0:logon:PASSWORD") Local $button = _IEGetObjById($oIE, "_id0:logon:logonButton") _IEFormElementSetValue($server, "TestServer:1000") _IEFormElementSetValue($username, "MyUserName") _IEFormElementSetValue($password, "MyPass") ; THIS PART ABOUT BUTTON CLICK I DONT UNDERSTAND AT ALL $sSelector = "body > div:nth-of-type(2) > div > div:nth-of-type(3) > div > table > tbody > tr > td > table > tbody > tr > td > table > tbody > tr:nth-of-type(1) > td > div > div:nth-of-type(1) > form > div:nth-of-type(5) > button" $signInUC = $oIE.document.QuerySelector($sSelector) _IEAction($signInUC, "click") EndFunc ;==>signIn  
      I would be very grateful for any help
    • By plankton
      While IsArray(PixelSearch(100, 100, 300, 300, 0xffffff))     Send("{ESC}")     Sleep(1000) WEnd  MsgBox(0,"Loop exited","") Hi, above is my function that will execute ESC button when white color is present in specific area which is color 0xffffff.
      But how do I do the opposite like when white color is not present in that specific area? Like this below code which gives me error
       
      While IsArray(PixelSearch(100, 100, 300, 300, <>0xffffff))     Send("{ESC}")     Sleep(1000) WEnd  MsgBox(0,"Loop exited","")  
       
    • By plankton
      Hi I want it to search for a specific color in certain area then excute the loop which presses ESC button and stop the loop when the color no longer present in that specific area.  Here is the example of my code. But it doesnt stop when color is disappeared.
       
      Pixelsearch(511, 455, 678, 501, 0xFFFFFF)
      If Not  @Error Then
      While 1
      Sleep(1000)
      Send("{ESC}")
      Pixelsearch(511, 455, 678, 501, 0xFFFFFF)
      If @Error Then Exitloop
       
    • By Borges
      Sorry if I posted in wrong section but...
      how can I do something like that?
       
      If PixelSearch(660, 30, 670, 38, 0x242424, 0 , 1) <> @error Then
          Send("{F3}")
          Sleep(200)
       ElseIf PixelSearch(800, 30, 810, 38, 0x242424, 0 , 1) <> @error Then
          Send("{F4}")
          Sleep(200)
       EndIf
       
×
×
  • Create New...