Skip to content
On this page

Lua的OpenCV

此文档非常重要请开发者一定看完

目标是让它像 opencv-python 一样易于使用。

因此,OpenCV 文档应该是参考。

注意事项

  1. 格式注意 如果遇到 JPG 格式文件报错,请改用 PNG 格式保存或读取。

  2. 窗口显示与操作不可用 以下窗口显示与交互相关的函数 不可用

    • cv.imshow()
    • cv.waitKey()
    • cv.destroyAllWindows()
  3. Lua OpenCV 图像宽高获取方式变更 在 Lua 中读取 mat 格式图像时,不再使用 Python 中的写法 template.shape[:2] 来获取宽高, 而是直接用 .height.width 属性。 对比示例:Python 旧写法:

    python
    import cv2
    img = cv2.imread("pic1.png")
    height, width = img.shape[:2]

    Lua 新写法:

    lua
    local cv = require("cv")
    local img = cv.imread("pic1.png")
    local height, width = img.height, img.width

关键词参数

类似于 Python关键字参数或 C#命名参数,关键字参数让您从匹配调用方法参数列表中参数顺序的束缚中解放出来。

当一个函数有多个默认参数时,关键字参数允许您仅覆盖所需的参数,而无需指定之前的默认参数。

例如,给定cv.normalize的文档

cpp
void cv::normalize  (   InputArray       src,
                        InputOutputArray dst,
                        double           alpha = 1,
                        double           beta = 0,
                        int              norm_type = NORM_L2,
                        int              dtype = -1,
                        InputArray       mask = noArray()
    )
Python:
    cv.normalize( src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]] ) -> dst

以下表达式是等价的:

lua
cv.normalize(src, dst, alpha, beta, norm_type, dtype, mask)
cv.normalize(src, dst, alpha, beta, norm_type, dtype, opencv_lua.kwargs({ mask = mask }))
cv.normalize(src, dst, alpha, beta, norm_type, opencv_lua.kwargs({ dtype = dtype, mask = mask }))
cv.normalize(src, dst, alpha, beta, opencv_lua.kwargs({ norm_type = norm_type, dtype = dtype, mask = mask }))
cv.normalize(src, dst, alpha, opencv_lua.kwargs({ beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
cv.normalize(src, dst, opencv_lua.kwargs({ alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
cv.normalize(src, opencv_lua.kwargs({ dst = dst, alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))
cv.normalize(opencv_lua.kwargs({ src = src, dst = dst, alpha = alpha, beta = beta, norm_type = norm_type, dtype = dtype, mask = mask }))

当然,可选参数不是强制的。换句话说,如果您只想更改norm_type参数,您可以这样做

lua
cv.normalize(src, dst, opencv_lua.kwargs({ norm_type = cv.NORM_L1 }))

如何翻译 python/c++代码

opencv使用教程请参考部分 https://apachecn.github.io/opencv-doc-zh/#/docs/4.0.0/2.1-tutorial_py_image_display

转换通常直接从 Python 进行。

tuplesarrays 变为tables.

numpy 调用和 arrays 操作有它们的 cv.Mat 对应物。

关键词参数 将被包裹在 opencv_lua.kwargs中。


Python 翻译示例

python
import cv2 as cv

img = cv.imread("pic1.png")
height, width = img.shape[:2]
img_grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_grey, 100, 255, cv.THRESH_BINARY)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

print(f"Found { len(contours) } contours")

cv.drawContours(img, contours, -1, ( 0, 0, 255 ) , 2)
cv.imwrite("output3.png", img)
lua
local opencv_lua = require("opencv_lua")
local cv = opencv_lua.cv

local img = cv.imread("pic1.png")
local height, width = img.height, img.width --这里将python的取图片高宽template.shape[:2]改成.height和.width了

local img_grey = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
local ret, thresh = cv.threshold(img_grey, 100, 255, cv.THRESH_BINARY)
local contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

print("Found " .. #contours .. " contours")

cv.drawContours(img, contours, -1, { 0, 0, 255 }, 2)
local success1 = cv.imwrite("output3.png", img)
print(success1 and "" or "")

Lua 陷阱

1-索引

lua中数组是 1 索引的,而在 python 中是 0 索引的。因此,如果你在 python 中看到p[0],你应该在 lua 中写成p[1]

此外,opencv 函数仍然期望 0 索引的参数。例如

lua
for i = 1, #contours do
    -- Notice the i - 1
    cv.drawContours(src, contours, i - 1, {0, 0, 255}, 2)
end

实例方法调用

实例方法使用:而不是.调用。 : 后面的 —— 实例方法,成员函数. 后面的 —— 字段,静态方法或成员变量 如果您在 Python 中看到

python
cap = cv.VideoCapture(camId)
read, frame = cap.read()

您应该用 Lua 编写

lua
cap = cv.VideoCapture(camId)
read, frame = cap:read()

严格遵循文档

为了向后兼容,Python 仍然允许使用旧语法来定义枚举和调用构造函数。本库不支持。

如果您在 Python 中看到

python
cv.ml.SVM_create(...)
cv.ml.SVM_C_SVC
cv.TERM_CRITERIA_MAX_ITER

您应该用 Lua 编写

lua
cv.ml.SVM.create(...)
cv.ml.SVM.C_SVC
cv.TermCriteria.MAX_ITER

内存

图像处理会占用大量内存。仅依赖垃圾回收器的行为可能导致您的程序消耗比必要的更多内存。

因此,考虑在这些情况下调用collectgarbage

lua
local cap = cv.VideoCapture(0)
while true do
    -- 没有这个,内存会无限增长!!!
    collectgarbage()

    local read, frame = cap:read()
end

矩阵操作

为了获得最大的速度性能,当您需要在 lua 中操作矩阵时,将它们转换为 ,进行操作,然后再将它们转换回矩阵

lua
-- transform into an lua table for faster processing in lua
local rows, cols, type_ = res.rows, res.cols, res:type()
res = res:table()

for j = 1, rows do
    local y = j - 1
    for i = 1, cols do
        local x = i - 1
        if res[j][i] >= threshold then
            cv.rectangle(img_rgb, { x, y }, { x + w, y + h }, { 0, 0, 255 }, 2)
        end
    end
end

res = cv.Mat.createFromArray(res, type_)

从文件读取图像

lua
local img = cv.imread("starry_night.jpg")

代码解析

  • cv.imread(path[, flags, fromRecycle]) 用于从文件加载图像。
  • 参数说明:
    • path:图像文件路径,例如 "starry_night.jpg"
    • flags (可选)
      • cv.IMREAD_COLOR:BGR彩色(默认)。
      • cv.IMREAD_GRAYSCALE:灰度模式。
      • cv.IMREAD_UNCHANGED:原始数据(带透明通道)。
    • fromRecycle (可选,bool,默认 false)
      • true:只读取数据回收管理中的图片。
      • false 或不传:读取项目目录中的图片。

使用示例

lua
local opencv_lua = require("opencv_lua")
local cv = opencv_lua.cv

local img_color = cv.imread("starry_night.jpg", cv.IMREAD_COLOR, false)
if img_color then
    print("项目目录中找到图片")
else
    print("项目目录中未找到图片")
end

local img_recycle = cv.imread("starry_night.jpg", cv.IMREAD_COLOR, true)
if img_recycle then
    print("数据回收管理中找到图片")
else
    print("数据回收管理中未找到图片")
end

保存图像到文件

lua
cv.imwrite("output.jpg", img)

代码解析

  • cv.imwrite(filename, mat[, toRecycle]) 用于保存图像。
  • 参数说明:
    • filename:保存的文件路径,例如 "output.jpg"
    • matcv.Mat 图像数据对象。
    • toRecycle (可选,bool,默认 false)
      • true:只保存到数据回收管理中,不写入项目目录。
      • false 或不传:保存到项目目录。

使用示例

lua
local opencv_lua = require("opencv_lua")
local cv = opencv_lua.cv

local img = cv.imread("starry_night.jpg", cv.IMREAD_COLOR, false)
if not img then
    print("读取图片失败")
    return
end

if cv.imwrite("output.jpg", img, false) then
    print("图片已保存到项目目录")
else
    print("保存到项目目录失败")
end

if cv.imwrite("output_recycle.jpg", img, true) then
    print("图片已保存到数据回收管理")
else
    print("保存到数据回收管理失败")
end