caffe接口中python代码和c++代码的转换
2018-01-31 14:59
423 查看
caffe使用别人训练好的模型
我觉得都是一样的套路,不管是python还是c++
掌握好步骤流程就行
加载网络结构流程
_1、设置gpu或者cpu模式
2、设置gpu设备号
3、加载网络结构,caffeModel和prototxt文件
4、处理输入图片,例如减去均值和归一化操作
5、前向传播
6、处理计算之后的结果_
|——————————————————————————
|—–从上面的python代码中可以看出完整的加载模型流程
|—–而使用c++会有几点需要注意的地方
|——————————————————————————
几个不同的地方
_1,将待测试图片加载进网络中
2,运算完成之后取出数据_
python中写法比较简单,按照套路直接写
加载待测图片
从前向传播之后取最后的检测结果
我觉得都是一样的套路,不管是python还是c++
掌握好步骤流程就行
加载网络结构流程
_1、设置gpu或者cpu模式
2、设置gpu设备号
3、加载网络结构,caffeModel和prototxt文件
4、处理输入图片,例如减去均值和归一化操作
5、前向传播
6、处理计算之后的结果_
#python代码 #ssd mobileNet检测图片 import numpy as np import sys,os import cv2 caffe_root = '/home/ssd/caffe/' sys.path.insert(0, caffe_root + 'python') import caffe import time net_file= 'deploy.prototxt' caffe_model= 'tr.caffemodel' test_dir = "/home/qwe/Desktop/12" if not os.path.exists(caffe_model): print("MobileNetSSD_deploy.affemodel does not exist,") print("use merge_bn.py to generate it.") exit() caffe.set_mode_gpu() caffe.set_device(0) net = caffe.Net(net_file,caffe_model,caffe.TEST) CLASSES = ('background', 'obj') def preprocess(src): img = cv2.resize(src, (512,256)) img = img - 127.5 img = img * 0.007843 return img def postprocess(img, out): h = img.shape[0] w = img.shape[1] box = out['detection_out'][0,0,:,3:7] * np.array([w, h, w, h]) cls = out['detection_out'][0,0,:,1] conf = out['detection_out'][0,0,:,2] return (box.astype(np.int32), conf, cls) def detect(imgfile): origimg = cv2.imread(imgfile) img = preprocess(origimg) img = img.astype(np.float32) img = img.transpose((2, 0, 1)) start_time = time.time() net.blobs['data'].data[...] = img out = net.forward() box, conf, cls = postprocess(origimg, out) pro_time = time.time() - start_time print('use time: ' + str(pro_time) + 's') for i in range(len(box)): p1 = (box[i][0], box[i][1]) p2 = (box[i][2], box[i][3]) cv2.rectangle(origimg, p1, p2, (0,255,0)) p3 = (max(p1[0], 15), max(p1[1], 15)) title = "%s:%.2f" % (CLASSES[int(cls[i])], conf[i]) cv2.putText(origimg, title, p3, cv2.FONT_ITALIC, 0.6, (0, 255, 0), 1) cv2.imshow("SSD", origimg) k = cv2.waitKey(0) & 0xff #Exit if ESC pressed if k == 27 : return False return True for f in os.listdir(test_dir): if detect(test_dir + "/" + f) == False: break
|——————————————————————————
|—–从上面的python代码中可以看出完整的加载模型流程
|—–而使用c++会有几点需要注意的地方
|——————————————————————————
//-------ssd.h class Detector { public: Detector(const string& model_file,const string& weights_file); std::vector<std::vector<float> > Detect(const cv::Mat& _img); private: boost::shared_ptr<Net<float> > net_; };
//------ssd.cpp Detector::Detector(const string &model_file, const string &weights_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(weights_file); } std::vector<std::vector<float> >Detector::Detect(const cv::Mat &_img) { cv::Mat img = _img.clone(); Blob<float>* inputBlob = net_->input_blobs()[0]; int width = inputBlob->width(); //网络规定的输入图片的宽度和高度 int height = inputBlob->height(); cv::resize(img,img,cv::Size(width,height));//将测试图片进行调整大小 img.convertTo(img, CV_32FC3); //转为浮点图 img = (img - 127.5) * 0.007843; float* data = inputBlob->mutable_cpu_data(); //将图片的像素值,复制进网络的输入Blob for (int k = 0; k<3; ++k){ for (int i = 0; i<height; ++i){ for (int j = 0; j<width; ++j){ int index = (k*height + i)*width + j; //获取偏移量 data[index] = img.at<Vec3f>(i, j)[k]; } } } vector<Blob<float>* > inputs(1, inputBlob); //const vector<Blob<float>* >& outputBlobs = net_->Forward(inputs); //进行前向传播,并返回最后一层的blob const vector<Blob<float>* >& outputBlobs = net_->Forward(); //进行前向传播,并返回最后一层的blob Blob<float>* outputBlob = outputBlobs[0]; //输出blob const float* result = outputBlob->cpu_data(); vector<vector<float> > detections; for (int i = 0; i<outputBlob->count(); ++i) //将输出blob里的特征数值,拷贝到vector里并返回 { if (result[0] == -1) { // Skip invalid detection. result += 7; continue; } vector<float> detection(result, result + 7); detections.push_back(detection); result += 7; } return detections; }
几个不同的地方
_1,将待测试图片加载进网络中
2,运算完成之后取出数据_
python中写法比较简单,按照套路直接写
加载待测图片
#python 代码 #---------------------------- #加载待测图片 origimg = cv2.imread(imgfile) #将图片减去均值,归一化处理 img = cv2.resize(src, (512,256)) img = img - 127.5 img = img * 0.007843 #将图片转换成float类型 img = img.astype(np.float32) img = img.transpose((2, 0, 1)) #将图片内容送进网络中进行前向传播 net.blobs['data'].data[...] = img #前向传播 out = net.forward()
/*c++代码 -------------------------------------*/ //opencv 读取图片文件 cv::Mat img = cv::imread(fileName); Blob<float>* inputBlob = net_->input_blobs()[0]; //网络规定的输入图片的宽度和高度 int width = inputBlob->width(); int height = inputBlob->height(); cv::resize(img,img,cv::Size(width,height));//将测试图片进行调整大小 img.convertTo(img, CV_32FC3); //转为浮点图 img = (img - 127.5) * 0.007843; //减去均值,归一化图像 /*减均值也可以使用cv::subtract函数,例如: cv::Mat mean(height,width,image.type(),cv::Scalar(102.9801,115,122.77); cv::Mat normalized; cv::subtract(image,mean,normalized); */ //------ //将图片加载进网络结构前向传播 float* data = inputBlob->mutable_cpu_data(); //将图片的像素值,复制进网络的输入Blob for (int k = 0; k<3; ++k) { for (int i = 0; i<height; ++i){ for (int j = 0; j<width; ++j){ int index = (k*height + i)*width + j; //获取偏移量 data[index] = img.at<Vec3f>(i, j)[k]; } } } /*也可以写成下面的形式 std::vector<cv::Mat> input_channels; float* input_data = inputBlob->mutable_cpu_data(); for (int i = 0; i < inputBlob->channels(); ++i) { cv::Mat channel(height, width, CV_32FC1, input_data); input_channels->push_back(channel); input_data += width * height; } cv::split(img, input_channels); */ //前向传播,直接取最后一层输出结果 const vector<Blob<float>* >& outputBlobs = net_->Forward(); //这样的写法要注意网络结构最后是否有多个分支,如果是多个分支,则会导致最后的结果将多个分支的结果融合在一起,不好区分。
从前向传播之后取最后的检测结果
#python代码 #------------------------ #out = net.forward() h = img.shape[0] #待测图片的高 w = img.shape[1] #待测图片的宽 #取出out中的detection_out的blob中的数据,按照blob名字取数据。 #detection_out中的是包含7个float数据,从第4个到第7个分别代表位置坐标 #由于要还原到原来的图片中的实际位置,所以分别乘以原图中的宽高 box = out['detection_out'][0,0:3,7] * np.array([w,h,w,h) cls = out['detection_out'][0,0,:,1] #第二个位置是分类结果 conf = out['detection_out'][0,0,:,2]#第三个位置是分类置信度
/*C++代码 ----------------------------*/ const vector<Blob<float>* >& outputBlobs = net_->Forward(); Blob<float>* outputBlob = outputBlobs[0]; //输出blob const float* result = outputBlob->cpu_data(); vector<vector<float> > detections; //注意这里 outputBlob->count() 和 outputBlob->height()的数值也许是不一样的 for (int i = 0; i<outputBlob->count(); ++i) { if (result[0] == -1) { // Skip invalid detection. result += 7; continue; } vector<float> detection(result, result + 7); detections.push_back(detection); result += 7; }
相关文章推荐
- 【caffe】Caffe的Python接口-官方教程-01-learning-Lenet-详细说明(含代码)
- 【caffe】Caffe的Python接口-官方教程-00-classification-详细说明(含代码)
- ROS python 代码转换到 C++
- Caffe中c++与python调用图像分类接口
- Python接口(2):使用ctpyes模块在python中调用c++代码
- 如何将C++代码转换为Delphi代码的双线性插值算法
- unicode utf-8 gb2312编码 使用C++相互转换的代码
- python工具代码之农历转换公历,公历转换农历神器持续更新:【内向即失败--王奕君】
- Python2到Python3代码的转换工具2to3.py
- Caffe-Python接口常用API参考
- 对筛法求素数的实现代码(Python及C++)
- c++ 数据格式转换代码(收集)
- 如何让C/C++代码同时兼容Python2和Python3
- python类型强制转换long to int的代码
- 我的第一个python web开发框架(33)——接口代码重构
- python 转换 Javascript %u 字符串为python unicode的代码
- 在ubuntu上配置cuda+cudnn+caffe(包括python和matlab接口)+digits
- 如何快糙好猛地在Windows下编译CAFFE并使用其matlab和python接口
- 深度学习之Caffe(一) 用c++接口提取特征后用SVM分类
- caffe预测、特征可视化python接口调用