如何使用opencv_dnn模块通过LeNet进行数字分类
How to use opencv_dnn module for digit classification by using LeNet?
我尝试使用相同的代码,但在这里进行了一些修改,使用基于 Caffe 的 mnist 训练模型进行数字识别。我修改后的源代码和网络如下。我还在末尾添加了错误消息。代码中使用的图像是来自 mnist 的示例图像。它无法通过的代码行是
net.forward();
我很确定这是因为输入的维度。
任何想法如何运行LeNet的代码?
caffe_mnist.cpp
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <time.h>
#include <math.h>
using namespace cv;
using namespace cv::dnn;
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
clock_t t;
/* Find best class for the blob (i. e. class with maximal probability) */
void getMaxClass(dnn::Blob &probBlob, int *classId, double *classProb)
{
Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix
Point classNumber;
minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
*classId = classNumber.x;
}
std::vector<String> readClassNames(const char *filename = "./caffe_model/mnist/label.txt")
{
std::vector<String> classNames;
std::ifstream fp(filename);
if (!fp.is_open())
{
std::cerr << "File with classes labels not found: " << filename << std::endl;
exit(-1);
}
std::string name;
while (!fp.eof())
{
std::getline(fp, name);
if (name.length())
classNames.push_back( name.substr(name.find(' ')+1) );
}
fp.close();
return classNames;
}
int main(int argc, char **argv)
{
String modelTxt = "./caffe_model/mnist/mnist.prototxt";
String modelBin = "./caffe_model/mnist/mnist.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "./caffe_model/mnist/0.png";
Ptr<dnn::Importer> importer;
try //Try to import Caffe GoogleNet model
{
importer = dnn::createCaffeImporter(modelTxt, modelBin);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
std::cerr << err.msg << std::endl;
}
if (!importer)
{
std::cerr << "Can't load network by using the following files: " << std::endl;
std::cerr << "prototxt: " << modelTxt << std::endl;
std::cerr << "caffemodel: " << modelBin << std::endl;
exit(-1);
}
dnn::Net net;
importer->populateNet(net);
std::cout << "done: importer->populateNet(net) " << std::endl;
importer.release(); //We don't need importer anymore
Mat img = imread(imageFile);
if (img.empty())
{
std::cerr << "Can't read image from the file: " << imageFile << std::endl;
exit(-1);
}
resize(img, img, Size(28, 28)); //LeNet accepts 224x224 RGB-images
std::cout << "done: resize(img, img, Size(28, 28)); " << std::endl;
dnn::Blob inputBlob = dnn::Blob(img); //Convert Mat to dnn::Blob image batch
net.setBlob(".data", inputBlob); //set the network input
std::cout << "done: net.setBlob(.data, inputBlob); " << std::endl;
t = clock();
net.forward();
std::cout << "done: net.forward(); " << std::endl;
//compute output
dnn::Blob prob = net.getBlob("prob"); //gather output of "prob" layer
int classId;
double classProb;
getMaxClass(prob, &classId, &classProb);//find the best class
std::vector<String> classNames = readClassNames();
std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
std::cout << "Probability: " << classProb * 100 << "%" << std::endl;
t = clock() - t;
std::cout << "Time Spent: " << ((float)t)/CLOCKS_PER_SEC << std::endl;
return 0;
} //main
mnist.prototxt
name: "LeNet"
input: "data"
input_dim: 1
input_dim: 1
input_dim: 28
input_dim: 28
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "prob"
type: "Softmax"
bottom: "ip2"
top: "prob"
}
错误:
done: importer->populateNet(net)
done: resize(img, img, Size(28, 28));
done: net.setBlob(.data, inputBlob);
OpenCV Error: Assertion failed (blobs[0].num() == outCn && blobs[0].channels() == inpCn / group) in allocate, file /home/ubuntu/opencv_contrib/modules/dnn/src/layers/convolution_layer.cpp, line 87
terminate called after throwing an instance of 'cv::Exception'
what(): /home/ubuntu/opencv_contrib/modules/dnn/src/layers/convolution_layer.cpp:87: error: (-215) blobs[0].num() == outCn && blobs[0].channels() == inpCn / group in function allocate
Aborted (core dumped)
也许您应用了不正确的图像。正确行:Mat img = imread(imageFile, CV_LOAD_IMAGE_GRAYSCALE);
我遇到了同样的问题。将其更改为CV_LOAD_IMAGE_GRAYSCALE后,代码运行没有错误。
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 我想做一个彼此不同但重复出现的数字
- 将数字转换为字母(例如:123 转换为一二三)
- C++如何计算用户输入的数字中的偶数位数
- 如何在C++中确定文本文件中的元素是字符还是数字
- 打印数字图案
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 如何检查一个c++字符串中有多少相同的字符/数字
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 将数字打印成文字
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 如何使用opencv_dnn模块通过LeNet进行数字分类