web-dev-qa-db-ja.com

OpenCVマットをC ++ Tensorflowグラフに渡すにはどうすればよいですか?

Tensorflow C++では、次を使用して画像ファイルをグラフにロードできます

tensorflow::Node* file_reader =  tensorflow::ops::ReadFile(tensorflow::ops::Const(IMAGE_FILE_NAME, b.opts()),b.opts().WithName(input_name));
tensorflow::Node* image_reader = tensorflow::ops::DecodePng(file_reader, b.opts().WithAttr("channels", 3).WithName("png_reader"));
tensorflow::Node* float_caster = tensorflow::ops::Cast(image_reader, tensorflow::DT_FLOAT, b.opts().WithName("float_caster"));
tensorflow::Node* dims_expander = tensorflow::ops::ExpandDims(float_caster, tensorflow::ops::Const(0, b.opts()), b.opts());
tensorflow::Node* resized = tensorflow::ops::ResizeBilinear(dims_expander, tensorflow::ops::Const({input_height, input_width},b.opts().WithName("size")),b.opts());

組み込みアプリケーションの場合は、代わりにOpenCV Matをこのグラフに渡します。

Matをtensorflow :: ops :: Castまたはtensorflow :: ops :: ExpandDimsへの入力として使用できるテンソルにどのように変換しますか?

16
lefty

CvMatから直接ではありませんが、TensorFlow Androidの例: https:// github。 com/tensorflow/tensorflow/blob/0.6.0/tensorflow/examples/Android/jni/tensorflow_jni.cc#L17

まず、次のような新しいtensorflow :: Tensorオブジェクトを作成します(すべてのコードはテストされていません)。

tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, height, width, depth}));

これにより、バッチサイズが1、サイズがwidthx height、フロート値、およびdepthチャネルを持つTensorオブジェクトが作成されます。たとえば、3つのチャネルを持つ幅128×高さ64の画像は、_{1, 64, 128, 3}_の形で渡されます。バッチサイズは、1回の呼び出しで複数の画像を渡す必要がある場合にのみ使用され、単純な用途では1のままにしておくことができます。

次に、次のような行を使用してテンソルの背後にある基になる配列を取得します。

auto input_tensor_mapped = input_tensor.tensor<float, 4>();

_input_tensor_mapped_オブジェクトは、新しく作成されたテンソル内のデータへのインターフェイスであり、独自のデータをそこにコピーできます。ここでは、ソースデータへのポインタとして_source_data_を設定していることを前提としています。次に例を示します。

_const float* source_data = some_structure.imageData;_

次に、データをループしてコピーします。

_for (int y = 0; y < height; ++y) {
    const float* source_row = source_data + (y * width * depth);
    for (int x = 0; x < width; ++x) {
        const float* source_pixel = source_row + (x * depth);
        for (int c = 0; c < depth; ++c) {
           const float* source_value = source_pixel + c;
           input_tensor_mapped(0, y, x, c) = *source_value;
        }
    }
}
_

この素朴なアプローチを最適化する明らかな機会があり、ソースデータを取得するOpenCV側を処理する方法を示すサンプルコードは手元にありませんが、これが開始に役立つことを願っています。

23
Pete Warden

私はopencv Matファイルでインセプションモデルを実行しようとしましたが、次のコードでうまくいきました https://Gist.github.com/kyrs/9adf86366e9e4f04addb 。ただし、opencvとtensorflowの統合にはいくつかの問題があります。 .pngファイルのコードは問題なく機能しましたが、.jpgおよび.jpegのロードに失敗しました。詳細については、これに従ってください https://github.com/tensorflow/tensorflow/issues/1924

1
kumar shubham

以下に、読み取りとフィードの完全な例を示します。

Mat image;
image = imread("flowers.jpg", CV_LOAD_IMAGE_COLOR);
cv::resize(image, image, cv::Size(input_height, input_width), 0, 0, CV_INTER_CUBIC);

int depth = 3;
tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT,
                                tensorflow::TensorShape({1, image.rows, image.cols, depth}));

for (int y = 0; y < image.rows; y++) {
    for (int x = 0; x < image.cols; x++) {
        Vec3b pixel = image.at<Vec3b>(y, x);

        input_tensor_mapped(0, y, x, 0) = pixel.val[2]; //R
        input_tensor_mapped(0, y, x, 1) = pixel.val[1]; //G
        input_tensor_mapped(0, y, x, 2) = pixel.val[0]; //B
    }
}

auto result = Sub(root.WithOpName("subtract_mean"), input_tensor, {input_mean});
ClientSession session(root);
TF_CHECK_OK(session.Run({result}, out_tensors));
0
Ivan Talalaev
Tensor convertMatToTensor(Mat &input)
{
    int height = input.rows;
    int width = input.cols;
    int depth = input.channels();

    Tensor imgTensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({height, width, depth}));

    float* p = imgTensor.flat<float>().data();
    Mat outputImg(height, width, CV_32FC3, p);
    input.convertTo(outputImg, CV_32FC3);

    return imgTensor;
}
0
Saurabh Saxena