【问题标题】:OpenCV in Go without SWIG and third-parties lib没有 SWIG 和第三方库的 Go 中的 OpenCV
【发布时间】:2014-09-25 07:57:23
【问题描述】:

主要目标:使OpenCV 在没有SWIG 和第三方库的情况下在Go 中工作(一个使用Go 在Linux 中比较图像的应用程序)

我是所有工具包(OpenCv Go 和 linux)的新手

  1. 图像检测(feature2d 等)只能由 C-api 完成吗? 没有方便的方式调用C++代码,C-api没有更新(?)

  2. 我关注了How to use C++ in Go?,但我失败了。 当我制作时,出现以下错误

ma​​kefile:5: /usr/local/go/bin/src/Make.amd64: 没有这样的文件或目录
makefile:6: /usr/local/go/bin/src/Make.pkg: 没有这样的文件或目录
makefile:8: *
缺少分隔符。停下来。

ma​​kefile如下

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)  

非常感谢

【问题讨论】:

    标签: go wrapper


    【解决方案1】:

    如果不自己编写 C 包装器 (+ cgo) 或使用 SWIG,就无法调用 C++ 代码,这就是可悲的方式。

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

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

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

    【讨论】:

    • 1.是的。我正在研究包装器,但我遇到了困难。你介意告诉我正确的方法吗?我已经尝试了很多,但仍然找不到可行的解决方案。非常感谢。 2.“用纯go重写opencv”,比起写一个包装器,这不是一个了不起的工作吗?
    • @Eric 是的,我只是举例说明你可以做到。
    【解决方案2】:

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

    typedef void* gocv_matrix;
    

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

    因此,标题 mat.h 中的一些 Matrix 方法可能看起来像

    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;
    }
    

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

    一些特别说明:

    • 确保您有实际调用的 destroy 方法,否则会泄漏内存。
    • 由于 C 和 C++ 常量与 Go 常量不同,您必须将它们声明为 var 而不是 const
    • OpenCV 的一些常量包含在非纯 C 的头文件中,这使得在 Go 中定义它们变得极其困难。我在一些图像处理子包中最注意到这一点。
    • 请注意缺少模板泛型。一般来说,您要么完全放弃模板,为每个可能的实例定义不同的类型,要么选择一个(可能是 double,可能是用于显示图像的 int 大小)并坚持使用它。
    • 请注意,您不能以这种方式使用重载运算符。所以 a+b*c 是 b.Mul(c).Add(a)。从理论上讲,您可以发明一些表达式解析器,它接收像“a+(b*c)”这样的字符串和矩阵列表,然后进行一些调用批处理,但是如果您处于开发阶段,您就不会问了这个问题。
    • 这对于 cgo 来说是正常的,但您可能会经常使用 unsafe,特别是如果您想直接使用矩阵的原始支持数据。您可以通过将 Go 级别的 Mytype 类型设置为包含 C.mytype 的简单结构而不是实际转换它来减少这种情况。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-16
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多