【问题标题】:Tensorflow custom op with OpenCV undefined symbol带有 OpenCV 未定义符号的 TensorFlow 自定义操作
【发布时间】:2017-07-30 16:55:08
【问题描述】:

我正在为应该加载视频的 Tensorflow 编写自定义操作。为此,我需要包含 OpenCV。

目前,该操作只是尝试打开一个 VideoCapture 并返回一个空张量。

这是 C++ 代码:

#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"


#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/op_kernel.h"

#include <iostream>

using namespace tensorflow;
using namespace cv;
using namespace std;

using shape_inference::ShapeHandle;
using shape_inference::DimensionHandle;

REGISTER_OP("LoadVideo")
    .Input("filename: string")
    .Output("frame: float32")
    .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) {
        TensorShape outputTensorShape({224, 224, 3});
        ShapeHandle outputShapeHandle;
        c->MakeShapeFromTensorShape(outputTensorShape, &outputShapeHandle);
        c->set_output(0, outputShapeHandle);
        return Status::OK();
    });

class LoadVideoOp : public OpKernel {
 public:
  explicit LoadVideoOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* context) override {
    // Grab the input tensor
    const Tensor& input_tensor = context->input(0);
    auto input = input_tensor.flat<string>();
    string filename = input(0);

    VideoCapture cap = VideoCapture("data/0eRkpTGq5pA.mp4");

    Tensor* output_tensor = NULL;
    OP_REQUIRES_OK(context, context->allocate_output(0, {224, 224, 3}, &output_tensor));

  }
};

REGISTER_KERNEL_BUILDER(Name("LoadVideo").Device(DEVICE_CPU), LoadVideoOp);

然后,我使用以下命令编译代码:

g++ -std=c++11 -shared -fPIC \
-I /home/master/anaconda3/envs/tf/lib/python3.6/site-packages/tensorflow/include \
-I ~/anaconda3/envs/tf/include/opencv2/ -I ~/anaconda3/envs/tf/include/opencv/ -O2 \
-L ~/anaconda3/envs/tf/lib \
load_video.cc -o load_video.so \
-lopencv_core -lopencv_videoio -lopencv_highgui \
-lopencv_imgproc -lopencv_video -lopencv_objdetect

当我将编译后的代码加载到 Python 脚本中(使用 tf.load_op_library)并尝试运行操作时,我收到以下错误:

tensorflow.python.framework.errors_impl.NotFoundError:lib/ops/load_video.so:未定义符号:_ZN2cv12VideoCaptureC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

编译后的 C++ 代码似乎无法访问相应的 OpenCV 对象。我对 C++ 编译和链接不太了解,所以问题可能是我以错误的方式编译自定义操作。

你能帮我编译一下这样的操作,它可以被tensorflow成功加载和运行吗?

编辑 1:

这是我用来加载自定义操作的 Python 脚本:

import tensorflow as tf
load_video_module = tf.load_op_library('lib/ops/load_video.so')
with tf.Session():
  x = load_video_module.load_video("data/0eRkpTGq5pA.mp4").eval()
  print(x)

错误发生在第 2 行(即尝试加载已编译的 C++ 代码时)。

解决方案:

在重建 OpenCV 后,我成功地编译并运行了自定义 tensorflow 操作。编译命令为:

g++ -std=c++11 -ggdb -shared -I`python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())'` `pkg-config --cflags opencv` -o load_video.so load_video.cc `pkg-config --libs opencv` -fPIC

【问题讨论】:

    标签: python c++ opencv tensorflow compilation


    【解决方案1】:

    您可以使用ldd 检查您的库是否需要某些缺少的库。

    只需检查ldd load_video.so

    但是,您可能没有链接您正在使用的某些 OpenCV 方法所需的某些共享库。

    为了确保链接并包含所有需要的库,您可以使用pkg-config

    手动删除指向 OpenCV 库的 -I-l 标志,然后添加 pkg-config --libs --cflags opencv 为您完成完成工作(包括和链接库)

    【讨论】:

      【解决方案2】:

      如果您在 Linux 上运行,请 cd 进入包含您的视频文件的目录,然后执行,不带括号:

      sudo chmod 777 (the name of your video file)
      

      这应该使您的程序可以访问视频文件。 我对C++了解不多,但是TensorFlow在被拒绝权限时经常会抛出这个错误,所以试试看,祝你好运!

      【讨论】:

      • 我试过了,但没有帮助。我认为问题发生在 OpenCV 甚至尝试访问视频文件之前。
      • 堆栈跟踪是否指示代码中发生错误的特定行?对于 TensorFlow,您可能会在堆栈跟踪的顶部找到它。
      • 是的,参见编辑 1。
      • TensorFlow 仅适用于 Python、Java、C 和 Go,因此这可能是个问题。 OpenCV 可以与 Python、Java、C 和 C++ 一起使用,所以我建议对于这样的事情,如果你想结合 OpenCV 和 TensorFlow,我建议你用 Python、Java 或 C 编写所有内容。不幸的是,我无能为力以任何其他方式,但我可以保证,如果你用 Python 编写所有内容,你的代码应该能够集成——它对我有用!
      • 好的,完成后告诉我,如果有什么不同。
      猜你喜欢
      • 1970-01-01
      • 2018-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多