Jump to content

Recommended Posts

10 hours ago, smbape said:

7b is hard to translate since it involves manipulation of vectors and matrix

Yeah, there's a lot more work here than the python.

How to filter the list of vectors by square area immediately after _cveFindContoursTyped ?
Otherwise,  must filter before draw each type of profile, if there are more than one in script.

Link to post
Share on other sites
  • Replies 140
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

I wanted to use OpenCV v4+ in AutoIt. I found Opencv UDF on the forum, but there was no support for OpenCV v4+ This UDF provides support for OpenCV v4+ Update There is a new implem

If you mean having a subset of $contours that validates the condition on _cveContourAreaTyped, then it is Local $good_contours = _VectorOfVectorOfPointCreate() Local $tVectorPointPtr2 =

Hi @iZo Can you follow these running examples instructions  and give a feedback?

Posted Images

What we saw on the previous page:

Local $tVectorPointPtr2 = DllStructCreate("ptr value")
For $i = 0 To _VectorOfVectorOfPointGetSize($contours) - 1
    _VectorOfVectorOfPointGetItemPtr($contours, $i, $tVectorPointPtr2)
    Local $Area1 = _cveContourAreaTyped("VectorOfPoint", $tVectorPointPtr2.value)
    If $Area1 < 1000 Then
        ContinueLoop
    Else

But I want to make this filter once (after _cveFindContoursTyped), change $contours data, and use the modified data to build all types of contours.

Is that clear?

Thanks.

Link to post
Share on other sites
1 hour ago, Lion66 said:

Is that clear?

If you mean having a subset of $contours that validates the condition on _cveContourAreaTyped, then it is

Local $good_contours = _VectorOfVectorOfPointCreate()
Local $tVectorPointPtr2 = DllStructCreate("ptr value")
For $i = 0 To _VectorOfVectorOfPointGetSize($contours) - 1
    _VectorOfVectorOfPointGetItemPtr($contours, $i, $tVectorPointPtr2)
    Local $Area1 = _cveContourAreaTyped("VectorOfPoint", $tVectorPointPtr2.value)
    If $Area1 < 1000 Then
        ContinueLoop
    Else
    _VectorOfVectorOfPointPush($good_contours, $tVectorPointPtr2.value)

 

Link to post
Share on other sites

Yeah, that's what I wanted. Thank you!

I tried to make "8. Minimum Enclosing Circle" and stuck again.

Here's my search in the dark. 😞

Local $radius
        ;Local $box = _cveMatCreate()
        Local $tVectorPointPtr7 = DllStructCreate("ptr value")
        For $i = 0 To _VectorOfVectorOfPointGetSize($contours) - 1
            _VectorOfVectorOfPointGetItemPtr($contours, $i, $tVectorPointPtr7)
            Local $center = _cveInputArrayFromVectorOfPoint($tVectorPointPtr7.value)
            ;Func _cveMinEnclosingCircleTyped($typeOfPoints, $points, $center, $radius)
            _cveMinEnclosingCircleTyped("VectorOfPoint", $tVectorPointPtr7.value, $center, $radius)

            ;CvPoint2D32f* center
            Local $centerV = _VectorOfPointFCreateSize(2)
            _VectorOfPointFGetItemPtr($centerV, 0, $tVectorPointPtr7)
            Local $center_x = DllStructCreate($tagCvPoint2D32f, $tVectorPointPtr7.value)
            _VectorOfPointFGetItemPtr($centerV, 1, $tVectorPointPtr7)
            Local $center_y = DllStructCreate($tagCvPoint2D32f, $tVectorPointPtr7.value)


            ;float* radius



            ;Func _cveCircleTyped($typeOfImg, $img, $center, $radius, $color, $thickness = 1, $lineType = $CV_LINE_8, $shift = 0)
            _cveCircleTyped("Mat", $img, $centerV, $radius, _cvScalar(0, 255, 0), $CV_FILLED)
        Next

 

Link to post
Share on other sites
29 minutes ago, Lion66 said:

I tried to make "8. Minimum Enclosing Circle" and stuck again.

Here's my search in the dark. 😞

I must say that I am really amazed by your desire to learn. If I was a teacher, I would have loved to have a student like you. Keep it up.

; CVAPI(void) cveMinEnclosingCircle(cv::_InputArray* points, CvPoint2D32f* center, float* radius);
    Local $center = _cvPoint2f() ; equivalent of DllStructCreate($tagCvPoint2D32f)
    Local $radius = DllStructCreate("float value")
    _cveMinEnclosingCircleTyped("VectorOfPoint", $tVectorPointPtr.value, $center, $radius)
    $center = _cvPoint($center.x, $center.y)
    _cveCircleMat($img, $center, $radius.value, _cvScalar(0,255,0), 2)

 

Edited by smbape
Link to post
Share on other sites

I suppose that will do the 9.

Local $cvBox2D = DllStructCreate($tagCvBox2D)

    ; CVAPI(void) cveFitEllipse(cv::_InputArray* points, CvBox2D* box);
    _cveFitEllipseTyped("VectorOfPoint", $tVectorPointPtr.value, $cvBox2D)

    ; CVAPI(void) cveEllipse(cv::_InputOutputArray* img, CvPoint* center, CvSize* axes, double angle, double startAngle, double endAngle, const CvScalar* color, int thickness, int lineType, int shift);
    _cveEllipseMat($img, _cvPoint($cvBox2D.x, $cvBox2D.y), _cvSize($cvBox2D.width / 2, $cvBox2D.height / 2), $cvBox2D.angle, 0, 360, _cvScalar(0,255,0), 2)

 

Link to post
Share on other sites
3 hours ago, smbape said:

If I was a teacher, I would have loved to have a student like you. Keep it up.

Yes, teacher! 😃

Example 8 is working.

1 hour ago, smbape said:

I suppose that will do the 9.

You read my thoughts! 😉

But there's a little problem. If the contour is close to the edge of the picture, when trying to create an ellipse, the script is crashes.

That's probably what's indicated here (about fitEllipse()):

"Developer should keep in mind that it is possible that the returned ellipse/rotatedRect data contains negative indices, due to the data points being close to the border of the containing Mat element.".

I don't know what to do, but need to rule out crashes the script.

Thank you.

Edited by Lion66
Link to post
Share on other sites
1 hour ago, Lion66 said:

I don't know what to do, but need to rule out crashes the script.

I theorized that reducing the ellipse axes will solve the problem.
To test the theory, I need a test case.

Can you upload a script that crashes in those cases?

Link to post
Share on other sites

You script crashes for another reason.

There should be at least 5 points to fit the ellipse

You should add a condition before drawing fitEllipse

_VectorOfPointGetSize($tVectorPointPtr.value) >= 5

I found 2 ways to make the script dump errors.

  • set the environment variable OPENCV_DUMP_ERRORS to 1 and restart SciTE.
    EnvSet within a script does not work. SciTE has to be restarted.
    I recommend this way because all your scripts will benefit from it.
  • Add the following code in your script
    Local $hHandle = DllCallbackRegister("onError", "none", "int;ptr;ptr;ptr;int;ptr")
    _cveRedirectError(DllCallbackGetPtr($hHandle), Null, Null)
    
    ; ...
    
    Func onError($status, $func_name, $err_msg, $file_name, $line, $user_data)
        Local $errorStr = CStringToString(_cveErrorStr($status))
        $func_name = CStringToString($func_name)
        $err_msg = CStringToString($err_msg)
        $file_name = CStringToString($file_name)
    
        If $func_name == "" Then
            $func_name = "unknown function"
        EndIf
    
        ConsoleWrite("OpenCV Error: " & $errorStr & " (" & $err_msg & ") in " & $func_name & ", file " & $file_name & ", line " & $line & "" & @CRLF)
    EndFunc
    
    Func CStringToString($src)
        Local $sSrcDllType
        If IsDllStruct($src) Then
            $sSrcDllType = "struct*"
        Else
            $sSrcDllType = "ptr"
        EndIf
    
        Local $strlen = CVEDllCallResult(DllCall("msvcrt.dll", "int:cdecl", "strlen", $sSrcDllType, $src), "strlen", @error)
        Local $tStr = DllStructCreate("char value[" & $strlen & "]", $src)
    
        return $tStr.value
    EndFunc   ;==>CStringToString

     

Link to post
Share on other sites
10 hours ago, smbape said:

There should be at least 5 points to fit the ellipse

I didn't see it.

10 hours ago, smbape said:

_VectorOfPointGetSize($tVectorPointPtr.value) >= 5

It's a decision.

10 hours ago, smbape said:

Add the following code in your script

Local $hHandle = DllCallbackRegister("onError"

 

This is interesting in that it explains where the error is. But does not prevent the script from collapsing.

10 hours ago, smbape said:

set the environment variable OPENCV_DUMP_ERRORS to 1 and restart SciTE.

Do need to do this in Windows? I don't like solutions tied to a certain computer.

I did and saw no difference. Perhaps because I already used the decision ""Local $hHandle = DllCallbackRegister("onError".

 

Is it possible to replace in _cve freely _cvScalar(0, 255, 0) to _cvRGB(0, 255, 0). And vice versa?

Thank you.

Edited by Lion66
Link to post
Share on other sites
51 minutes ago, Lion66 said:

Do need to do this in Windows? I don't like solutions tied to a certain computer.

Well, you either set it in windows or in a command prompt, then start SciTE from that command prompt.
Usually, using EnvSet does the trick, but not in this case.

 

51 minutes ago, Lion66 said:

I did and saw no difference. Perhaps because I already used the decision ""Local $hHandle = DllCallbackRegister("onError".

Yes, using _cveRedirectError makes your function to be called instead of the default callback which logs the same error.

51 minutes ago, Lion66 said:

I didn't see it.

This is suprising. Once you activate OPENCV_DUMP_ERRORS, there should be in the console the error

OpenCV(4.5.3) Error: Incorrect size of input array (There should be at least 5 points to fit the ellipse) in cv::fitEllipseNoDirect

 

51 minutes ago, Lion66 said:

It's a decision.

I will rather say it is a consequence.
If you don't want your script to crash because of the error "There should be at least 5 points to fit the ellipse", you have to check that you have at least 5 points before computing fitEllipse

51 minutes ago, Lion66 said:

This is interesting in that it explains where the error is. But does not prevent the script from collapsing.

The only way to prevent a script from crashing is to handle errors that occurs.
For example, the following script will crash

Local $arr[1]
$arr[2] = 1

What could be the universal solution that will not make it crash?
Should we continue the script after not making it crash? A universal solution cannot decide that for you.

Edited by smbape
Link to post
Share on other sites
1 hour ago, Lion66 said:

I didn't see it.

It meant I didn't see it in the documentation before you pointed it out.

What about

1 hour ago, Lion66 said:

Is it possible to replace in _cve freely _cvScalar(0, 255, 0) to _cvRGB(0, 255, 0). And vice versa?

;;;;

 

Thanks.

Edited by Lion66
Link to post
Share on other sites
1 hour ago, smbape said:

The only way to prevent a script from crashing is to handle errors that occurs.

I understand that if you assume a mistake, then it can be processed. But when they have already learned a mistake, the script crashes.

Or is it possible to do something?

Link to post
Share on other sites
1 hour ago, Lion66 said:

Is it possible to replace in _cve freely _cvScalar(0, 255, 0) to _cvRGB(0, 255, 0). And vice versa?

Oh sorry, I missed that question.
No, _cvScalar can be seen as _cvBRGA. The first parameter is blue, the second is red, the third is green and the fourth is the opacity.
In AutoIt, we are used to RGB notation, that's why there is the convenient function _cvRGB.
Examples on the internet uses _cvScalar

Link to post
Share on other sites
4 minutes ago, Lion66 said:

But when they have already learned a mistake, the script crashes.

Or is it possible to do something?

I don't understand the question.
The script crashes when it encounters an error.
Who is "they" in "they have already learned a mistake" ? The users or the scripts?
If it is the users, you can't do anything about that.

Link to post
Share on other sites

When you say get back into the main loop, what do you expect the program to do:

  • Continue the loop. What if your program uses results of the previous loop?
  • Exit the loop. What if the process after the loop uses results of the previous loop?

I don't think it is possible in synchronous execution like in AutoIt.
In nodejs it is possible because it is asynchronous. When an unexpected error occurs, the current event loop is stopped, and nodejs goes to the next event loop.

Edited by smbape
Link to post
Share on other sites
  • smbape changed the title to OpenCV v4 UDF

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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By JoGa
      Greetings,
      here is a Autoit3 v3.3.14.5, 64 Bit installation on windows 10 with current updates.
      In a simple script I'm Dllcall'ing a 64 bit dll.
      # T1.au3 Local $name = "T1DLL.dll" if (FileExists($name)) Then ConsoleWrite("DLL '" &$name &"' exists" &@CRLF) EndIf Local $DLL = DllOpen($name) if (@ERROR OR $DLL = -1) then ConsoleWrite("DllOpen ERROR=" &@ERROR &" DLL=" &$DLL &@CRLF) Else ConsoleWrite("DllOpen Success" &@CRLF) endif DllCall($DLL, "none:cdecl", "SomeFunction", "str", "DLL Call from T1.au3") if (@ERROR) then ConsoleWrite("DllCall ERROR=" &@ERROR &" DLL=" &$DLL &@CRLF) Else ConsoleWrite("DllCall Success" &@CRLF) endif The C code contains one 64 bit OpenCV call:    cv::destroyAllWindows();.

      Excuting T1.au3 with SciTE gives:

      If the c code is compiled *without* the OpenCV call T1.au3 runs successful:
       
      I checked T1DLL.dll, it's definitely a 64 bit dll.
      What could cause the problem?
      Any hint would be very much appreciated.
      Thanks
      Wolf
       
       
       
       
    • By BBs19
      I needed a function to automate programs at work that can't be fully automated via Autoits built in functions.
      For example a virtual machine running on your physical machine, meaning you would need to run an extra script within the virtual machine (if it is even running Windows) in order to automate everything.
      I came across OpenCV which allows matching/finding a picture in another picture. This would also allow searching for a button/text on the screen in order to press the exact position. Fortunately @mylise already translated all the required OpenCV functions to Autoit, I just had to remove all unnecessary functions to make the script as small as possible.
      The problem:
      Using this method, you will never be able to fully automate everything dynamically, as it will only work on the machine with same resolution/dpi settings, same theme etc.. This is only a last resort for programs that can't be automated using the built in Autoit functions.
      Features:
      Find a given picture on the entire screen (all monitors) or a certain area on the screen and execute mouse clicks on this position. Adjust the threshold so that the picture doesn't have to match 100%. Debugging options like logging and marking the screen where the picture was found etc. Includes a Snapshot-Tool that creates snapshots of a certain area(buttons, text etc.) on the screen and generates the code that is required for the matching. It can also be used to get the coordinates to a marked area on the screen in order to check only on a certain area for the match picture. Example:
      Note: The example will probably not work on your computer, depending on the display resolution and dpi settings, as the picture has to match the exact same size on the screen. Please use the included Snapshot-Tool to generate new match pictures and code very easily.
      #AutoIt3Wrapper_UseX64=n ; In order for the x86 DLLs to work #include "OpenCV-Match_UDF.au3" _OpenCV_Startup();loads opencv DLLs _OpenCV_EnableLogging(True,True,True) ;Logs matches, errors in a log file and autoit console output. ;Please note that these examples might not work as the match pictures have to be found with the exact same size on your screen. ;Example 1 ShellExecute("http://www.tv.com/");Open Website tv.com $Match1 = _MatchPicture(@ScriptDir&"\Match\1.png", 0.70,False,10,500);Try to find the match picture on the screen. Number of tries: 10, Sleep between each try: 500ms. If Not @error Then _MarkMatch($Match1) ;Debugging: Draws a rect on the screen/coordinates of the match to show the user where the match was found Sleep(100) _ClickMouse($Match1, "left",1) ;Calculates the center of the match and clicks the left mouse once on click position EndIf Sleep(1000) ;Example 2, matching on a specific area of the screen ShellExecute("notepad.exe");open nodepad WinWait("[CLASS:Notepad]","",5) WinMove("[CLASS:Notepad]","",0,0,500,500) Local $sCoords[4] = [0, 0, 500,500] $Match2 = _MatchPicture(@ScriptDir&"\Match\2.png", 0.80,$sCoords,3,500) If Not @error Then _MarkMatch($Match2) Sleep(100) _ClickMouse($Match2, "left", 1) EndIf _OpenCV_Shutdown();Closes DLLs So basically, all you need to do is provide a path to the match picture and the function will return you the coordinates (x1,y1,x2,y2) of where the picture has been found on the screen. With these, you can either calculate an exact position for the mouse click or use the "_ClickMouse" function which will execute a mouse click on the center of the coordinates where the picture was found. 
      Credits:
      @mylise for the OpenCV UDF
       
      Download:
      Includes the required .DLL files of OpenCV. You can also manually download them on the website of OpenCV (Version 3.x doesn't include these anymore, you need to download 2.x).
      OpenCV_Match.zip
×
×
  • Create New...