如何将 OpenCV Mat 传递到 C++ Tensorflow 图中?
How do I pass an OpenCV Mat into a C++ Tensorflow graph?
在 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 输入的张量?
它不是直接来自 CvMat,但您可以在 TensorFlow Android 示例中看到如何从内存数组初始化张量的示例:
https://github.com/tensorflow/tensorflow/blob/0.6.0/tensorflow/examples/android/jni/tensorflow_jni.cc#L173
您将从创建一个新的 tensorflow::Tensor 对象开始,使用如下内容(所有代码均未经测试):
tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT,
tensorflow::TensorShape({1, height, width, depth}));
这将创建一个具有浮点值、批量大小为 1、大小为 width
xheight
和 depth
通道的 Tensor 对象。例如,具有 3 个通道的 128 宽 x 64 高图像将以 {1, 64, 128, 3}
的形状传递。 batch size 仅在需要在一次调用中传入多个图像时使用,为了简单使用,您可以将其保留为 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 端,但希望这对您入门有所帮助。
我曾尝试 运行 opencv Mat
文件上的初始模型,以下代码对我有效 https://gist.github.com/kyrs/9adf86366e9e4f04addb. Although there are some issue with integration of opencv and tensorflow. Code worked without any issue for .png
files but failed to load .jpg
and .jpeg
. You can follow this for more info https://github.com/tensorflow/tensorflow/issues/1924
这里是完整的阅读示例:
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));
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;
}
在 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 输入的张量?
它不是直接来自 CvMat,但您可以在 TensorFlow Android 示例中看到如何从内存数组初始化张量的示例: https://github.com/tensorflow/tensorflow/blob/0.6.0/tensorflow/examples/android/jni/tensorflow_jni.cc#L173
您将从创建一个新的 tensorflow::Tensor 对象开始,使用如下内容(所有代码均未经测试):
tensorflow::Tensor input_tensor(tensorflow::DT_FLOAT,
tensorflow::TensorShape({1, height, width, depth}));
这将创建一个具有浮点值、批量大小为 1、大小为 width
xheight
和 depth
通道的 Tensor 对象。例如,具有 3 个通道的 128 宽 x 64 高图像将以 {1, 64, 128, 3}
的形状传递。 batch size 仅在需要在一次调用中传入多个图像时使用,为了简单使用,您可以将其保留为 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 端,但希望这对您入门有所帮助。
我曾尝试 运行 opencv Mat
文件上的初始模型,以下代码对我有效 https://gist.github.com/kyrs/9adf86366e9e4f04addb. Although there are some issue with integration of opencv and tensorflow. Code worked without any issue for .png
files but failed to load .jpg
and .jpeg
. You can follow this for more info https://github.com/tensorflow/tensorflow/issues/1924
这里是完整的阅读示例:
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));
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;
}