Updated classification example

pull/265/head
Vitaliy Lyudvichenko 10 years ago
parent 6548839454
commit db4ff2172a
  1. 2
      modules/dnn/include/opencv2/dnn/blob.hpp
  2. 2
      modules/dnn/include/opencv2/dnn/dict.hpp
  3. 281
      modules/dnn/samples/bvlc_alexnet.prototxt
  4. 27
      modules/dnn/samples/classify_with_googlenet.cpp
  5. BIN
      modules/dnn/samples/space_shuttle.jpg
  6. 1000
      modules/dnn/samples/synset_words.txt
  7. 18
      modules/dnn/scripts/download_model.py
  8. 6
      modules/dnn/src/caffe_importer.cpp
  9. 6
      modules/dnn/src/dnn.cpp
  10. 2
      modules/dnn/src/layers/concat_layer.cpp
  11. 2
      modules/dnn/src/layers/convolution_layer.cpp
  12. 2
      modules/dnn/src/layers/elementwise_layers.cpp
  13. 4
      modules/dnn/src/layers/reshape_layer.cpp
  14. 2
      modules/dnn/src/layers/slice_layer.cpp
  15. 23
      modules/dnn/test/cnpy.cpp
  16. 12
      modules/dnn/test/cnpy.h
  17. 2
      modules/dnn/test/test_layers.cpp

@ -83,7 +83,7 @@ namespace dnn
@note Unlike ::xsize, if \p axis points to non-existing dimension then an error will be generated.
*/
int size(int axis) const;
/** @brief returns number of elements
@param startAxis starting axis (inverse indexing can be used)
@param endAxis ending (excluded) axis

@ -16,7 +16,7 @@ struct DictValue
DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer<int64,1>) { (*pi)[0] = p; }
DictValue(double p) : type(Param::REAL), pd(new AutoBuffer<double,1>) { (*pd)[0] = p; }
DictValue(const String &p) : type(Param::STRING), ps(new AutoBuffer<String,1>) { (*ps)[0] = p; }
template<typename TypeIter>
static DictValue arrayInt(TypeIter begin, int size);
template<typename TypeIter>

@ -1,281 +0,0 @@
name: "AlexNet"
input: "data"
input_dim: 10
input_dim: 3
input_dim: 227
input_dim: 227
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 96
kernel_size: 11
stride: 4
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
layer {
name: "norm1"
type: "LRN"
bottom: "conv1"
top: "norm1"
lrn_param {
local_size: 5
alpha: 0.0001
beta: 0.75
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "norm1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 2
kernel_size: 5
group: 2
}
}
layer {
name: "relu2"
type: "ReLU"
bottom: "conv2"
top: "conv2"
}
layer {
name: "norm2"
type: "LRN"
bottom: "conv2"
top: "norm2"
lrn_param {
local_size: 5
alpha: 0.0001
beta: 0.75
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "norm2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "conv3"
type: "Convolution"
bottom: "pool2"
top: "conv3"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 384
pad: 1
kernel_size: 3
}
}
layer {
name: "relu3"
type: "ReLU"
bottom: "conv3"
top: "conv3"
}
layer {
name: "conv4"
type: "Convolution"
bottom: "conv3"
top: "conv4"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 384
pad: 1
kernel_size: 3
group: 2
}
}
layer {
name: "relu4"
type: "ReLU"
bottom: "conv4"
top: "conv4"
}
layer {
name: "conv5"
type: "Convolution"
bottom: "conv4"
top: "conv5"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
convolution_param {
num_output: 256
pad: 1
kernel_size: 3
group: 2
}
}
layer {
name: "relu5"
type: "ReLU"
bottom: "conv5"
top: "conv5"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "conv5"
top: "pool5"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "fc6"
type: "InnerProduct"
bottom: "pool5"
top: "fc6"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 4096
}
}
layer {
name: "relu6"
type: "ReLU"
bottom: "fc6"
top: "fc6"
}
layer {
name: "drop6"
type: "Dropout"
bottom: "fc6"
top: "fc61"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc7"
type: "InnerProduct"
bottom: "fc61"
top: "fc7"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 4096
}
}
layer {
name: "relu7"
type: "ReLU"
bottom: "fc7"
top: "fc7"
}
layer {
name: "drop7"
type: "Dropout"
bottom: "fc7"
top: "fc71"
dropout_param {
dropout_ratio: 0.5
}
}
layer {
name: "fc8"
type: "InnerProduct"
bottom: "fc71"
top: "fc8"
param {
lr_mult: 1
decay_mult: 1
}
param {
lr_mult: 2
decay_mult: 0
}
inner_product_param {
num_output: 1000
}
}
layer {
name: "prob"
type: "Softmax"
bottom: "fc8"
top: "prob"
}

@ -25,53 +25,52 @@ std::vector<String> CLASES_NAMES;
void initClassesNames()
{
std::ifstream fp("ILSVRC2012_synsets.txt");
std::ifstream fp("synset_words.txt");
CV_Assert(fp.is_open());
std::string name;
while (!fp.eof())
{
std::getline(fp, name);
CLASES_NAMES.push_back(name);
if (name.length())
CLASES_NAMES.push_back( name.substr(name.find(' ')+1) );
}
CV_Assert(CLASES_NAMES.size() == 1000);
fp.close();
}
int main(void)
int main(int argc, char **argv)
{
Net net;
{
Ptr<Importer> importer = createCaffeImporter("bvlc_alexnet.prototxt", "bvlc_alexnet.caffemodel");
Ptr<Importer> importer = createCaffeImporter("bvlc_googlenet.prototxt", "bvlc_googlenet.caffemodel");
importer->populateNet(net);
}
Mat img = imread("zebra.jpg");
String filename = (argc > 1) ? argv[1] : "space_shuttle.jpg";
Mat img = imread(filename);
CV_Assert(!img.empty());
cvtColor(img, img, COLOR_BGR2RGB);
img.convertTo(img, CV_32F);
resize(img, img, Size(227, 227));
subtract(img, cv::mean(img), img);
Blob imgBlob(img);
net.setBlob("data", imgBlob);
net.setBlob(".data", imgBlob);
net.forward();
Blob probBlob = net.getBlob("prob");
ClassProb bc = getMaxClass(probBlob);
Blob prob = net.getBlob("prob");
ClassProb bc = getMaxClass(prob);
initClassesNames();
std::string className = (bc.first < (int)CLASES_NAMES.size()) ? CLASES_NAMES[bc.first] : "unnamed";
std::cout << "Best class:";
std::cout << " #" << bc.first;
std::cout << " (from " << probBlob.total(1) << ")";
std::cout << " (from " << prob.total(1) << ")";
std::cout << " \"" + className << "\"";
std::cout << std::endl;
std::cout << "Prob: " << bc.second * 100 << "%" << std::endl;
return 0;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because it is too large Load Diff

@ -21,15 +21,15 @@ def reporthook(count, block_size, total_size):
duration = max(1, time.time() - start_time)
if int(duration) == int(prev_duration):
return
progress_size = int(count * block_size)
speed = int(progress_size / (1024 * duration))
percent = int(count * block_size * 100 / total_size)
sys.stdout.write("\r...%d%%, %d MB, %d KB/s, %d seconds passed" %
sys.stdout.write("\r...%d%%, %d MB, %d KB/s, %d seconds passed" %
(percent, progress_size / (1024 * 1024), speed, duration))
sys.stdout.flush()
prev_duration = duration
# Function for checking SHA1.
def model_checks_out(filename, sha1):
@ -41,14 +41,14 @@ def model_download(filename, url, sha1):
if os.path.exists(filename) and model_checks_out(filename, sha1):
print("Model {} already exists.".format(filename))
return
# Download and verify model.
urllib.urlretrieve(url, filename, reporthook)
print model_checks_out(filename, sha1)
if not model_checks_out(filename, sha1):
print("ERROR: model {} did not download correctly!".format(url))
sys.exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Downloading trained model binaries.")
parser.add_argument("download_list")
@ -58,22 +58,22 @@ if __name__ == '__main__':
if not test_dir:
print "ERROR: OPENCV_TEST_DATA_PATH environment not specified"
sys.exit(1)
try:
with open(args.download_list, 'r') as f:
models_to_download = json.load(f)
except:
print "ERROR: Can't pasrse {}".format(args.download_list)
sys.exit(1)
for model_name in models_to_download:
model = models_to_download[model_name]
dst_dir = os.path.join(test_dir, os.path.dirname(model['file']))
dst_file = os.path.join(test_dir, model['file'])
if not os.path.exists(dst_dir):
print "ERROR: Can't find module testdata path '{}'".format(dst_dir)
sys.exit(1)
print "Downloading model '{}' to {} from {} ...".format(model_name, dst_file, model['url'])
model_download(dst_file, model['url'], model['sha1'])

@ -202,7 +202,7 @@ namespace
struct BlobNote
{
BlobNote(const std::string &_name, int _layerId, int _outNum) :
BlobNote(const std::string &_name, int _layerId, int _outNum) :
name(_name.c_str()), layerId(_layerId), outNum(_outNum) {}
const char *name;
@ -237,7 +237,7 @@ namespace
extractBinaryLayerParms(layer, layerParams);
int id = dstNet.addLayer(name, type, layerParams);
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
addInput(layer.bottom(inNum), id, inNum, dstNet, addedBlobs);
@ -249,7 +249,7 @@ namespace
void addOutput(const caffe::LayerParameter &layer, int layerId, int outNum, std::vector<BlobNote> &addedBlobs)
{
const std::string &name = layer.top(outNum);
bool haveDups = false;
for (int idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
{

@ -32,7 +32,7 @@ struct LayerPin
LayerPin(int layerId = -1, int outputId = -1)
: lid(layerId), oid(outputId) {}
bool valid() const
{
return (lid >= 0 && oid >= 0);
@ -104,7 +104,7 @@ private:
struct Net::Impl
{
Impl()
{
{
//allocate fake net input layer
netInputLayer = Ptr<NetInputLayer>(new NetInputLayer());
LayerData &inpl = layers.insert( make_pair(0, LayerData()) ).first->second;
@ -171,7 +171,7 @@ struct Net::Impl
LayerData& getLayerData(int id)
{
MapIdToLayerData::iterator it = layers.find(id);
if (it == layers.end())
CV_Error(Error::StsError, "Layer with requested id=" + toString(id) + " not found");

@ -28,7 +28,7 @@ namespace dnn
void ConcatLayer::allocate(const std::vector<Blob *> &inputs, std::vector<Blob> &outputs)
{
CV_Assert(inputs.size() > 0);
int refType = inputs[0]->type();
BlobShape refShape = inputs[0]->shape();
CV_Assert(axis < refShape.dims());

@ -197,7 +197,7 @@ namespace dnn
for (int g = 0; g < group; g++)
{
Mat dstMat(inpGroupCn, inpH*inpW, decnBlob.type(), decnBlob.ptrRaw(n, g*inpGroupCn));
if (is1x1())
colMat = dstMat;

@ -84,7 +84,7 @@ namespace dnn
return tanh(x);
}
};
struct SigmoidFunctor
{
SigmoidFunctor(LayerParams&) {}

@ -8,7 +8,7 @@ namespace dnn
//TODO: Extend cv::Mat::reshape method
class ReshapeLayer : public Layer
{
{
public:
ReshapeLayer(LayerParams &params);
@ -121,7 +121,7 @@ void ReshapeLayer::computeOutputShape(int startAxis, int endAxis, BlobShape &inp
Ptr<Layer> createFlattenLayer(LayerParams&)
{
LayerParams params;
int shapeDesc[] = {0, -1};
params.set("dim", DictValue::arrayInt(shapeDesc, 2));

@ -45,7 +45,7 @@ void SliceLayer::allocate(const std::vector<Blob*> &inputs, std::vector<Blob> &o
int axis = inpBlob.canonicalAxis(inAxis);
int axisSize = inpBlob.size(axis);
BlobShape inpShape = inpBlob.shape();
if (slicePoints.size()) //divide blob with respect to passed parameters
{
std::vector<int> outAxisSize;

@ -57,9 +57,9 @@ template<> std::vector<char>& cnpy::operator+=(std::vector<char>& lhs, const cha
return lhs;
}
void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order) {
void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order) {
char buffer[256];
size_t res = fread(buffer,sizeof(char),11,fp);
size_t res = fread(buffer,sizeof(char),11,fp);
if(res != 11)
throw std::runtime_error("parse_npy_header: failed fread");
std::string header = fgets(buffer,256,fp);
@ -85,7 +85,7 @@ void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& sh
}
//endian, word size, data type
//byte order code | stands for not applicable.
//byte order code | stands for not applicable.
//not sure when this applies except for byte array
loc1 = header.find("descr")+9;
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
@ -134,7 +134,7 @@ cnpy::NpyArray load_the_npy_file(FILE* fp) {
arr.word_size = word_size;
arr.shape = std::vector<unsigned int>(shape,shape+ndims);
delete[] shape;
arr.data = new char[size*word_size];
arr.data = new char[size*word_size];
arr.fortran_order = fortran_order;
size_t nread = fread(arr.data,word_size,size,fp);
if(nread != size)
@ -148,7 +148,7 @@ cnpy::npz_t cnpy::npz_load(std::string fname) {
if(!fp) printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
assert(fp);
cnpy::npz_t arrays;
cnpy::npz_t arrays;
while(1) {
std::vector<char> local_header(30);
@ -166,7 +166,7 @@ cnpy::npz_t cnpy::npz_load(std::string fname) {
if(vname_res != name_len)
throw std::runtime_error("npz_load: failed fread");
//erase the lagging .npy
//erase the lagging .npy
varname.erase(varname.end()-4,varname.end());
//read in the extra field
@ -182,7 +182,7 @@ cnpy::npz_t cnpy::npz_load(std::string fname) {
}
fclose(fp);
return arrays;
return arrays;
}
cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
@ -191,7 +191,7 @@ cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
if(!fp) {
printf("npz_load: Error! Unable to open file %s!\n",fname.c_str());
abort();
}
}
while(1) {
std::vector<char> local_header(30);
@ -205,7 +205,7 @@ cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) {
//read in the variable name
unsigned short name_len = *(unsigned short*) &local_header[26];
std::string vname(name_len,' ');
size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp);
size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp);
if(vname_res != name_len)
throw std::runtime_error("npz_load: failed fread");
vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy
@ -237,7 +237,7 @@ cnpy::NpyArray cnpy::npy_load(std::string fname) {
if(!fp) {
printf("npy_load: Error! Unable to open file %s!\n",fname.c_str());
abort();
abort();
}
NpyArray arr = load_the_npy_file(fp);
@ -245,6 +245,3 @@ cnpy::NpyArray cnpy::npy_load(std::string fname) {
fclose(fp);
return arr;
}

@ -27,7 +27,7 @@ namespace cnpy {
bool fortran_order;
void destruct() {delete[] data;}
};
struct npz_t : public std::map<std::string, NpyArray>
{
void destruct()
@ -49,14 +49,14 @@ namespace cnpy {
template<typename T> std::vector<char>& operator+=(std::vector<char>& lhs, const T rhs) {
//write in little endian
for(char byte = 0; byte < sizeof(T); byte++) {
char val = *((char*)&rhs+byte);
char val = *((char*)&rhs+byte);
lhs.push_back(val);
}
return lhs;
}
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const std::string rhs);
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const char* rhs);
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const std::string rhs);
template<> std::vector<char>& operator+=(std::vector<char>& lhs, const char* rhs);
template<typename T> std::string tostring(T i, int = 0, char = ' ') {
@ -131,7 +131,7 @@ namespace cnpy {
if(fp) {
//zip file exists. we need to add a new npy file to it.
//first read the footer. this gives us the offset and size of the global header
//then read and store the global header.
//then read and store the global header.
//below, we will write the the new data at the start of the global header then append the global header and footer below it
unsigned int global_header_size;
parse_zip_footer(fp,nrecs,global_header_size,global_header_offset);
@ -201,7 +201,7 @@ namespace cnpy {
footer += (unsigned int) (global_header_offset + nbytes + local_header.size()); //offset of start of global headers, since global header now starts after newly written array
footer += (unsigned short) 0; //zip file comment length
//write everything
//write everything
fwrite(&local_header[0],sizeof(char),local_header.size(),fp);
fwrite(&npy_header[0],sizeof(char),npy_header.size(),fp);
fwrite(data,sizeof(T),nels,fp);

@ -95,7 +95,7 @@ TEST(Layer_Reshape_Split_Slice_Test, Accuracy)
net.setBlob(".input", input);
net.forward();
Blob output = net.getBlob("output");
input.fill(shape, CV_32F, inputMat.data);
normAssert(input, output);
}

Loading…
Cancel
Save