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?
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 width
x 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.
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
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));