From 81ac69fa9e3c10e8b357f8725fe60c503fe31fab Mon Sep 17 00:00:00 2001 From: xinyang Date: Sat, 20 Apr 2019 14:37:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8E=B0=E5=8F=AF=E4=BD=BF=E7=94=A8CNN?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E5=99=A8=E5=88=A4=E6=96=AD=E8=A3=85=E7=94=B2?= =?UTF-8?q?=E6=9D=BF=E5=8F=8A=E5=85=B6=E6=95=B0=E5=AD=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../armor_finder/classifier/classifier.h | 51 ++++ .../armor_finder/classifier/classifier.cpp | 269 ++++++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 armor/include/armor_finder/classifier/classifier.h create mode 100644 armor/src/armor_finder/classifier/classifier.cpp diff --git a/armor/include/armor_finder/classifier/classifier.h b/armor/include/armor_finder/classifier/classifier.h new file mode 100644 index 0000000..57b3bc6 --- /dev/null +++ b/armor/include/armor_finder/classifier/classifier.h @@ -0,0 +1,51 @@ +// +// Created by xinyang on 19-4-19. +// + +#ifndef _CLASSIFIER_H_ +#define _CLASSIFIER_H_ + +#include +#include +#include +#include +#include + +using namespace std; +using namespace Eigen; + +class Classifier { +private: + bool state; + + vector> conv1_w, conv2_w; + vector conv1_b, conv2_b; + MatrixXd fc1_w, fc2_w; + VectorXd fc1_b, fc2_b; + + vector> load_conv_w(const string &file); + vector load_conv_b(const string &file); + MatrixXd load_fc_w(const string &file); + VectorXd load_fc_b(const string &file); + + MatrixXd softmax(const MatrixXd &input); + MatrixXd relu(const MatrixXd &input); + vector> apply_bias(const vector> &input, const vector &bias); + vector> relu(const vector> &input); + vector> pool(const vector> &input, int size); + vector> pand(const vector> &input, int val); + MatrixXd conv(const MatrixXd &filter, const MatrixXd &input); + vector> conv2(const vector> &filter, const vector> &input); + MatrixXd flatten(const vector> &input); + +public: + explicit Classifier(const string &folder); + ~Classifier() = default; + + MatrixXd calculate(const vector> &input); + explicit operator bool() const; + int operator()(const cv::Mat &image); +}; + + +#endif //RUNCNN_CLASSIFIER_H diff --git a/armor/src/armor_finder/classifier/classifier.cpp b/armor/src/armor_finder/classifier/classifier.cpp new file mode 100644 index 0000000..b303375 --- /dev/null +++ b/armor/src/armor_finder/classifier/classifier.cpp @@ -0,0 +1,269 @@ +// +// Created by xinyang on 19-4-19. +// + +#include +#include +#include +#include + + +vector> Classifier::load_conv_w(const string &file){ + vector> result; + FILE *fp = fopen(file.data(), "r"); + if(fp == nullptr){ + LOGE("%s open fail!", file.data()); + state = false; + return result; + } + int channel_in, channel_out, row, col; + fscanf(fp, "%d %d %d %d", &channel_in, &channel_out, &row, &col); + for(int o=0; o sub; + for(int i=0; i Classifier::load_conv_b(const string &file){ + vector result; + FILE *fp = fopen(file.data(), "r"); + if(fp == nullptr){ + LOGE("%s open fail!", file.data()); + state = false; + return result; + } + int len; + fscanf(fp, "%d", &len); + for(int i=0; i> Classifier::pool(const vector> &input, int size){ + vector> output; + for(int sample=0; sample sub; + for (int channel = 0; channel < input[0].size(); channel++) { + MatrixXd tmp(input[0][0].rows() / size, input[0][0].cols() / size); + for (int row = 0; row < input[0][0].rows() / size; row++) { + for (int col = 0; col < input[0][0].cols() / size; col++) { + double val = 0; + for (int x = 0; x < size; x++) { + for (int y = 0; y < size; y++) { + val += input[sample][channel](row * size + x, col * size + y); + } + } + tmp(row, col) = val / size / size; + } + } + sub.emplace_back(tmp); + } + output.emplace_back(sub); + } + return output; +} + +vector> Classifier::apply_bias(const vector> &input, const vector &bias){ + assert(input[0].size()==bias.size()); + vector> result; + for(int samples=0; samples sub; + for(int channels=0; channels0)?(val):(0); + }); +} + +vector> Classifier::relu(const vector> &input){ + vector> result; + for(int samples=0; samples sub; + for(int channels=0; channels> Classifier::pand(const vector> &input, int val){ + vector> result; + for(int sample=0; sample sub; + for(int channels=0; channels> Classifier::conv2(const vector> &filter, const vector> &input){ + if(filter.size() != input[0].size()){ + LOGE("shape du not match, which is filter.size=%d, input[0].size()=%d", filter.size(), input[0].size()); + exit(-1); + } + vector> result; + int result_rows = input[0][0].rows()-filter[0][0].rows()+1; + int result_cols = input[0][0].cols()-filter[0][0].cols()+1; + for(int col=0; col sub; + for(int row=0; row> &input){ + int ones = input[0][0].rows()*input[0][0].cols(); + int channels = input[0].size(); + int samples = input.size(); + int row = input[0][0].rows(); + int col = input[0][0].cols(); + MatrixXd output(channels*ones,samples); + for(int s=0; s> &input) { + vector> conv1_result = relu(apply_bias(conv2(conv1_w, input), conv1_b)); + vector> pool1_result = pool(conv1_result, 2); + vector> conv2_result = relu(apply_bias(conv2(conv2_w, pool1_result), conv2_b)); + vector> pool2_result = pool(conv2_result, 2); + MatrixXd flattened = flatten(pool2_result); + MatrixXd y1 = fc1_w * flattened; + y1.colwise() += fc1_b; + MatrixXd fc1 = relu(y1); + MatrixXd y2 = fc2_w * fc1; + y2.colwise() += fc2_b; + MatrixXd fc2 = softmax(y2); + return fc2; +} + +Classifier::operator bool() const { + return state; +} + +int Classifier::operator()(const cv::Mat &image) { + MatrixXd x; + cv2eigen(image, x); + vector sub = {x}; + vector> in = {sub}; + MatrixXd result = calculate(in); + MatrixXd::Index minRow, minCol; + result.maxCoeff(&minRow, &minCol); + return minRow; +} \ No newline at end of file