自己写程序利用lenet模型识别手写数字

自己编写程序,将手写图片送入训练得到的lenet模型,评估识别结果。
code:https://github.com/lhnows/caffeProjects
如果自己的caffe是用CMakeLists编译安装的,这样的话,可以运行如下的CMakeLists来编译自己的调用了caffe库的程序

CMakeLists.txt


cmake_minimum_required (VERSION 2.8)

PROJECT (mnistTest)


# Requires OpenCV v2.4.1 or later  
FIND_PACKAGE( OpenCV REQUIRED )  
IF (${OpenCV_VERSION} VERSION_LESS 2.4.1)  
    MESSAGE(FATAL_ERROR "OpenCV version is not compatible : ${OpenCV_VERSION}. requires atleast OpenCV v2.4.1")  
ENDIF() 


find_package(Caffe)  
include_directories(${Caffe_INCLUDE_DIRS})  
add_definitions(${Caffe_DEFINITIONS})   

add_executable(${PROJECT_NAME} mnistTest.cpp)
include_directories ( /Users/liuhao/devlibs/deeplearning/caffe/install/include
    /usr/local/include
    /usr/local/cuda/include )

target_link_libraries(${PROJECT_NAME} ${Caffe_LIBRARIES}
                        ${OpenCV_LIBS}  )

mnistTest.cpp


#define USE_OPENCV 1
#define CPU_ONLY 1
//貌似caffe有3种矩阵计算加速方式 mkl  accelerate blas,本人Mac编译的可能是下面这种(其他会报错找不到头文件)
//#define USE_ACCELERATE

#include <iostream>
#include <string>


#include <caffe/caffe.hpp>
#include <vector>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "head.h"

#include <algorithm>
#include <iosfwd>
#include <memory>
#include <utility>
#include <vector>
using namespace caffe;
using namespace cv;


cv::Point previousPoint(-1, -1), nowPoint(-1, -1);
Mat srcimage=Mat::zeros(280,280,CV_8UC1);
Mat srcimageori = Mat::zeros(280, 280, CV_8UC1);

class Classifier {
public:
    Classifier(const string& model_file,
        const string& trained_file);

    int Classify(const cv::Mat& img);

private:

    std::vector<int> Predict(const cv::Mat& img);

    void WrapInputLayer(std::vector<cv::Mat>* input_channels);

    void Preprocess(const cv::Mat& img,
        std::vector<cv::Mat>* input_channels);

private:
    shared_ptr<Net<float> > net_;
    cv::Size input_geometry_;
    int num_channels_;
};

Classifier::Classifier(const string& model_file,
    const string& trained_file) 
{
#ifdef CPU_ONLY
    Caffe::set_mode(Caffe::CPU);
#else
    Caffe::set_mode(Caffe::GPU);
#endif

    /* Load the network. */
    net_.reset(new Net<float>(model_file, TEST));
    net_->CopyTrainedLayersFrom(trained_file);

    CHECK_EQ(net_->num_inputs(), 1) << "Network should have exactly one input.";
    CHECK_EQ(net_->num_outputs(), 1) << "Network should have exactly one output.";

    Blob<float>* input_layer = net_->input_blobs()[0];
    num_channels_ = input_layer->channels();
    CHECK(num_channels_ == 3 || num_channels_ == 1)
        << "Input layer should have 1 or 3 channels.";
    input_geometry_ = cv::Size(input_layer->width(), input_layer->height());

}

/* Return the top N predictions. */
int Classifier::Classify(const cv::Mat& img) {
    std::vector<int> output = Predict(img);
    std::vector<int>::iterator iter=find(output.begin(), output.end(), 1);
    int prediction = distance(output.begin(), iter);
    return prediction<10 ? prediction:0;
}
std::vector<int> Classifier::Predict(const cv::Mat& img) {
    Blob<float>* input_layer = net_->input_blobs()[0];
    input_layer->Reshape(1, num_channels_,
        input_geometry_.height, input_geometry_.width);
    /* Forward dimension change to all layers. */
    net_->Reshape();

    std::vector<cv::Mat> input_channels;
    WrapInputLayer(&input_channels);

    Preprocess(img, &input_channels);

    net_->Forward();

    /* Copy the output layer to a std::vector */
    Blob<float>* output_layer = net_->output_blobs()[0];
    const float* begin = output_layer->cpu_data();
    const float* end = begin + output_layer->channels();
    return std::vector<int>(begin, end);
}

void Classifier::WrapInputLayer(std::vector<cv::Mat>* input_channels) {
    Blob<float>* input_layer = net_->input_blobs()[0];

    int width = input_layer->width();
    int height = input_layer->height();
    float* input_data = input_layer->mutable_cpu_data();
    for (int i = 0; i < input_layer->channels(); ++i) {
        cv::Mat channel(height, width, CV_32FC1, input_data);
        input_channels->push_back(channel);
        input_data += width * height;
    }
}

void Classifier::Preprocess(const cv::Mat& img,
    std::vector<cv::Mat>* input_channels) {
    /* Convert the input image to the input image format of the network. */
    cv::Mat sample;
    if (img.channels() == 3 && num_channels_ == 1)
        cv::cvtColor(img, sample, cv::COLOR_BGR2GRAY);
    else if (img.channels() == 4 && num_channels_ == 1)
        cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY);
    else if (img.channels() == 4 && num_channels_ == 3)
        cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR);
    else if (img.channels() == 1 && num_channels_ == 3)
        cv::cvtColor(img, sample, cv::COLOR_GRAY2BGR);
    else
        sample = img;

    cv::Mat sample_resized;
    if (sample.size() != input_geometry_)
        cv::resize(sample, sample_resized, input_geometry_);
    else
        sample_resized = sample;

    cv::Mat sample_float;
    if (num_channels_ == 3)
        sample_resized.convertTo(sample_float, CV_32FC3);
    else
        sample_resized.convertTo(sample_float, CV_32FC1);

    cv::split(sample_float, *input_channels);

    CHECK(reinterpret_cast<float*>(input_channels->at(0).data)
        == net_->input_blobs()[0]->cpu_data())
        << "Input channels are not wrapping the input layer of the network.";
}


static void on_Mouse(int event, int x, int y, int flags, void*)
{



    if (event == EVENT_LBUTTONUP || !(flags&EVENT_FLAG_LBUTTON))
    {
        previousPoint = cv::Point(-1,-1);
    }
    else
        if (event == EVENT_LBUTTONDOWN)
        {
            previousPoint = cv::Point(x, y);
        }
        else if (event == EVENT_MOUSEMOVE || (flags&EVENT_FLAG_LBUTTON))
        {
            cv::Point pt(x, y);
            if (previousPoint.x<0)
            {
                previousPoint = pt;
            }
            line(srcimage, previousPoint, pt, Scalar(255), 16, 8, 0);
            previousPoint = pt;
            imshow("result", srcimage);
        }

}


int main(int argc, char** argv)
{

    ::google::InitGoogleLogging(argv[0]);

#ifdef CPU_ONLY
    Caffe::set_mode(Caffe::CPU);
#else
    Caffe::set_mode(Caffe::GPU);
#endif

    string model_file = "lenet.prototxt";
    string trained_file = "lenet_iter_10000.caffemodel";
    Classifier classifier(model_file, trained_file);

    std::cout << "------directed by watersink------" << std::endl;
    std::cout << "------------enter:退出-----------" << std::endl;
    std::cout << "--------------1:还原-------------" << std::endl;
    std::cout << "-------------2:写数字------------" << std::endl;
    std::cout << "-----lhnows@qq.com-----" << std::endl;


    imshow("result", srcimage);
    setMouseCallback("result", on_Mouse, 0);
    while (1)
    {
        char c = (char)waitKey();
        if (c == 27)
            break;
        if (c=='1')
        {
            srcimageori.copyTo(srcimage);
            imshow("result", srcimage);
        }
        if (c == '2')
        {
            cv::Mat img;
            cv::resize(srcimage, img, cv::Size(28, 28));
            CHECK(!img.empty()) << "Unable to decode image " << std::endl;
            int  prediction = classifier.Classify(img);
            std::cout << "prediction:" << prediction << std::endl;
            imshow("result", srcimage);
        }
    }


    waitKey();
    return 0;

}

head.h

#include <caffe/common.hpp>
#include <caffe/layer.hpp>
#include <caffe/layer_factory.hpp>
#include <caffe/layers/input_layer.hpp>
#include <caffe/layers/inner_product_layer.hpp>
#include <caffe/layers/dropout_layer.hpp>
#include <caffe/layers/conv_layer.hpp>
#include <caffe/layers/relu_layer.hpp>
#include <caffe/layers/pooling_layer.hpp>
#include <caffe/layers/softmax_layer.hpp> 


namespace caffe
{

    extern INSTANTIATE_CLASS(InputLayer);
    extern INSTANTIATE_CLASS(InnerProductLayer);
    extern INSTANTIATE_CLASS(DropoutLayer);
    extern INSTANTIATE_CLASS(ConvolutionLayer);
    //REGISTER_LAYER_CLASS(Convolution);
    extern INSTANTIATE_CLASS(ReLULayer);
    //REGISTER_LAYER_CLASS(ReLU);
    extern INSTANTIATE_CLASS(PoolingLayer);
    //REGISTER_LAYER_CLASS(Pooling);
    extern INSTANTIATE_CLASS(SoftmaxLayer);
    //REGISTER_LAYER_CLASS(Softmax);

}

cmake.. & make

 $ cmake ..
-- The C compiler identification is AppleClang 8.1.0.8020042
-- The CXX compiler identification is AppleClang 8.1.0.8020042
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenCV: /usr/local (found version "3.2.0") 
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/liuhao/projects/caffeProjects/mnistTest/build


 $ make
Scanning dependencies of target mnistTest
[ 50%] Building CXX object CMakeFiles/mnistTest.dir/mnistTest.cpp.o
[100%] Linking CXX executable mnistTest
[100%] Built target mnistTest

输入./mnistTests 执行
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
LeNet-5神经网络 C源代码,这个的比较好,可以用gcc编译去跑,结合理论可以对深度学习有更深刻的了解 介绍 根据YANN LECUN的论文《Gradient-based Learning Applied To Document Recognition》设计的LeNet-5神经网络,C语言成,不依赖任何第三方库。 MNIST手写字符集初代训练识别率97%,多代训练识别率98%。 DEMO main.c文件为MNIST数据集的识别DEMO,直接编译即可运行,训练集60000张,测试集10000张。 项目环境 该项目为VISUAL STUDIO 2015项目,用VISUAL STUDIO 2015 UPDATE1及以上直接打开即可编译。采用ANSI C编,因此源码无须修改即可在其它平台上编译。 如果因缺少openmp无法编译,请将lenet.c中的#include和#pragma omp parallel for删除掉即可。 API #####批量训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 inputs: 要训练的多个图片对应unsigned char二维数组的数组,指向的二维数组的batchSize倍大小内存空间指针。在MNIST测试DEMO中二维数组为28x28,每个二维数组数值分别为对应位置图像像素灰度值 resMat:结果向量矩阵 labels:要训练的多个图片分别对应的标签数组。大小为batchSize batchSize:批量训练输入图像(二维数组)的数量 void TrainBatch(LeNet5 *lenet, image *inputs, const char(*resMat)[OUTPUT],uint8 *labels, int batchSize); #####单个训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 要训练的图片对应二维数组 resMat:结果向量矩阵 label: 要训练的图片对应的标签 void Train(LeNet5 *lenet, image input, const char(*resMat)[OUTPUT],uint8 label); #####预测 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 输入的图像的数据 labels: 结果向量矩阵指针 count: 结果向量个数 return 返回值为预测的结果 int Predict(LeNet5 *lenet, image input, const char(*labels)[LAYER6], int count); #####初始化 lenet: LeNet5的权值的指针,LeNet5神经网络的核心
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhnows

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值