简体   繁体   English

Tensorflow自定义操作与OpenCV未定义符号

[英]Tensorflow custom op with OpenCV undefined symbol

I'm writing a custom operation for Tensorflow that is supposed to load a video. 我正在为Tensorflow编写一个应该加载视频的自定义操作。 For this, I need to include OpenCV. 为此,我需要包含OpenCV。

For now, the operation simply tries to open a VideoCapture and returns an empty tensor. 目前,该操作只是尝试打开VideoCapture并返回空张量。

Here's the C++ code: 这是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);

Then, I use the following command to compile the code: 然后,我使用以下命令编译代码:

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

When I load the compiled code into a Python script (using tf.load_op_library ) and try to run the op I get the following error: 当我将编译的代码加载到Python脚本(使用tf.load_op_library )并尝试运行op时,我收到以下错误:

tensorflow.python.framework.errors_impl.NotFoundError: lib/ops/load_video.so: undefined symbol: _ZN2cv12VideoCaptureC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE tensorflow.python.framework.errors_impl.NotFoundError:lib / ops / load_video.so:undefined symbol:_ZN2cv12VideoCaptureC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

It looks like the compiled C++ code cannot access the appropriate OpenCV object. 看起来编译的C ++代码无法访问相应的OpenCV对象。 I don't know much about C++ compilation and linking, so the problem probably is that I'm compiling the custom op in a wrong way. 我对C ++编译和链接知之甚少,所以问题可能是我正在以错误的方式编译自定义op。

Could you please help me compile the op in such way, that it can be successfully loaded and run by tensorflow? 你能帮助我以这种方式编译op,它可以通过tensorflow成功加载和运行吗?

EDIT 1: 编辑1:

This is the Python script I use to load the custom op: 这是我用来加载自定义操作的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)

The error happens on the line 2 (ie when trying to load the compiled C++ code). 错误发生在第2行(即尝试加载已编译的C ++代码时)。

Solution: 解:

I managed to successfully compile and run the custom tensorflow op after rebuilding OpenCV. 在重建OpenCV之后,我成功地编译并运行了自定义tensorflow操作。 The compilation command is: 编译命令是:

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

You can check if your library requires some missing library using ldd . 您可以使用ldd检查您的库是否需要一些丢失的库。

Just check ldd load_video.so . 只需检查ldd load_video.so

However, probably you're not linking some shared library that some OpenCV method you're using requires. 但是,您可能没有链接某些您正在使用的OpenCV方法所需的共享库。

To be sure to link and include every library needed you can use pkg-config . 要确保链接并包含所需的每个库,您可以使用pkg-config

Remove your manually -I and -l flags that point to OpenCV libs and just add pkg-config --libs --cflags opencv that do the complete work (of including and linking libraries) for you 删除指向OpenCV库的手动-I-l标志,然后添加pkg-config --libs --cflags opencv ,为您完成全部工作(包括和链接库)

If you are running on Linux, cd into the directory that contains your video file and then perform, without the parentheses: 如果您在Linux上运行,请进入包含视频文件的目录,然后执行,不带括号:

sudo chmod 777 (the name of your video file)

This should give your program access to the video file. 这应该让您的程序访问视频文件。 I don't know much about C++, but TensorFlow often throws this error when it's denied permission, so give it a shot and good luck! 我对C ++知之甚少,但是当TensorFlow被拒绝许可时经常抛出这个错误,所以试一试,祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM