webentwicklung-frage-antwort-db.com.de

Wie übergebe ich eine OpenCV-Matte in eine C++ Tensorflow-Grafik?

In Tensorflow C++ kann ich eine Bilddatei mit in die Grafik laden

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

Für eine Embedded-Anwendung möchte ich stattdessen eine OpenCV-Mat in diese Grafik einfügen. 

Wie würde ich die Matte in einen Tensor umwandeln, der als Eingabe für tensorflow :: ops :: Cast oder tensorflow :: ops :: ExpandDims verwendet werden könnte?

15
lefty

Es ist nicht direkt von einem CvMat, aber Sie können ein Beispiel zum Initialisieren eines Tensors aus einem speicherinternen Array im TensorFlow sehen Android Beispiel: https: // github. de/tensorflow/tensorflow/blob/0.6.0/tensorflow/examples/Android/jni/tensorflow_jni.cc # L17

Sie würden damit beginnen, ein neues tensorflow :: Tensor-Objekt zu erstellen, das ungefähr so ​​aussieht (der gesamte Code ist ungetestet):

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

Dadurch wird ein Tensor-Objekt mit Gleitkommawerten mit einer Stapelgröße von 1 und einer Größe von widthx height sowie mit depth Kanälen erstellt. Zum Beispiel würde ein 128 mal 64 großes Bild mit 3 Kanälen in der Form {1, 64, 128, 3} Passieren. Die Stapelgröße wird nur verwendet, wenn Sie mehrere Bilder in einem einzigen Aufruf übergeben müssen, und für eine einfache Verwendung können Sie sie als 1 belassen.

Dann würden Sie das zugrunde liegende Array hinter dem Tensor mit einer Linie wie dieser erhalten:

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

Das Objekt input_tensor_mapped Ist eine Schnittstelle zu den Daten in Ihrem neu erstellten Tensor, in die Sie dann Ihre eigenen Daten kopieren können. Hier gehe ich davon aus, dass Sie source_data Als Zeiger auf Ihre Quelldaten festgelegt haben, zum Beispiel:

const float* source_data = some_structure.imageData;

Sie können dann Ihre Daten durchlaufen und kopieren:

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

Es gibt offensichtliche Möglichkeiten, diesen naiven Ansatz zu optimieren, und ich habe keinen Beispielcode zur Hand, um zu zeigen, wie man mit der OpenCV-Seite umgeht, um die Quelldaten zu erhalten, aber dies ist hoffentlich hilfreich, um Ihnen den Einstieg zu erleichtern.

23
Pete Warden

Ich hatte versucht, das Inception-Modell in der opencv-Datei Mat auszuführen, und der folgende Code funktionierte für mich https://Gist.github.com/kyrs/9adf86366e9e4e0f04addb . Obwohl es einige Probleme mit der Integration von opencv und Tensorflow gibt. Code funktionierte ohne Probleme für .png-Dateien, konnte jedoch .jpg und .jpeg nicht laden. Sie können dem folgen, um weitere Informationen zu erhalten https://github.com/tensorflow/tensorflow/issues/1924

1
kumar shubham

Hier ist ein vollständiges Beispiel zum Lesen und Füttern:

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