【发布时间】:2019-01-22 01:52:24
【问题描述】:
我正在开发一个可以数字化纸张数字的安卓应用。我使用本机 OpenCV 代码来查找图像上的数字。之后我想使用 OpenCV 的 dnn 模块来识别号码。可以在此处找到有关创建神经网络的精彩教程:
https://www.youtube.com/watch?v=kFWKdLOxykE
mnist_convnet_graph.pbtxt 开头是这样的:
node {
name: "conv2d_1_input"
op: "Placeholder"
attr {
key: "dtype"
value {
type: DT_FLOAT
}
}
attr {
key: "shape"
value {
shape {
dim {
size: -1
}
dim {
size: 28
}
dim {
size: 28
}
dim {
size: 1
}
}
}
}
}
所以输入是 28x28 灰度图像。
在教程中,java 代码用于使用神经网络。但是,由于速度的原因,我想在 C++ 中使用它。我使用 cv::dnn::Net Dnn.readNetFromTensorflow(String model, String config); 成功加载了模型并将对象传递到 NDK 端。我使用以下内容为神经网络创建输入:
// The part of the image, we are interested in.
Rect roi(static_cast<int>(w), static_cast<int>(h),
static_cast<int>(w), static_cast<int>(h));
Mat cropped(image_gray, roi);
// Resize image to 28x28.
Mat resized;
cv::resize(cropped, resized, Size(28,28));
之后,转发应该可以工作了:
const double IN_SCALE_FACTOR = 0.003921; // 1.0/255.0
Mat blob = dnn::blobFromImage(resized, IN_SCALE_FACTOR, Size(28,28));
net.setInput(blob);
Mat detections = net.forward();
其中 net 是传递的 cv::dnn::Net 对象。但是 net.forward() 命令失败并给出:
OpenCV(3.4.5) 错误:虚拟布尔 cv::dnn::experimental_dnn_34_v11::DataLayer::getMemoryShapes(const std::vector >&, int, std:: 中的断言失败 (inputs.size() == requiredOutputs) vector >&, std::vector >&) const,文件 /build/3_4_pack-android/opencv/modules/dnn/src/dnn.cpp,第 681 行
我也试过了:
- 裁剪 rgb 图像
- Mat blob = dnn::blobFromImage(resized, 1.0f, Size(28,28));
- 不使用 blobFromImage,而是使用 net.setInput(resized); 代替
但这些都没有导致解决方案。有人对此有解决方案吗?任何建议或想法将不胜感激。
【问题讨论】:
-
能否提供
std::cout << blob.size << std::endl的输出? -
当然。这是一个 1x1x28x28 的图像。我不知道它是否适合输入。因为在mnist_convnet_graph.pbtxt文件中顺序不一样。
-
1x1x28x28可以。 OpenCV 可以管理的只是不同的数据布局。您能否分享一个完整的文本.pbtxt文件以查看它?请指定您使用的 OpenCV 版本。顺便说一句,您是否尝试过仅使用二进制.pb文件导入模型? -
当然。它在这里:link。我使用 OpenCV 3.4.5 版和 Android Studio 3.3。问题是
readNetFromTensorflow()函数的第一个参数是.pb文件(~17,4 MB),第二个参数是.pbtxt(~284 KB)。 -
hmm,看起来模型是在训练模式下序列化的(应该是测试模式)。有一个称为冻结的过程,它禁用了所有仅训练的节点(在您的图表中有)。
标签: android c++ opencv neural-network