Use GDI+ to do image search?
Use GDI+ to do image search?
I am using ImageSearch to search a bitmap image in a loop, however it causes my screen lag sometimes. I did some research and found out that I can use GDI+ instead, I just got into ahk and never heard of GDI+, can someone give me a example how it works? and maybe offer me some useful link? Thanks.
Re: Use GDI+ to do image search?
I still need help please.
Re: Use GDI+ to do image search?
This is actually pretty fiddly if you're new to Gdip.ahk/Gdip_All.ahk. Plus you need to include an add-on script: Gdip_ImageSearch.ahk.
HTH
HTH
Code: Select all
;put Gdip.ahk (or Gdip_All.ahk) and Gdip_ImageSearch.ahk into:
;C:\Program Files\AutoHotkey\Lib
;at GitHub, right-click the Raw button to save the ahk file
;Gdip/Gdip.ahk at master · tariqporter/Gdip · GitHub
;https://github.com/tariqporter/Gdip/blob/master/Gdip.ahk
;Gdip_All.ahk
;https://www.dropbox.com/s/0e9gdfetbfa8v0o/Gdip_All.ahk
;AutoHotkey/Gdip_ImageSearch.ahk at master · MasterFocus/AutoHotkey · GitHub
;https://github.com/MasterFocus/AutoHotkey/blob/master/Functions/Gdip_ImageSearch/Gdip_ImageSearch.ahk
;an example of a regular ImageSearch:
;My first project: How hard/easy it is to develop a script for this? - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?p=131491#p131491
q::
vPathN := A_Desktop "\MyNeedleImage.png"
vPathH := A_Desktop "\MyHaystackImage.png"
vScreen1 := 0
vScreen2 := 0
vScreen3 := A_ScreenWidth
vScreen4 := A_ScreenHeight
vScreen := vScreen1 "|" vScreen2 "|" vScreen3 "|" vScreen4
vPos1 := 0, vPos2 := 0, vPos3 := vScreen3, vPos4 := vScreen4
pToken := Gdip_Startup()
vMode := "s"
;vMode := "f"
if (vMode = "s") ;haystack is screen
pBitmapH := Gdip_BitmapFromScreen(vScreen, 0x40CC0020)
if (vMode = "f") ;haystack is another image
{
pBitmapH := Gdip_CreateBitmapFromFile(vPathH)
Gdip_GetDimensions(pBitmapH, vPos3, vPos4)
MsgBox, % vPos3 " " vPos4
}
pBitmapN := Gdip_CreateBitmapFromFile(vPathN)
;vRet: 0=not found, 1=found
vRet := Gdip_ImageSearch(pBitmapH, pBitmapN, vPosXY, vPos1, vPos2, vPos3, vPos4)
vPos := InStr(vPosXY, ",")
vPosX := SubStr(vPosXY, 1, vPos-1)
vPosY := SubStr(vPosXY, vPos+1)
Gdip_DisposeImage(pBitmapH)
Gdip_DisposeImage(pBitmapN)
Gdip_Shutdown(pToken)
MsgBox, % vRet " (" vPosXY ")"
;MsgBox, % vPosX " " vPosY
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Use GDI+ to do image search?
Sorry for reviving an old post
My %Ret% value always shows as 1 (1 instance found) Even if my needle nor my haystack is visible on screen. What could be the reason for this?
My Haystack and Needle : https://imgur.com/a/AHvHxwm
My %Ret% value always shows as 1 (1 instance found) Even if my needle nor my haystack is visible on screen. What could be the reason for this?
My Haystack and Needle : https://imgur.com/a/AHvHxwm
Re: Use GDI+ to do image search?
It depends on what is in the bitmap for which you provided the pointer when you called the function. Unless you created a bitmap of the whole screen, then it’s not likely that the bitmap being searched contains both instances.
Re: Use GDI+ to do image search?
Im sorry to bother you, im not that advanced in coding. What do you mean when you said "It depends on what is in the bitmap for which you provided the pointer when you called the function"? Am i understanding this right, my haystack and needle are wrong?
And one last question, is the %RET% value (instances found) from the number of times the Needle was found? or the number of times the Haystack was found?
And one last question, is the %RET% value (instances found) from the number of times the Needle was found? or the number of times the Haystack was found?
Re: Use GDI+ to do image search?
The bitmap you identify as your haystack doesn’t need to be visible on the screen for GDI+ to search it, unlike AutoHotkey’s built-in ImageSearch command. If you want to search only what’s visible, you can use that. Why did you choose to use GDI+ to search for your image?
Re: Use GDI+ to do image search?
I wanted to search for an image even if my application/game is not in focus (behind other windows). My problem is it always shows 1 instance even if that Needle and Haystack is not visible anywhere. Its driving me insane.boiler wrote: ↑13 Mar 2021, 07:28The bitmap you identify as your haystack doesn’t need to be visible on the screen for GDI+ to search it, unlike AutoHotkey’s built-in ImageSearch command. If you want to search only what’s visible, you can use that. Why did you choose to use GDI+ to search for your image?
thanks again for the reply
Re: Use GDI+ to do image search?
The haystack needs to be captured from your game window, not some separate image that you’ve already saved and are referring to as the haystack. Are you capturing images from your game in real time as new haystacks?
Are you perhaps using an allowable variation so large that you image is always found no matter what?
You should show your script because your question in general cannot be answered since this isn’t how it would work if things were set up properly.
Are you perhaps using an allowable variation so large that you image is always found no matter what?
You should show your script because your question in general cannot be answered since this isn’t how it would work if things were set up properly.
Re: Use GDI+ to do image search?
Here is my scriptboiler wrote: ↑13 Mar 2021, 09:55The haystack needs to be captured from your game window, not some separate image that you’ve already saved and are referring to as the haystack. Are you capturing images from your game in real time as new haystacks?
Are you perhaps using an allowable variation so large that you image is always found no matter what?
You should show your script because your question in general cannot be answered since this isn’t how it would work if things were set up properly.
Code: Select all
#NoEnv
#SingleInstance Force
SetBatchLines, -1
Process, Priority,, High
SetTitleMatchMode, 3
#Include GDIP.ahk
#Include Gdip_ImageSearch.ahk
;OnExit, EXIT_LABEL
gdipToken := Gdip_Startup()
bmpHaystack := Gdip_CreateBitmapFromFile("IMG/cabal.png")
bmpNeedle := Gdip_CreateBitmapFromFile("IMG/respawn.png")
RET := Gdip_ImageSearch(bmpHaystack,bmpNeedle,LIST,0,0,0,0,0,0xFFFFFF,1,0)
MsgBox, %RET%
;ControlClick, x408 y429, CABAL,, Left,, NA Pos
;Sleep, 1500
*/
EXIT_LABEL:
Gdip_Shutdown(gdipToken)
EXITAPP
Re: Use GDI+ to do image search?
i used autohotkey master's GDIP_ImageSearch
https://github.com/MasterFocus/AutoHotkey/tree/master/Functions/Gdip_ImageSearch
https://github.com/MasterFocus/AutoHotkey/tree/master/Functions/Gdip_ImageSearch
Re: Use GDI+ to do image search?
So as I suspected, you are only searching in an image file you already created as the haystack, which is why it always finds one and exactly one image in it. It sounds like you are actually looking to find when that image appears in your game, which means you would have to have the script continuously capture new images from the game window using Gdip_BitmapFromHWND() or similar and perform Gdip_ImageSearch() on the newly captured image as the haystack. Using a static image you captured already has no link to your active game window, so there would be nothing in your script telling it to look there.
Re: Use GDI+ to do image search?
Makes a lot of sense, thank you so much. I'll look into it.boiler wrote: ↑13 Mar 2021, 13:10So as I suspected, you are only searching in an image file you already created as the haystack, which is why it always finds one and exactly one image in it. It sounds like you are actually looking to find when that image appears in your game, which means you would have to have the script continuously capture new images from the game window using Gdip_BitmapFromHWND() or similar and perform Gdip_ImageSearch() on the newly captured image as the haystack. Using a static image you captured already has no link to your active game window, so there would be nothing in your script telling it to look there.
Re: Use GDI+ to do image search?
Thanks so much for the help previously, it almosts works as intended but there's one slight hiccup.
by the way, i'll totally understand if you stop replying cause im asking too many questions dont worry.
here's the code im using in order to run my image detection thing on a certain window. I did what you said and used Gdip_BitmapFromHwnd instead (I changed the function variable in order to just type the title in there instead of the ID). It almost works, I tested it by setting the RET variable to 1 (i changed the current RET to RET1 so the script doesnt get confused) my script, if RET = 1... Ran.
My problem is my %RET% is always 0, even if the needle image is on the window as clear as day. Any reason why that would be? thank you so much in advance once again.
by the way, i'll totally understand if you stop replying cause im asking too many questions dont worry.
here's the code im using in order to run my image detection thing on a certain window. I did what you said and used Gdip_BitmapFromHwnd instead (I changed the function variable in order to just type the title in there instead of the ID). It almost works, I tested it by setting the RET variable to 1 (i changed the current RET to RET1 so the script doesnt get confused) my script, if RET = 1... Ran.
My problem is my %RET% is always 0, even if the needle image is on the window as clear as day. Any reason why that would be? thank you so much in advance once again.
Code: Select all
#NoEnv
#SingleInstance Force
SetBatchLines, -1
Process, Priority,, High
SetTitleMatchMode, 3
#Include GDIP.ahk
#Include Gdip_ImageSearch.ahk
;OnExit, EXIT_LABEL
imgsearch:
gdipToken := Gdip_Startup()
bmpHaystack := Gdip_BitmapFromHWND("CABAL")
bmpNeedle := Gdip_CreateBitmapFromFile("IMG/respawn.png")
RET := Gdip_ImageSearch(bmpHaystack,bmpNeedle,LIST,0,0,0,0,0,0xFFFFFF,1,0)
MsgBox, %RET%
if RET = 0
GoSub, imgsearch
if RET = 1
ControlClick, x408 y429, CABAL,, Left,, NA Pos
Sleep, 1500
Return
*/
EXIT_LABEL:
Gdip_Shutdown(gdipToken)
EXITAPP
Re: Use GDI+ to do image search?
Are you saying you actually changed the code of the Gdip_BitmapFromHwnd() function to use the window title instead of the HWND? Changing the variable name or something like that wouldn’t do it. You’d actually have to change some of the lines of code. It’s easy enough to pass the actual HWND to it, so you should do this and use the original version of the function:
When a function expects an HWND, it’s expected that you grab it in your script, like above, not that you would find it manually and type it in, especially since it changes every time the window is created.
Some other thoughts:
Is there a reason you set the “Trans” parameter to be white? Not that it should hurt in this case, but I’m not sure of the reason to do so here. You might think you need to provide some value, but you don’t. A null value (the default) will mean that no color values will be taken to be transparent. When a default parameter value exists, as does this one, you can just leave it blank to use the default like below. You could have done that for many of the parameters.
If it still doesn’t work after the above fix for the HWND, I suggest saving the captured bitmap to a file using the appropriate Gdip function so you can see if it’s actually capturing the window correctly.
Using gosub for looping isn’t a great practice, especially when it would be recursive like that. Even goto (which I hate) would be better in this case, but it would be best to use proper looping commands (loop, while, until, break, continue).
I would only perform Gdip_Startup() once in your script, not every time through the loop.
Code: Select all
bmpHaystack := Gdip_BitmapFromHWND(WinExist("CABAL"))
Some other thoughts:
Is there a reason you set the “Trans” parameter to be white? Not that it should hurt in this case, but I’m not sure of the reason to do so here. You might think you need to provide some value, but you don’t. A null value (the default) will mean that no color values will be taken to be transparent. When a default parameter value exists, as does this one, you can just leave it blank to use the default like below. You could have done that for many of the parameters.
Code: Select all
RET := Gdip_ImageSearch(bmpHaystack,bmpNeedle,LIST,0,0,0,0,0,,1,0)
If it still doesn’t work after the above fix for the HWND, I suggest saving the captured bitmap to a file using the appropriate Gdip function so you can see if it’s actually capturing the window correctly.
Using gosub for looping isn’t a great practice, especially when it would be recursive like that. Even goto (which I hate) would be better in this case, but it would be best to use proper looping commands (loop, while, until, break, continue).
I would only perform Gdip_Startup() once in your script, not every time through the loop.
Re: Use GDI+ to do image search?
Thank you so much for your input, i'll try it out. Hope it'll work this timeboiler wrote: ↑16 Mar 2021, 06:57Are you saying you actually changed the code of the Gdip_BitmapFromHwnd() function to use the window title instead of the HWND? Changing the variable name or something like that wouldn’t do it. You’d actually have to change some of the lines of code. It’s easy enough to pass the actual HWND to it, so you should do this and use the original version of the function:When a function expects an HWND, it’s expected that you grab it in your script, like above, not that you would find it manually and type it in, especially since it changes every time the window is created.Code: Select all
bmpHaystack := Gdip_BitmapFromHWND(WinExist("CABAL"))
Some other thoughts:
Is there a reason you set the “Trans” parameter to be white? Not that it should hurt in this case, but I’m not sure of the reason to do so here. You might think you need to provide some value, but you don’t. A null value (the default) will mean that no color values will be taken to be transparent. When a default parameter value exists, as does this one, you can just leave it blank to use the default like below. You could have done that for many of the parameters.Code: Select all
RET := Gdip_ImageSearch(bmpHaystack,bmpNeedle,LIST,0,0,0,0,0,,1,0)
If it still doesn’t work after the above fix for the HWND, I suggest saving the captured bitmap to a file using the appropriate Gdip function so you can see if it’s actually capturing the window correctly.
Using gosub for looping isn’t a great practice, especially when it would be recursive like that. Even goto (which I hate) would be better in this case, but it would be best to use proper looping commands (loop, while, until, break, continue).
I would only perform Gdip_Startup() once in your script, not every time through the loop.
Re: Use GDI+ to do image search?
I seem to have a problem which i dont know if it is fixable or not.
The code that you told me to make works, but not on the window that i want it to.
I did the save bitmap to file function. When I use a different window, I get a .png file of whatever the window looks like EXACTLY. but whenever I put CABAL as the window (which is my intended window to use), it just shows the titlebar of the app with a pure white canvas in it.
Im asking if this is a game issue? like an anticheat of some sort or is it just a code error?
(Code works on a different window, "Msgbox success" appears, but with the window that i want it to work on, it doesnt. I already did Run as administrator)
The code that you told me to make works, but not on the window that i want it to.
I did the save bitmap to file function. When I use a different window, I get a .png file of whatever the window looks like EXACTLY. but whenever I put CABAL as the window (which is my intended window to use), it just shows the titlebar of the app with a pure white canvas in it.
Im asking if this is a game issue? like an anticheat of some sort or is it just a code error?
(Code works on a different window, "Msgbox success" appears, but with the window that i want it to work on, it doesnt. I already did Run as administrator)
Code: Select all
#NoEnv
#SingleInstance Force
SetBatchLines, -1
Process, Priority,, High
SetTitleMatchMode, 3
#Include GDIP.ahk
#Include Gdip_ImageSearch.ahk
OnExit, EXIT_LABEL
Checkbmp := "Check.png"
gdipToken := Gdip_Startup()
Gdip_SaveBitmapToFile(bmpHaystack, Checkbmp)
Loop
{
bmpHaystack := Gdip_BitmapFromHWND(WinExist("CABAL"))
bmpNeedle := Gdip_CreateBitmapFromFile("IMG/test.png")
RET := Gdip_ImageSearch(bmpHaystack,bmpNeedle,,0,0,0,0,0,0,1,10)
}
Until RET = 1
MsgBox Success
EXIT_LABEL:
Gdip_Shutdown(gdipToken)
EXITAPP
Re: Use GDI+ to do image search?
Try replacing Gdip_BitmapFromHWND() with this version which allows for more graphics rendering approaches to be captured:
Code: Select all
Gdip_BitmapFromHWND(hwnd)
{
WinGetPos,,, Width, Height, ahk_id %hwnd%
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
RegExMatch(A_OsVersion, "\d+", Version)
PrintWindow(hwnd, hdc, Version >= 8 ? 2 : 0)
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
return pBitmap
}
Re: Use GDI+ to do image search?
Finally! works like a charm.
Thank you so much for your help!
The new Gdip_CreateBitmapFromFile() function fixed it.
Again, thank you so much for your time and patience!
Thank you so much for your help!
The new Gdip_CreateBitmapFromFile() function fixed it.
Again, thank you so much for your time and patience!