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

时间:2017-07-30 16:55:09

标签: python c++ opencv tensorflow compilation

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

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

这是C ++代码:

class Calculator:
    def addition(self,x,y):
        added = x + y
        return added
    def subtraction(self,x,y):
        subtracted = x - y
        return subtracted
    def multiplication(self,x,y):
        multiplied = x * y
        return multiplied
    def division(self,x,y):
        divided = x / y
        return divided

calculator = Calculator()
num1 = raw_input('First Number >')
num2 = raw_input('Second Number >')
print("1 \tAddition")
print("2 \tSubtraction")
print("3 \tMultiplication")
print("4 \tDivision")
operations = raw_input('Select operation number>')

if int(operations)== 1:
    print (calculator.addition(float(num1),float(num2)))
if int(operations)== 2:
    print (calculator.subtraction(float(num1),float(num2)))
if int(operations)== 3:
    print (calculator.multiplication(float(num1),float(num2)))
if int(operations)== 4:
    print (calculator.division(float(num1),float(num2)))

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

#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);

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

  

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

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

请您帮我编译op,以便成功加载并运行tensorflow?

编辑1:

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

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

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

解决方案:

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

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 个答案:

答案 0 :(得分:2)

您可以使用ldd检查您的图书馆是否需要丢失库。

只需检查ldd load_video.so

但是,您可能并未将某些共享库与某些您正在使用的OpenCV方法相关联。

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

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

答案 1 :(得分:1)

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

sudo chmod 777 (the name of your video file)

这应该让您的程序可以访问视频文件。 我不太了解C ++,但TensorFlow在被拒绝许可时经常会抛出此错误,所以请试一试并祝你好运!