环境要求(*如果未安装请参考我的其他博客,有具体介绍)
部署流程图
代码文件
Lenet-5.pro,配置文件.添加opencv的库目录和caffe库目录及相关依赖项
#-------------------------------------------------
#
# Project created by QtCreator 2018-01-11T23:43:50
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Lenet-5
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
lenet.cpp
HEADERS += mainwindow.h \
lenet.h
FORMS += mainwindow.ui
#下面代码为具体配置,路径根据自己的修改
INCLUDEPATH += /usr/local/include \
/usr/local/include/opencv \
/usr/local/include/opencv2
LIBS += /usr/local/lib/libopencv_calib3d.so \
/usr/local/lib/libopencv_core.so \
/usr/local/lib/libopencv_features2d.so \
/usr/local/lib/libopencv_flann.so \
/usr/local/lib/libopencv_highgui.so \
/usr/local/lib/libopencv_imgcodecs.so \
/usr/local/lib/libopencv_imgproc.so \
/usr/local/lib/libopencv_ml.so \
/usr/local/lib/libopencv_objdetect.so \
/usr/local/lib/libopencv_photo.so \
/usr/local/lib/libopencv_shape.so \
/usr/local/lib/libopencv_stitching.so \
/usr/local/lib/libopencv_superres.so \
/usr/local/lib/libopencv_videoio.so \
/usr/local/lib/libopencv_video.so \
/usr/local/lib/libopencv_videostab.so
# caffe
INCLUDEPATH += ../include/caffe/include\
../include/caffe/src \
LIBS += /home/jinshan/caffe/build/lib/libcaffe.so
LIBS +=../lib/libcaffe.so.1.0.0-rc3
LIBS += -L../lib
LIBS += -lglog -lgflags -lprotobuf -lboost_system -lboost_thread -llmdb -lleveldb -lstdc++ -lcblas -latlas
QMAKE_CXXFLAGS += -std=c++0x
CONFIG += c++11
#ifndef LENET_H
#define LENET_H
#define CPU_ONLY //CPU Mode
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace caffe;
class Lenet
{
public:
Lenet();
~Lenet();
Lenet(std::string model_file,std::string delay_file); //model_file->weight delay->file->netFile
void WrapInputLayer(const vector imgs, std::vector *input_channels); //多张图片,h*w*3->3*h*w
void WrapInputLayer(const cv::Mat imgs, std::vector *input_channels); //单张图片,h*w*3->3*h*w
int Predict(cv::Mat img); //返回结果
std::shared_ptr< Net<float>>net; //网络
};
#endif // LENET_H
#include "lenet.h"
Lenet::Lenet(){}
Lenet::~Lenet(){}
Lenet::Lenet(std::string model_file,std::string delay_file)
{
//CPU模式
#ifdef CPU_ONLY
Caffe::set_mode(Caffe::CPU);
//GPU模式
#else
Caffe::set_mode(Caffe::GPU);
#endif
net.reset(new Net<float>(delay_file,TEST)); //加载网络文件
net->CopyTrainedLayersFrom(model_file); //加载权重文件
}
//将w*h*3转化位3*h*w
void Lenet:: WrapInputLayer(const vector imgs, std::vector *input_channels)
{
Blob<float> *input_layer = net->input_blobs()[0]; //取数据层blob
int width = input_layer->width(); //获得blob的宽度
int height = input_layer->height(); //获得blob高度
int num = input_layer->num(); //blob数量
float *input_data = input_layer->mutable_cpu_data(); //指针方向指向数据blob
for (int j = 0; j < num; j++) { //input_data ->input_channels;
//std::vector *input_channels;
for (int k = 0; k < input_layer->channels(); ++k)
{
cv::Mat channel(height, width, CV_32FC1, input_data);
input_channels->push_back(channel);
input_data += width * height;
}
cv::Mat img = imgs[j];
cv::split(img, *input_channels);//赋值->给网络赋值,分为三通道:r,g,b
input_channels->clear();
}
}
//单张图片,h*w*3->3*h*w
void Lenet::WrapInputLayer(const cv::Mat imgs, std::vector *input_channels)
{
Blob<float> *input_layer = net->input_blobs()[0]; //取数据层blob
int width = input_layer->width(); //获得blob的宽度
int height = input_layer->height(); //获得blob高度
float *input_data = input_layer->mutable_cpu_data(); //指针方向指向数据blob
for (int k = 0; k < input_layer->channels(); ++k)
{
cv::Mat channel(height, width, CV_32FC1, input_data);
input_channels->push_back(channel);
input_data += width * height;
}
cv::split(imgs, *input_channels);//赋值->给网络赋值,分为三通道:r,g,b
}
//预测结果
int Lenet::Predict(cv::Mat img)
{
std::vector<float> softMax;
cv::Mat grayImg;
if(img.channels()==3)
{
cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
}
//输入必须位灰度图
cv::resize(grayImg,grayImg, cv::Size(28,28),cv::INTER_CUBIC); //输入为28*28
//cv::imwrite("w.jpg", grayImg);
grayImg.convertTo(grayImg,CV_32FC1, 0.00392157); //归一化
//rehape net 设置网络输入尺寸
Blob<float> *input_layer = net->input_blobs()[0];
input_layer->Reshape(1, 1,grayImg.rows, grayImg.cols);
net->Reshape();
//change channels 数据转换
std::vector channels;
WrapInputLayer(grayImg,&channels);
//forword net 前向传播
net->Forward();
//get SOftMax label 取网络最后一层SoftMax
Blob<float>* out_layer = net->output_blobs()[0];
int count = out_layer->count();
const float* start_feature = out_layer->cpu_data();
const float* end_feature = out_layer->cpu_data() + count;
softMax =std::vector<float>(start_feature, end_feature);
//获得最大值的下标index=预测数字
float result = softMax[0];
int index = 0;
cout<< "sfds"<for(int i = 1; i < softMax.size();i++)
{
if(result< softMax[i])
{
result = softMax[i];
index = i;
}
cout<":"<cout<<"result:"<" ";
return index;
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "lenet.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置窗口
this->showMaximized(); //最大化
ui->srcImage->setScaledContents(true); //图片自适应label
//初始化网络
string model_file = "./lenet_iter_10000.caffemodel"; //权重文件
string delay_file = "./lenet_delay.prototxt"; //网络文件
lenetCNN = Lenet(model_file,delay_file); //初始化
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_selectImage_clicked() //按钮selectImage的槽函数
{
//获得图片路径
QString fileName = QFileDialog::getOpenFileName(
this, "open image",QDir::currentPath(),
"All files(*.jpg *.png *.bmp)"
);
//std::cout<
cv::Mat img; //定义图片
int resultNumber; //识别结果
img = cv::imread(fileName.toStdString()); //读取图片
resultNumber = lenetCNN.Predict(img); //预测
ui->reseult->setText("number: " + QString::number(resultNumber)); //显示
// cout<<"number:"<
//图片显示到srcImage控件上
cv::cvtColor(img, img, CV_BGR2RGB);
QImage qImg = QImage((const unsigned char*)(img.data), img.cols, img.rows, img.cols * img.channels(), QImage::Format_RGB888);
ui->srcImage->clear();
ui->srcImage->setPixmap(QPixmap::fromImage(qImg));
}
#include "mainwindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}