Skip to content

smbape/node-emgucv-autoit-generator

Repository files navigation

Emgucv autoit udf

Do you want to use OpenCV v4+ in AutoIt v3 ?
If yes, then this udf might be for you.

Usage of the UDF

Prerequisites

Usage

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Opt("MustDeclareVars", 1)

#include "emgucv-autoit-bindings\cve_extra.au3"

; Open the library
_OpenCV_DLLOpen("libemgucv-windesktop-4.5.3.4721\libs\x64\cvextern.dll")

Local $img = _cveImreadAndCheck("data\lena.jpg")
_cveImshowMat("Image", $img)
_cveWaitKey()

; always release resources to avoid memory leaks on long running processes
_cveMatRelease($img)
_cveDestroyAllWindows()

; Close the library
_Opencv_DLLClose()

Running examples

# get the source files
git clone https://github.com/smbape/node-emgucv-autoit-generator
cd node-emgucv-autoit-generator

# download libemgucv-windesktop-4.5.3.4721 
curl -L 'https://github.com/emgucv/emgucv/releases/download/4.5.3/libemgucv-windesktop-4.5.3.4721.zip' -o libemgucv-windesktop-4.5.3.4721.zip
unzip libemgucv-windesktop-4.5.3.4721.zip -d libemgucv-windesktop-4.5.3.4721

Now you can run any file in the samples\tutorial_code folder.

[optional] Build the addon dll

This shows how to put performance critical tasks in c++ functions, export those functions in a dll and then use them in autoit.

Look at samples\tutorial_code\Histograms_Matching\calcHist_Demo.au3 for an example of usage.

Prerequisite

Building

Run build.bat script located in the autoit-addon folder.

How to translate python/c++ code to the UDF

  • Finding the functions/constants names.
  • Transform the parameter types according to the UDF parameter. This step might involve looking at the opencv documentation.
  • Adjust the return type and variable. This step might involve looking at the opencv documentation.

Finding the functions/constants names

For a function named foo or Foo, there is usually a function named _cveFoo

For a constant FOO, there is usually a Global Const ending with _FOO and starting with $CV_

Transform the parameter types

For cv::Point, cv::Range, cv::Rect, cv::Scalar and cv::Size types,
there are _cvPoint, _cvRange, _cvRect, _cvScalar and _cvSize functions to convert parameters.

For cv::ScalarAll, there is _cvScalarAll function.

Types which are *Array like cv::_InputArray, are harder to translate because there is no automatic convertion in AutoIt like in c++.
For this reason, for functions which take those type of parameters, there will be 2 additionnal functions.
_cveFooTyped where you specified the type of the Array parameter and
_cveFooMat where you specified the type of all the Array parameter are Mat.

For vectors, there are functions starting with _VectorOf that allows to managed them.
As examples, for std::vector<int>*, there is

  • _VectorOfInt
  • _VectorOfIntCreateSize
  • _VectorOfIntGetSize
  • _VectorOfIntPush
  • _VectorOfIntPushMulti
  • _VectorOfIntPushVector
  • _VectorOfIntClear
  • _VectorOfIntRelease
  • _VectorOfIntCopyData
  • _VectorOfIntGetStartAddress
  • _VectorOfIntGetEndAddress
  • _VectorOfIntGetItem
  • _VectorOfIntGetItemPtr
  • _VectorOfIntSizeOfItemInBytes

As examples, for std::vector<std::vector<cv::Point>>*, there is

  • _VectorOfVectorOfPoint
  • _VectorOfVectorOfPointCreateSize
  • _VectorOfVectorOfPointGetSize
  • _VectorOfVectorOfPointPush
  • _VectorOfVectorOfPointPushMulti
  • _VectorOfVectorOfPointPushVector
  • _VectorOfVectorOfPointClear
  • _VectorOfVectorOfPointRelease
  • _VectorOfVectorOfPointCopyData
  • _VectorOfVectorOfPointGetStartAddress
  • _VectorOfVectorOfPointGetEndAddress
  • _VectorOfVectorOfPointGetItem
  • _VectorOfVectorOfPointGetItemPtr
  • _VectorOfVectorOfPointSizeOfItemInBytes

Python translation example

Let's translate the following python code

blurred = cv2.GaussianBlur(image, (3, 3), 0)
T, thresh_img = cv2.threshold(blurred, 215, 255, cv2.THRESH_BINARY)
cnts, _ = cv2.findContours(thresh_img, 
                                cv2.RETR_EXTERNAL, 
                                cv2.CHAIN_APPROX_SIMPLE)

First line

blurred = cv2.GaussianBlur(image, (3, 3), 0)

The UDF function of GaussianBlur is

Func _cveGaussianBlur($src, $dst, $ksize, $sigmaX, $sigmaY = 0, $borderType = $CV_BORDER_DEFAULT)
    ; CVAPI(void) cveGaussianBlur(cv::_InputArray* src, cv::_OutputArray* dst, CvSize* ksize, double sigmaX, double sigmaY, int borderType);

The GaussianBlur documentation gives the following information

void cv::GaussianBlur   (   InputArray    src,
    OutputArray   dst,
    Size    ksize,
    double    sigmaX,
    double    sigmaY = 0,
    int   borderType = BORDER_DEFAULT 
  )     
Python:
  cv.GaussianBlur(  src, ksize, sigmaX[, dst[, sigmaY[, borderType]]] ) ->  dst

src input image;
dst output image;

In python, the returned value dst, is the OutputArray dst parameter of the c++ function, hence the UDF function.
src and dst are images, that means of type Mat

Because there are Array parameters, we have to use the Typed version of the UDF.
It allows to specify the type the Array parameters.

The python code will therefore become

$blurred = _cveMatCreate()
_cveGaussianBlurTyped("Mat", $image, "Mat", $blurred, _cvSize(3, 3), 0)

And because all the Array types are Mat, it is equivalent to

$blurred = _cveMatCreate()
_cveGaussianBlurMat($image, $blurred, _cvSize(3, 3), 0)

Second line

T, thresh_img = cv2.threshold(blurred, 215, 255, cv2.THRESH_BINARY)

Applying the same steps leads to

$thresh_img = _cveMatCreate()
$T = _cveThresholdMat($blurred, $thresh_img, 215, 255, $CV_THRESH_BINARY)

Third line

cnts, _ = cv2.findContours(thresh_img, 
                                cv2.RETR_EXTERNAL, 
                                cv2.CHAIN_APPROX_SIMPLE)

Accoroding to findContours documentation
countours is a std::vector<std::vector<cv::Point>>
hierarchy Optional output vector (e.g. std::vector<cv::Vec4i>):
hierarchy is harder to translate. cv::Vec4i is a Matrix. A vector of Mattrix is also a Matrix.

The python code will become

$cnts = _VectorOfVectorOfPointCreate()
$_ = _cveMatCreate()
_cveFindContoursTyped("Mat", $thresh_img, "VectorOfVectorOfPoint", $cnts, "Mat", $_, $CV_RETR_EXTERNAL, $CV_CHAIN_APPROX_SIMPLE)

Final result

Python

blurred = cv2.GaussianBlur(image, (3, 3), 0)
T, thresh_img = cv2.threshold(blurred, 215, 255, cv2.THRESH_BINARY)
cnts, _ = cv2.findContours(thresh_img, 
                                cv2.RETR_EXTERNAL, 
                                cv2.CHAIN_APPROX_SIMPLE)

AutoIt

$blurred = _cveMatCreate()
_cveGaussianBlurTyped("Mat", $image, "Mat", $blurred, _cvSize(3, 3), 0)

$thresh_img = _cveMatCreate()
$T = _cveThresholdMat($blurred, $thresh_img, 215, 255, $CV_THRESH_BINARY)

$cnts = _VectorOfVectorOfPointCreate()
$_ = _cveMatCreate()
_cveFindContoursTyped("Mat", $thresh_img, "VectorOfVectorOfPoint", $cnts, "Mat", $_, $CV_RETR_EXTERNAL, $CV_CHAIN_APPROX_SIMPLE)

Developpement

Prerequisites

Environment

In Git BASH, excute the following commands

# get the source files
git clone https://github.com/smbape/node-emgucv-autoit-generator
cd node-emgucv-autoit-generator

# Install nodejs dependencies
npm ci

# Install submodules
git submodule update --init --recursive

# Build emgucv cvextern.dll
git apply -v emgucv.patch --directory emgucv
find emgucv/ -type f -name '*.bat' -exec unix2dos '{}' \;
(cd $(realpath emgucv)/platforms/windows; CMAKE_BUILD_TYPE=Release ADDITIONAL_BUILD_TARGET=opencv_modules cmd.exe //c Build_Binary_x86.bat 64 nogpu vc no-openni "" "" build)

Generate the UDF files

node generate.js

History

I wanted to use OpenCV v4+ in AutoIt v3.

I found the Opencv UDF on the forum.
However it was for OpenCV v2 and there was a question for OpenCV v4+ without any anwser.

Therefore, there was no other option than trying find an answer myself.

AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting.
AutoIt v3 can use dynamic libraries (dll).
However, since v3, OpenCV does not expose all the needed functions for image processing.
It is now focused on c++ project integration.
That means, if you want to use OpenCV in AutoIt v3,
you will need to write your own dll and export as many functions as you need.

It can be tedious.

I supposed that other languages will have the same problem.
AutoIt v3 is focused on windows and .Net is, at least in the past, focused on windows.
There was a high chance that an OpenCV binding to .Net will involve dlls.

Therefore, I looked for OpenCV in .Net and I found emgucv.

emgucv is a cross platform .Net wrapper to the OpenCV image processing library.
The project has exported almost all the OpenCV functions in a dll, making their dll suitable to be used with AutoIt v3