为了账号安全,请及时绑定邮箱和手机立即绑定

没有 SWIG 和第三方库的 Go 中的 OpenCV

没有 SWIG 和第三方库的 Go 中的 OpenCV

Go
拉莫斯之舞 2021-08-16 19:42:26
主要目标:OpenCV在Go没有SWIG和第三方库的情况下工作(使用 Go 在 linux 中比较图像的应用程序)我是所有工具包的新手(OpenCv Go 和 linux)图像检测(feature2d 等)可以仅由 C-api 完成吗?没有方便的方法调用 C++ 代码并且 C-api 没有更新(?)我遵循了如何在 Go 中使用 C++?但我失败了。当我制作时,出现以下错误makefile:5: /usr/local/go/bin/src/Make.amd64: 没有那个文件或目录makefile:6: /usr/local/go/bin/src/Make.pkg: 没有那个文件或目录makefile: 8: *缺少分隔符。停止。在生成文件作为跟随GOROOT=/usr/local/go/bin     GOARCH=amd64     TARG=foo     CGOFILES=foo.go     include $(GOROOT)/src/Make.$(GOARCH)     include $(GOROOT)/src/Make.pkg     foo.o:foo.cpp     g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<     cfoo.o:cfoo.cpp     g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $<     CGO_LDFLAGS+=-lstdc++     $(elem)_foo.so: foo.cgo4.o foo.o cfoo.o     gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $@ $^ $(CGO_LDFLAGS)  非常感谢
查看完整描述

2 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

您不能在不自己编写 C 包装器 (+ cgo) 或使用 SWIG 的情况下调用 C++ 代码,遗憾的是它就是这样。

你链接的那个帖子已经过时了,不能再使用了。

另一方面,你总是可以在纯 Go 中开始重写 opencv,速度差异不会那么大,特别是如果你学会了如何使用 unsafe 来处理速度关键部分。

不建议使用 unsafe 的免责声明,因为它是不安全的。


查看完整回答
反对 回复 2021-08-16
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

你可以这样做,为了我自己的目的,我已经将 OpenCV 的一个非常简单的子集移植到 Go 中。通常,该过程是分配堆上的所有内容并将其作为 typedef'd 返回void*。例如:


typedef void* gocv_matrix;

从那里开始,您的很多工作都是直通函数。一个非常重要的注意事项是您的头文件必须是纯 C 并且只能(递归地)包含纯 C 的头文件。这意味着您的标头将主要是原型/前向声明。


所以标题中的一些 Matrix 方法mat.h可能看起来像


gocv_matrix newMatrix();

void add(gocv_matrix m1, gocv_matrix m2, gocv_matrix dst);

void destroy(gocv_matrix m);

然后你的实现mat.cxx看起来像


//include all relevant C++ OpenCV headers directly

gocv_matrix newMatrix() {

    cv::Matrix *mat = new cv::Matrix();

    return (gocv_matrix)mat;

}


void add(gocv_matrix m1, gocv_matrix m2, gocv_matrix dst) {

    cv::Matrix *a = (cv::Matrix *)m1;

    cv::Matrix *b = (cv::Matrix *)m2;

    cv::Matrix *dstMat = (cv::Matrix *)dst;

    (*dstMat) = (*a)+(*b);

}


void destroy(gocv_matrix m) {

    cv::Matrix *a = (cv::Matrix *)(m1);

    delete a;

}

(免责声明:这里的确切代码没有经过正确性验证,这只是要点)。


一些特别的注意事项:


确保你有一个你实际调用的销毁方法,否则你会泄漏内存。

由于 C 和 C++ 常量与 Go 常量不同,因此您必须将它们声明为var而不是const.

OpenCV 的一些常量包含在不是纯 C 的头文件中,这使得在 Go 中定义它们变得非常困难。我在一些图像处理子包中注意到了这一点。

请注意缺少模板化泛型。通常,您要么完全放弃模板,为每个可能的实例定义不同的类型,要么选择一个(可能是两倍,可能是用于显示图像的 int 大小)并坚持使用它。

请注意,您不能以这种方式使用重载运算符。所以 a+b*c 是 b.Mul(c).Add(a)。从理论上讲,您可以发明一些表达式解析器,它接受像 "a+(b*c)" 这样的字符串和矩阵列表,然后进行一些调用批处理,但是如果您当时处于开发阶段,您就不会问这个问题。

这通常对于 cgo 来说是正常的,但是您可能会经常使用 unsafe,特别是如果您想直接使用矩阵的原始支持数据。您可以通过使您的 Go 级别Mytype类型成为包含 aC.mytype而不是实际转换它的简单结构来稍微减少这种情况。

老实说,你可能应该只使用 SWIG,因为这基本上已经为你做了什么,除了额外的细节,比如在大多数情况下为你生成实际的 Go 常量而不是粗略的 var 魔法。


查看完整回答
反对 回复 2021-08-16
  • 2 回答
  • 0 关注
  • 276 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信