Cómo llamar a Caffe para clasificar imágenes en el programa
Capa{
Nombre: "Mis datos"
Tipo: MEMORY_DATA
Parte superior: "Datos"
Parte superior: "Etiqueta"
Parámetros de conversión {
Escala: 0,00390625
}
Parámetros de datos de memoria{
Tamaño de lote: 10
Canal: 1
Alto: 24
Ancho: 24
}
}
Los cuatro parámetros en Memory_data_param deben configurarse aquí. Los parámetros correspondientes se pueden encontrar en el archivo caffe.proto del código fuente.
Ahora, podemos diseñar una clase clasificadora para encapsularla:
#ifndef CAFFE_CLASSIFIER_H
#define coffee_classifier_H
# include lt string gt
# incluir ltvector gt
#Incluir "caffe/net.hpp"
#Incluir "caffe/data_layers.hpp"
# incluir ltopencv 2/core HPP gt;
Usar cv::Mat;
Espacio de nombres caffe {
Plantilla lttypename Dtype gt
clasificador de categoría {
Público:
clasificador explícito (archivo de parámetros de amp de cadena constante, archivo de peso de amp de cadena constante);
Prueba de tipo de datos (imagen de vector ltMat gt amp, vector ltint gt amp label, int iter_num);
Clasificador virtual(){}
inline share_ptr ltNet ltDtype gt gtnet(){ return net_;}
predicción nula (vector ltMat gt amp imagen, vector ltint gt* etiqueta);
predicción de vacío(vector ltDtype gt amp datos, vector ltint gt* etiqueta, int num);
void extract_feature(vector lt ; Mat gt amp imagen, vector lt vector ltDtype gt gt* out);
Protegido:
shared _ ptr ltNet ltDtype gt gtnet _;
MemoryDataLayer ltDtype; gt* m _ capa _
int lote _ tamaño _
int canales _;
int alto _;
int ancho _ ;
DISABLE_COPY_AND_ASSIGN(clasificador);
};
}//Espacio de nombres
# endif//coffee_classifier_H
En el constructor, pasamos el archivo de definición del modelo (. prototxt) y el archivo de modelo entrenado (.caffemodel), y apunte m_layer_ a la capa de datos de memoria en Net, de modo que las funciones AddMatVector y Reset en la capa de datos de memoria se puedan llamar más tarde para agregar datos.
# incluir ltcstdio gt
# incluir lt algoritmo gt
# incluir lt string gt
# incluir ltvector gt
#Contiene "caffe/net.hpp"
#Contiene "caffe/proto/caffe.pb.h"
#Contiene "caffe/util/io.hpp "
#Incluye " caffe/util/math_functions.hpp "
#Incluye " caffe/util/upgrade_proto.hpp "
#Incluye " caffe_classifier.h "
Espacio de nombres caffe {
Plantilla lttypename Dtype gt
Clasificador ltDtype gt clasificador (archivo de parámetros amp de cadena constante, archivo ampweights_file de cadena constante): net_()
{
net_. Reset(new net ltDtype gt(param_file, TEST));
net _- gt; CopyTrainedLayersFrom(weights _ file
//m _ capa _ = (memoria capa de datos lt); ;Dtype gt*)net _- gt;layer_by_name("mnist"). get();
m_layer_=(capa de datos de memoria lt;Dtype gt*)net_- gt;layers()[0].
get();
batch_size_ = m_layer_->batch_size();
channel_ = m_layer_- gt;channel();
altura _ = m _ capa _- gt; altura();
ancho _ = m _ capa _- gt;
}
Plantilla lttypename Dtype gt
p>
Clasificador de tipo de datos ltDtype gt* prueba(vector ltMat gt amp imagen, vector ltint gt amp etiqueta, entero)
{
m _ capa _- gt;AddMatVector (imagen, etiqueta);
//
int iteraciones = iter _ num
Vector ltBlob ltDtype gt* gtbottom _ vec
Identificación de salida de la puntuación de la prueba Vector ltint gt;
Vector ltDtype gt test_score;
dtype loss = 0;
for( int I = 0; i lt número de iteración ; i) {
Dtype iter _ loss
Vector constante ltBlob ltDtype gt* gt amp result=
net _ - gt forward (bottom _ vec amp; ; ITER _ pérdida);
pérdida = ITER _ pérdida;
int idx = 0;
for( int j = 0; j ltresult . tamaño( ); j) {
const Dtype * resultado _ vec = resultado[j]- gt; CPU _ data()
for (int k = 0; k lt resultado [ j] - gt; count(); k, idx) {
puntuación const Dtype = resultado _ vec[k];
if (i == 0) {
prueba_puntuación.push_back(puntuación);
prueba_puntuación_salida_id. >
test_score[idx] = puntuación;
}
Cadena ampoutput_name = net_- gt; blob_names ()[
net_- gt;output_blob_indexes( )[j]];
Registro(información) lt lt" Lote " lt lti lt lt", " lt ltNombre de salida lt lt" = " lt lt puntuación
}
}
}
pérdida /=Número de iteraciones ;
Registro(información) lt lt"Pérdida:" lt ltLoss;
Pérdida de retorno;
}
Plantilla lttypename Dtype gt
clasificador vacío ltDtype gt* predicción (vector l
tMat gt amp imagen, vector ltint gt*label)
{
int original_length = imágenes.size().
if(original_length == 0)
Return;
int valid _ longitud = original _ longitud/lote _ tamaño _ * lote _ tamaño _; /p>
if(longitud_original!=longitud válida)
{
longitud _ válida = lote _ tamaño _;
for(int i = longitud original; i lt longitud efectiva; i )
{
images.push_back(images[0]). clone());
}
}
Vector ltint gt etiqueta válida, etiqueta prevista.
valid_labels.resize(valid_length,0);
m_layer_-gt;AddMatVector(images,valid_labels);
Vector ltBlob ltDtype gt* gtbottom _ vec
for(int I = 0;iltvalid_length/batch_size_;i)
{
constante Vector ltBlob ltDtype gt* gt ampresult = net _- gt forward( inferior _ vec);
const Dtype * resultado _ vec = resultado[1]- gt; CPU _ data()
for(int j = 0; j lt resultado [ 1]- gt; count(); j )
{
etiquetas _ predichas .
}
if (longitud_original!=longitud efectiva)
{ p>
images . erase(imágenes . comenzar() longitud_original, imágenes . end());
}
Etiqueta - gt; resize(original_length, 0) ;
STD::copy(predicted_labels.begin(), predicted_labels.begin() original_length,labels-gt;begin());
}
Plantilla lttypename Dtype gt
clasificador vacío ltDtype gt* predicción (vector ltDtype gt amp datos, vector ltint gt* etiqueta, entero)
{
int tamaño = canales _ * alto _ * ancho _;
CHECK_EQ(datos .size(), num * tamaño);
int original _length = num
if(original_length == 0)
Return;
int valid_length = original_longitud/lote_tamaño_ * lote_tamaño_;
int valid_length = original_length/batch_size_*batch_size_;
p>
if (longitud_original! =longitud válida)
{
longitud_valida = tamaño_lote_;
for(int i =longitud original;iltlongitud válida;i)
{
for(int j = 0; j lt tamaño; j )
datos . push _ back(0); p>}
Vector ltint gt predict_label;
Dtype * etiqueta _ = nuevo Dtype[valid _ length];
memset(label_, 0
, longitud _ válida);
m _ capa _- gt; Reset(data.data(), etiqueta_, longitud _ válida
Vector ltBlob ltDtype gt* gtbottom _ vec);
for(int I = 0; i ltvalid_length/batch_size_;i)
{
Vector constante ltBlob ltDtype gt* gt ampresult = net _- gt; forward(bottom _ vec);
const Dtype * resultado _ vec = resultado[1]- gt CPU _ data()
for(int j = 0; j ltresult; [1]- gt; count(); j )
{
predicho _ etiquetas . }
}
if (longitud_original!=longitud válida)
{
datos borrar (datos . comenzar() original _. longitud * tamaño, datos final());
}
eliminar[] tag_;
tag-gt ;resize(original_length, 0);
STD::copy(predicted_labels.begin(),predicted_labels.begin() longitud_original,labels-gt;begin());
p>}
Plantilla lttypename Dtype gt
clasificador vacío ltDtype gt* extracto _ característica(vector ltMat gt amp imagen, vector lt vector ltDtype gt gt*out)
{
int longitud_original = imágenes.tamaño().
if(original_length == 0)
Return;
int valid _ longitud = original _ longitud/lote _ tamaño _ * lote _ tamaño _; /p>
if(longitud_original!=longitud válida)
{
longitud _ válida = lote _ tamaño _;
for(int i = longitud original; i lt longitud efectiva; i )
{
images.push_back(images[0]).
clone());
}
}
Vector ltint gt etiqueta válida;
valid_etiquetas_resize(valid_length. , 0);
m _ capa _- gt; AddMatVector(imágenes, etiquetas válidas
Vector ltBlob ltDtype gt* gtbottom _ vec
out); - gt;clear();
for(int I = 0;iltvalid_length/batch_size_;i)
{
Vector constante ltBlob ltDtype gt* gt ampresult = net _- gt forward(bottom _ vec);
const Dtype * resultado _ vec = resultado[0]- gt; CPU _ data(); = resultado[0]- gt; recuento(1);
for(int j = 0; j lt resultado[0]- gt; num(); j ) p>
{
const Dtype * ptr = resultado _ vec j * dim;
Vector ltDtype gtone _;
for(int k = 0 ;k ltdim; k)
a_. push_back(ptr[k]);
out- gt; push_back(one_);
}
}
if(original_length !=longitud efectiva)
{
images . erase(images . comenzar() original _ longitud, imágenes . end()
out- gt); ; borrar(salida- gt; comenzar() longitud_origen, salida->; final()
}
}
INSTANTIATE_CLASS(clasificador);
} //Namespace Coffee
Debido a que la cantidad de datos agregados debe ser un múltiplo entero de tamaño_de_lote, usamos relleno al agregar el método de datos.
CHECK_EQ(num batch_size_, 0) lt;
"Los datos agregados deben ser un múltiplo del tamaño del lote." //AddMatVector
En el archivo de modelo Al final, cambiamos la capa de pérdida durante el entrenamiento a la capa argmax:
Capa {
Nombre: "Prediction"
Tipo: ARGMAX
p>Abajo: "prob"
Arriba: "Predicción"
}