Skip to content

Commit a773226

Browse files
committed
lint, use cv.Mat.table to improve performance, fix bit.cpp for lua 5.3, 5.4
1 parent ae567a1 commit a773226

File tree

27 files changed

+402
-180
lines changed

27 files changed

+402
-180
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ foreach(item ${files_to_change})
333333
vcpkg_regex_replace_string("${item}" "(/lua-opencv/releases/download/v|/lua-opencv/tree/v)[0-9]+\\.[0-9]+\\.[0-9]+" "\\1${PROJECT_VERSION}")
334334
vcpkg_regex_replace_string("${item}" "(opencv-|/opencv/opencv/blob/|opencv_lua )[0-9]+\\.[0-9]+\\.[0-9]+" "\\1${OpenCV_VERSION}")
335335
vcpkg_regex_replace_string("${item}" "(--branch )[0-9]+\\.[0-9]+\\.[0-9]+( https://github.com/opencv/opencv)" "\\1${OpenCV_VERSION}\\2")
336-
vcpkg_regex_replace_string("${item}" "(--branch )[0-9]+\\.[0-9]+\\.[0-9]+( https://github.com/smbape/lua-opencv)" "\\1${PROJECT_VERSION}\\2")
336+
vcpkg_regex_replace_string("${item}" "(--branch v)[0-9]+\\.[0-9]+\\.[0-9]+( https://github.com/smbape/lua-opencv)" "\\1${PROJECT_VERSION}\\2")
337337

338338
# Force LF EOL
339339
configure_file(${item} ${item} @ONLY NEWLINE_STYLE LF)

README.md

Lines changed: 199 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ Therefore the [OpenCV documentation](https://docs.opencv.org/4.x/index.html) sho
3333
- [Windows](#windows-2)
3434
- [Linux](#linux-2)
3535
- [Hosting you own binary rocks](#hosting-you-own-binary-rocks)
36+
- [Keyword arguments](#keyword-arguments)
37+
- [How to translate python/c++ code](#how-to-translate-pythonc-code)
38+
- [Python translation example](#python-translation-example)
39+
- [Python Gotchas](#python-gotchas)
40+
- [1-indexed](#1-indexed)
41+
- [Instance method calls](#instance-method-calls)
42+
- [Strict compliance with documentation](#strict-compliance-with-documentation)
43+
- [Memory](#memory)
44+
- [Matrix manipulation](#matrix-manipulation)
3645

3746
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
3847

@@ -206,21 +215,25 @@ Sources:
206215
--]]
207216

208217
local img_rgb = cv.imread("mario.png")
209-
assert(img_rgb, "file could not be read, check with os.path.exists()")
218+
assert(not img_rgb:empty(), "file could not be read, check with os.path.exists()")
210219
local img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
211220
local template = cv.imread("mario_coin.png", cv.IMREAD_GRAYSCALE)
212-
assert(template, "file could not be read, check with os.path.exists()")
221+
assert(not template:empty(), "file could not be read, check with os.path.exists()")
213222

214223
local h, w = template.height, template.width
215224

216-
local res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
225+
local res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
217226
local threshold = 0.8
218227

219-
for j=1,res.rows do
228+
-- transform into an lua table for faster processing in lua
229+
local rows, cols = res.rows, res.cols
230+
res = res:table()
231+
232+
for j = 1, rows do
220233
local y = j - 1
221-
for i=1,res.cols do
234+
for i = 1, cols do
222235
local x = i - 1
223-
if res(y, x) >= threshold then
236+
if res[j][i] >= threshold then
224237
cv.rectangle(img_rgb, { x, y }, { x + w, y + h }, { 0, 0, 255 }, 2)
225238
end
226239
end
@@ -304,3 +317,183 @@ For example, if you uploaded it into http://example.com/binary-rock/, you can in
304317
```sh
305318
luarocks install --server=http://example.com/binary-rock opencv_lua
306319
```
320+
321+
## Keyword arguments
322+
323+
Similar to python [keyword arguments](https://docs.python.org/3/glossary.html#term-argument) or c# [Named parameters](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#named-arguments), keyword arguments free you from matching the order of arguments to the order of parameters in the parameter lists of called methods.
324+
325+
When a function has multiple default parameters, keyword arguments allows you to override only the needed parameters without specifying the previous default parameters.
326+
327+
As an example, given the documentation of [cv.normalize](https://docs.opencv.org/4.x/d2/de8/group__core__array.html#ga87eef7ee3970f86906d69a92cbf064bd)
328+
329+
```cpp
330+
void cv::normalize ( InputArray src,
331+
InputOutputArray dst,
332+
double alpha = 1,
333+
double beta = 0,
334+
int norm_type = NORM_L2,
335+
int dtype = -1,
336+
InputArray mask = noArray()
337+
)
338+
Python:
339+
cv.normalize( src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]] ) -> dst
340+
```
341+
342+
the following expressions are equivalent:
343+
344+
```lua
345+
cv.normalize(src, dst, alpha, beta, norm_type, dtype, mask)
346+
cv.normalize(src, dst, alpha, beta, norm_type, dtype, opencv_lua.kwargs({ mask = mask }))
347+
cv.normalize(src, dst, alpha, beta, norm_type, opencv_lua.kwargs({ dtype = dtype, mask = mask }))
348+
cv.normalize(src, dst, alpha, beta, opencv_lua.kwargs({ norm_type = norm_type, dtype = dtype, mask = mask }))
349+
cv.normalize(src, dst, alpha, opencv_lua.kwargs({ beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
350+
cv.normalize(src, dst, opencv_lua.kwargs({ alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
351+
cv.normalize(src, opencv_lua.kwargs({ dst = dst, alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
352+
cv.normalize(opencv_lua.kwargs({ src = src, dst = dst, alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
353+
```
354+
355+
Of course, optional parameters are not mandatory. In other words, if you only want to change the `norm_type` parameter, you can do
356+
357+
```lua
358+
cv.normalize(src, dst, opencv_lua.kwargs({ norm_type = cv.NORM_L1 }))
359+
```
360+
361+
## How to translate python/c++ code
362+
363+
The transformation will usually be straight from python.
364+
365+
`tuples` and `arrays` becomes `tables`.
366+
367+
`numpy` calls and `arrays` manipulations have their `cv.Mat` counter parts.
368+
369+
`keyword arguments` will be wrapped within `opencv_lua.kwargs`.
370+
371+
### Python translation example
372+
373+
```python
374+
import cv2 as cv
375+
376+
img = cv.imread(cv.samples.findFile("pic1.png"))
377+
img_grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
378+
ret, thresh = cv.threshold(img_grey, 100, 255, cv.THRESH_BINARY)
379+
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
380+
381+
print(f"Found { len(contours) } contours")
382+
383+
cv.drawContours(img, contours, -1, ( 0, 0, 255 ) , 2)
384+
385+
cv.imshow("Image", img)
386+
cv.waitKey()
387+
cv.destroyAllWindows()
388+
```
389+
390+
```lua
391+
local opencv_lua = require("opencv_lua")
392+
local cv = opencv_lua.cv
393+
394+
local img = cv.imread(cv.samples.findFile("pic1.png"))
395+
local img_grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
396+
local ret, thresh = cv.threshold(img_grey, 100, 255, cv.THRESH_BINARY)
397+
local contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
398+
399+
print("Found " .. #contours .. " contours")
400+
401+
cv.drawContours(img, contours, -1, { 0, 0, 255 }, 2)
402+
403+
cv.imshow("Image", img)
404+
cv.waitKey()
405+
cv.destroyAllWindows()
406+
```
407+
408+
## Python Gotchas
409+
410+
### 1-indexed
411+
412+
Arrays are 1-indexed in `lua`, and 0-indexed in python. Therefore, if you see in python `p[0]`, you should write in lua `p[1]`
413+
414+
More over, opencv functions still expect 0-indexed parameters. For exemple
415+
416+
```lua
417+
for i = 1, #contours do
418+
-- Notice the i - 1
419+
cv.drawContours(src, contours, i - 1, {0, 0, 255}, 2)
420+
end
421+
```
422+
423+
### Instance method calls
424+
425+
Instance method are called with ':' not '.'.
426+
427+
If you see in python
428+
429+
```python
430+
cap = cv.VideoCapture(camId)
431+
read, frame = cap.read()
432+
```
433+
434+
You should write in lua
435+
436+
```python
437+
cap = cv.VideoCapture(camId)
438+
read, frame = cap:read()
439+
```
440+
441+
### Strict compliance with documentation
442+
443+
For backwards compatibility, python still allow an old syntax for enums and call constructors. This library does not.
444+
445+
If you see in python
446+
447+
```python
448+
cv.ml.SVM_create(...)
449+
cv.ml.SVM_C_SVC
450+
cv.TERM_CRITERIA_MAX_ITER
451+
```
452+
453+
You should write in lua
454+
455+
```lua
456+
cv.ml.SVM.create(...)
457+
cv.ml.SVM.C_SVC
458+
cv.TermCriteria.MAX_ITER
459+
```
460+
461+
### Memory
462+
463+
Image processing can use up a lot of memory. Relying solely on the behaviour of the garbage collector can cause your program to consume more memory than necessary.
464+
465+
Therefore, think about calling `collectgarbage` in those cases.
466+
467+
```lua
468+
local cap = cv.VideoCapture(0)
469+
while true do
470+
-- Without this, memory grows indefinitely
471+
collectgarbage()
472+
473+
local read, frame = cap:read()
474+
cv.imshow("capture camera", frame)
475+
if cv.waitKey(0) == 0x1b then break end
476+
end
477+
```
478+
479+
### Matrix manipulation
480+
481+
For maximum speed performance, when you need to manipulate matrices in lua, convert them `table`, do your manipulation and convert them back to matrices
482+
483+
```lua
484+
-- transform into an lua table for faster processing in lua
485+
local rows, cols, type = res.rows, res.cols, res:type()
486+
res = res:table()
487+
488+
for j = 1, rows do
489+
local y = j - 1
490+
for i = 1, cols do
491+
local x = i - 1
492+
if res[j][i] >= threshold then
493+
cv.rectangle(img_rgb, { x, y }, { x + w, y + h }, { 0, 0, 255 }, 2)
494+
end
495+
end
496+
end
497+
498+
res = cv.Mat.createFromArray(res, type)
499+
```

docs/docs.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,6 +2491,7 @@
24912491
- [cv.Mat.step1](#cvmatstep1)
24922492
- [cv.Mat.sum](#cvmatsum)
24932493
- [cv.Mat.t](#cvmatt)
2494+
- [cv.Mat.table](#cvmattable)
24942495
- [cv.Mat.tolist](#cvmattolist)
24952496
- [cv.Mat.total](#cvmattotal)
24962497
- [cv.Mat.type](#cvmattype)
@@ -28857,9 +28858,9 @@ lua:
2885728858

2885828859
```cpp
2885928860
static cv::Mat cv::Mat::createFromArray( sol::table array,
28860-
int depth = -1 );
28861+
int type = CV_64F );
2886128862
lua:
28862-
cv.Mat.createFromArray( array[, depth] ) -> retval
28863+
cv.Mat.createFromArray( array[, type] ) -> retval
2886328864
```
2886428865

2886528866
### cv.Mat.createFromVec2b
@@ -30047,12 +30048,20 @@ lua:
3004730048
oMat:t() -> retval
3004830049
```
3004930050

30051+
### cv.Mat.table
30052+
30053+
```cpp
30054+
sol::table cv::Mat::table();
30055+
lua:
30056+
oMat:table() -> retval
30057+
```
30058+
3005030059
### cv.Mat.tolist
3005130060

3005230061
```cpp
30053-
sol::table cv::Mat::tolist();
30062+
sol::table cv::Mat::table();
3005430063
lua:
30055-
oMat:tolist() -> retval
30064+
oMat:table() -> retval
3005630065
```
3005730066

3005830067
### cv.Mat.total

generator/declarations/Mat.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,10 +496,11 @@ module.exports = ({ self, self_get, shared_ptr }) => {
496496

497497
["cv.Mat.createFromArray", "Mat", ["/S", "/Call=::cvextra::createMatFromArray", "/Expr=$0, lua"], [
498498
["sol::table", "array", "", []],
499-
["int", "depth", "-1", []],
499+
["int", "type", "CV_64F", []],
500500
], "", ""],
501501

502502
["cv.Mat.tolist", "sol::table", ["/Call=::cvextra::tolistMat", `/Expr=${ self }, lua`], [], "", ""],
503+
["cv.Mat.table", "sol::table", ["/Call=::cvextra::tolistMat", `/Expr=${ self }, lua`], [], "", ""],
503504
];
504505

505506
const types = new Set(["int", "float", "double"]);

samples/01-show-image.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv

samples/02-video-capture-camera.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv
@@ -29,7 +29,7 @@ while true do
2929
-- Flip the image horizontally to give the mirror impression
3030
local frame = cv.flip(frame, 1)
3131

32-
cv.putText(frame, string.format("FPS : %.2f", fps), { 10, 30 }, cv.FONT_HERSHEY_PLAIN, 2, {255, 0, 255}, 3)
32+
cv.putText(frame, string.format("FPS : %.2f", fps), { 10, 30 }, cv.FONT_HERSHEY_PLAIN, 2, { 255, 0, 255 }, 3)
3333
cv.imshow("capture camera", frame)
3434

3535
local key = cv.waitKey(CAP_SPF)

samples/03-video-capture-file.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv

samples/04-rotate-image.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv

samples/05-drawing-contours.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv

samples/06-template-matching.lua

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1,1)) .. package.path
1+
package.path = arg[0]:gsub("[^/\\]+%.lua", '?.lua;'):gsub('/', package.config:sub(1, 1)) .. package.path
22

33
local opencv_lua = require("init")
44
local cv = opencv_lua.cv
@@ -9,21 +9,25 @@ Sources:
99
--]]
1010

1111
local img_rgb = cv.imread(cv.samples.findFile("mario.png"))
12-
assert(img_rgb, "file could not be read, check with os.path.exists()")
12+
assert(not img_rgb:empty(), "file could not be read, check with os.path.exists()")
1313
local img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
1414
local template = cv.imread(cv.samples.findFile("mario_coin.png"), cv.IMREAD_GRAYSCALE)
15-
assert(template, "file could not be read, check with os.path.exists()")
15+
assert(not template:empty(), "file could not be read, check with os.path.exists()")
1616

1717
local h, w = template.height, template.width
1818

19-
local res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
19+
local res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
2020
local threshold = 0.8
2121

22-
for j=1,res.rows do
22+
-- transform into an lua table for faster processing in lua
23+
local rows, cols = res.rows, res.cols
24+
res = res:table()
25+
26+
for j = 1, rows do
2327
local y = j - 1
24-
for i=1,res.cols do
28+
for i = 1, cols do
2529
local x = i - 1
26-
if res(y, x) >= threshold then
30+
if res[j][i] >= threshold then
2731
cv.rectangle(img_rgb, { x, y }, { x + w, y + h }, { 0, 0, 255 }, 2)
2832
end
2933
end

0 commit comments

Comments
 (0)