摘要: 转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/

github上的代码链接,求给星星:) https://github.com/YihangLou/FasterRCNN-Encapsulation-Cplusplus

在上一篇文章中,我们是将对caffe的调用隔离了出来,可以说相当于原来caffe源码下的tools中cpp文件使用相同,然后自己写了个CMakeLists.txt进行编译。这里是进一步将代码进行分离,封装成libfaster_rcnn.so文件进行使用。对于部分接口,我可能做了一些改动。
目录结构
├── CMakeLists.txt
├── lib
│   ├── CMakeLists.txt
│   ├── faster_rcnn.cpp
│   ├── faster_rcnn.hpp
├── main.cpp
├── pbs_cxx_faster_rcnn_demo.job

在这里main.cpp就是直接调用faster_rcnn.cpp的接口,他的内容也很简单,只是在之前的基础上,再加上libfaster_rcnn.so这个动态库文件

#include "faster_rcnn.hpp"
int main()
{string model_file = "/home/lyh1/workspace/py-faster-rcnn/models/pascal_voc/VGG_CNN_M_1024/faster_rcnn_alt_opt/faster_rcnn_test.pt";string weights_file = "/home/lyh1/workspace/py-faster-rcnn/output/default/yuanzhang_car/vgg_cnn_m_1024_fast_rcnn_stage2_iter_40000.caffemodel";int GPUID=0;Caffe::SetDevice(GPUID);Caffe::set_mode(Caffe::GPU);Detector det = Detector(model_file, weights_file);det.Detect("/home/lyh1/workspace/py-faster-rcnn/data/demo/car.jpg");return 0;
}

可以看到这里只是include了faster_rcnn.hpp头文件,其对应的CMakeLists.txt文件如下:


#This part is used for compile faster_rcnn_demo.cpp
cmake_minimum_required (VERSION 2.8)project (main_demo)add_executable(main main.cpp)include_directories ( "${PROJECT_SOURCE_DIR}/../caffe-fast-rcnn/include""${PROJECT_SOURCE_DIR}/../lib/nms" "${PROJECT_SOURCE_DIR}/lib" /share/apps/local/include/usr/local/include /opt/python/include/python2.7/share/apps/opt/intel/mkl/include /usr/local/cuda/include )target_link_libraries(main /home/lyh1/workspace/py-faster-rcnn/faster_cxx_lib/lib/libfaster_rcnn.so/home/lyh1/workspace/py-faster-rcnn/caffe-fast-rcnn/build/lib/libcaffe.so/home/lyh1/workspace/py-faster-rcnn/lib/nms/gpu_nms.so /share/apps/local/lib/libopencv_highgui.so /share/apps/local/lib/libopencv_core.so /share/apps/local/lib/libopencv_imgproc.so /share/apps/local/lib/libopencv_imgcodecs.so/share/apps/local/lib/libglog.so/share/apps/local/lib/libboost_system.so/share/apps/local/lib/libboost_python.so/share/apps/local/lib/libglog.so/opt/rh/python27/root/usr/lib64/libpython2.7.so)

对于faster_rcnn.hppfaster_rcnn.cpp ,我们需要将他们编译成动态库,下面是他们对应的CMakeLists.txt,在文件中,可以看到跟上面这个区别是用了add_library语句,并且加入了SHARED关键字,SHARED代表动态库。其次,在编译动态库的过程中,是不需要链接的,但是我们知道这个库是依赖别的很多个库的,所以在最后形成可执行文件也就是上面这个CMakeLists.txt,我们需要添加这个动态库所依赖的那些动态库,至此就OK了。编译的话,非常傻瓜cmake .然后在执行make即可。

cmake_minimum_required (VERSION 2.8)SET (SRC_LIST faster_rcnn.cpp)
include_directories ( "${PROJECT_SOURCE_DIR}/../../caffe-fast-rcnn/include""${PROJECT_SOURCE_DIR}/../../lib/nms" /share/apps/local/include/usr/local/include /opt/python/include/python2.7/share/apps/opt/intel/mkl/include /usr/local/cuda/include )add_library(faster_rcnn SHARED ${SRC_LIST})

首先将原来的cpp文件中的声明提取出来,比较简单,就是hpp文件对应cpp文件。如下:

#ifndef FASTER_RCNN_HPP
#define FASTER_RCNN_HPP
#include <stdio.h>  // for snprintf
#include <string>
#include <vector>
#include <math.h>
#include <fstream>
#include <boost/python.hpp>
#include "caffe/caffe.hpp"
#include "gpu_nms.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace caffe;
using namespace std;#define max(a, b) (((a)>(b)) ? (a) :(b))
#define min(a, b) (((a)<(b)) ? (a) :(b))//background and car
const int class_num=2;/*
 * ===  Class  ======================================================================
 *         Name:  Detector
 *  Description:  FasterRCNN CXX Detector
 * =====================================================================================
 */
class Detector {
public:Detector(const string& model_file, const string& weights_file);void Detect(const string& im_name);void bbox_transform_inv(const int num, const float* box_deltas, const float* pred_cls, float* boxes, float* pred, int img_height, int img_width);void vis_detections(cv::Mat image, int* keep, int num_out, float* sorted_pred_cls, float CONF_THRESH);void boxes_sort(int num, const float* pred, float* sorted_pred);private:shared_ptr<Net<float> > net_;Detector(){}
};//Using for box sort
struct Info
{float score;const float* head;
};
bool compare(const Info& Info1, const Info& Info2)
{return Info1.score > Info2.score;
}
#endif

相应的cpp文件

#include <stdio.h>  // for snprintf
#include <string>
#include <vector>
#include <math.h>
#include <fstream>
#include <boost/python.hpp>
#include "caffe/caffe.hpp"
#include "gpu_nms.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "faster_rcnn.hpp"
using namespace caffe;
using namespace std;/*
 * ===  FUNCTION  ======================================================================
 *         Name:  Detector
 *  Description:  Load the model file and weights file
 * =====================================================================================
 */
//load modelfile and weights
Detector::Detector(const string& model_file, const string& weights_file)
{net_ = shared_ptr<Net<float> >(new Net<float>(model_file, caffe::TEST));net_->CopyTrainedLayersFrom(weights_file);
}/*
 * ===  FUNCTION  ======================================================================
 *         Name:  Detect
 *  Description:  Perform detection operation
 *                 Warning the max input size should less than 1000*600
 * =====================================================================================
 */
//perform detection operation
//input image max size 1000*600
void Detector::Detect(const string& im_name)
{float CONF_THRESH = 0.8;float NMS_THRESH = 0.3;const int  max_input_side=1000;const int  min_input_side=600;cv::Mat cv_img = cv::imread(im_name);cv::Mat cv_new(cv_img.rows, cv_img.cols, CV_32FC3, cv::Scalar(0,0,0));if(cv_img.empty()){std::cout<<"Can not get the image file !"<<endl;return ;}int max_side = max(cv_img.rows, cv_img.cols);int min_side = min(cv_img.rows, cv_img.cols);float max_side_scale = float(max_side) / float(max_input_side);float min_side_scale = float(min_side) /float( min_input_side);float max_scale=max(max_side_scale, min_side_scale);float img_scale = 1;if(max_scale > 1){img_scale = float(1) / max_scale;}int height = int(cv_img.rows * img_scale);int width = int(cv_img.cols * img_scale);int num_out;cv::Mat cv_resized;std::cout<<"imagename "<<im_name<<endl;float im_info[3];float data_buf[height*width*3];float *boxes = NULL;float *pred = NULL;float *pred_per_class = NULL;float *sorted_pred_cls = NULL;int *keep = NULL;const float* bbox_delt;const float* rois;const float* pred_cls;int num;for (int h = 0; h < cv_img.rows; ++h ){for (int w = 0; w < cv_img.cols; ++w){cv_new.at<cv::Vec3f>(cv::Point(w, h))[0] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[0])-float(102.9801);cv_new.at<cv::Vec3f>(cv::Point(w, h))[1] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[1])-float(115.9465);cv_new.at<cv::Vec3f>(cv::Point(w, h))[2] = float(cv_img.at<cv::Vec3b>(cv::Point(w, h))[2])-float(122.7717);}}cv::resize(cv_new, cv_resized, cv::Size(width, height));im_info[0] = cv_resized.rows;im_info[1] = cv_resized.cols;im_info[2] = img_scale;for (int h = 0; h < height; ++h ){for (int w = 0; w < width; ++w){data_buf[(0*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[0]);data_buf[(1*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[1]);data_buf[(2*height+h)*width+w] = float(cv_resized.at<cv::Vec3f>(cv::Point(w, h))[2]);}}net_->blob_by_name("data")->Reshape(1, 3, height, width);net_->blob_by_name("data")->set_cpu_data(data_buf);net_->blob_by_name("im_info")->set_cpu_data(im_info);net_->ForwardFrom(0);bbox_delt = net_->blob_by_name("bbox_pred")->cpu_data();num = net_->blob_by_name("rois")->num();rois = net_->blob_by_name("rois")->cpu_data();pred_cls = net_->blob_by_name("cls_prob")->cpu_data();boxes = new float[num*4];pred = new float[num*5*class_num];pred_per_class = new float[num*5];sorted_pred_cls = new float[num*5];keep = new int[num];for (int n = 0; n < num; n++){for (int c = 0; c < 4; c++){boxes[n*4+c] = rois[n*5+c+1] / img_scale;}}bbox_transform_inv(num, bbox_delt, pred_cls, boxes, pred, cv_img.rows, cv_img.cols);for (int i = 1; i < class_num; i ++){for (int j = 0; j< num; j++){for (int k=0; k<5; k++)pred_per_class[j*5+k] = pred[(i*num+j)*5+k];}boxes_sort(num, pred_per_class, sorted_pred_cls);_nms(keep, &num_out, sorted_pred_cls, num, 5, NMS_THRESH, 0);//for visualize onlyvis_detections(cv_img, keep, num_out, sorted_pred_cls, CONF_THRESH);}cv::imwrite("vis.jpg",cv_img);delete []boxes;delete []pred;delete []pred_per_class;delete []keep;delete []sorted_pred_cls;}/*
 * ===  FUNCTION  ======================================================================
 *         Name:  vis_detections
 *  Description:  Visuallize the detection result
 * =====================================================================================
 */
void Detector::vis_detections(cv::Mat image, int* keep, int num_out, float* sorted_pred_cls, float CONF_THRESH)
{int i=0;while(sorted_pred_cls[keep[i]*5+4]>CONF_THRESH && i < num_out){if(i>=num_out)return;cv::rectangle(image,cv::Point(sorted_pred_cls[keep[i]*5+0], sorted_pred_cls[keep[i]*5+1]),cv::Point(sorted_pred_cls[keep[i]*5+2], sorted_pred_cls[keep[i]*5+3]),cv::Scalar(255,0,0));i++;}
}/*
 * ===  FUNCTION  ======================================================================
 *         Name:  boxes_sort
 *  Description:  Sort the bounding box according score
 * =====================================================================================
 */
void Detector::boxes_sort(const int num, const float* pred, float* sorted_pred)
{vector<Info> my;Info tmp;for (int i = 0; i< num; i++){tmp.score = pred[i*5 + 4];tmp.head = pred + i*5;my.push_back(tmp);}std::sort(my.begin(), my.end(), compare);for (int i=0; i<num; i++){for (int j=0; j<5; j++)sorted_pred[i*5+j] = my[i].head[j];}
}/*
 * ===  FUNCTION  ======================================================================
 *         Name:  bbox_transform_inv
 *  Description:  Compute bounding box regression value
 * =====================================================================================
 */
void Detector::bbox_transform_inv(int num, const float* box_deltas, const float* pred_cls, float* boxes, float* pred, int img_height, int img_width)
{float width, height, ctr_x, ctr_y, dx, dy, dw, dh, pred_ctr_x, pred_ctr_y, pred_w, pred_h;for(int i=0; i< num; i++){width = boxes[i*4+2] - boxes[i*4+0] + 1.0;height = boxes[i*4+3] - boxes[i*4+1] + 1.0;ctr_x = boxes[i*4+0] + 0.5 * width;ctr_y = boxes[i*4+1] + 0.5 * height;for (int j=0; j< class_num; j++){dx = box_deltas[(i*class_num+j)*4+0];dy = box_deltas[(i*class_num+j)*4+1];dw = box_deltas[(i*class_num+j)*4+2];dh = box_deltas[(i*class_num+j)*4+3];pred_ctr_x = ctr_x + width*dx;pred_ctr_y = ctr_y + height*dy;pred_w = width * exp(dw);pred_h = height * exp(dh);pred[(j*num+i)*5+0] = max(min(pred_ctr_x - 0.5* pred_w, img_width -1), 0);pred[(j*num+i)*5+1] = max(min(pred_ctr_y - 0.5* pred_h, img_height -1), 0);pred[(j*num+i)*5+2] = max(min(pred_ctr_x + 0.5* pred_w, img_width -1), 0);pred[(j*num+i)*5+3] = max(min(pred_ctr_y + 0.5* pred_h, img_height -1), 0);pred[(j*num+i)*5+4] = pred_cls[i*class_num+j];}}
}

faster_rcnn c++版本的 caffe 封装,动态库(2)相关推荐

  1. faster_rcnn c++版本的 caffe 封装(1)

    转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ 由于需要把FasterRCNN做的工程化,因此这里需要对Caff ...

  2. 分析Windows和Linux动态库

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  3. Windows和Linux动态库比较 (Zhuan)

    Windows和Linux动态库比较 Description: 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库 可以有效的减少程序大小,节 ...

  4. MFC的静态库.lib、动态库.dll(包含引入库.lib)以及Unicode库示例

    以vs2012为标准.转自:http://technet.microsoft.com/zh-cn/library/w4zd66ye ,有改动. 一 MFC的静态库(.lib) MFC静态库使用下列命名 ...

  5. KingbaseES V8R6 运维案例 --ksql访问动态库问题

    KingbaseES V8R6数据库运维案例之---ksql访问动态库问题 案例说明: CentOS环境下,在安装和初始化数据库实例后,启动数据库服务,通过ksql连接访问时出现以下故障: 经检查,是 ...

  6. C++动态库*.dll文件的Debug/Release版本是否可以混用(交叉用)?

    1.现象: 使用一些第三方的dll,比如opencv,会分别生成debug和release的dll,在exe中必须要引用指定版本的dll,不能混用,否则会出错:同样的道理,jsoncpp库也是. 但是 ...

  7. Qt显示pdf系列4——封装pdfium库为动态库,显示pdf

    序 一新建项目 二封装pdfium库 三使用封装好的pdf动态库 1在vs中使用 2在qt中使用 四结语  承接上篇,pdfium的lib文件是已经编译出来了,理论上已经可以开始直接用了,官方提供的测 ...

  8. Android studio封装调用多个第三方so动态库

    1.在项目local.properties文件中配置NDK版本: 2.配置编译目录 cpp 目录为编译脚本,源代码和头文件目录 jniLibs 为第三方so库目录, 3.添加第三方so库 注意子目录名 ...

  9. 解决Linux动态库版本兼容问题

    说道"动态库版本兼容",很多人头脑中首先蹦出的就是"Dll Hell".啊,这曾经让人头疼的难题.时至今日,这个难题已经很好地解决了.   在进一步讨论之前来思 ...

最新文章

  1. 充电 | 打开机器学习的大门,需要了解哪些知识?
  2. 3.7python怎么安装清屏_python3.7中怎么清屏
  3. Spring注解——使用@ComponentScan自动扫描组件
  4. (软件工程复习核心重点)第五章详细设计-第三节:过程设计工具
  5. 译:C#面向对象的基本概念 (Basic C# OOP Concept) 第二部分(封装,抽象,继承)...
  6. 浙大通讯与计算机网络离线作业,2015浙大通信与计算机网络离线作业.doc
  7. RESTful API 特点
  8. Valgrind 使用简单说明-转
  9. 解析Pinterest:兴趣乐园背后的大文章
  10. 左右侧边栏固定宽,中间宽度自适应
  11. JavaScript浏览器对象模型常用事件(2)
  12. vue组件之间的参数传递
  13. DIV+CSS定义及优势
  14. 查看name的状态,是属于active还是standby
  15. 关于sql server 代理(已禁用代理xp)
  16. 用什么录屏软件能录制高清视频
  17. ubb html编辑器,GitHub - ibone/ubb-editor: web编辑器
  18. 移动APP测试,adb工具,常用的命令(1)
  19. 【学习笔记】消息队列之MQ的基本概念
  20. (转)IST:Iterative Shrinkage/Thresholding和Iterative Soft Thresholding

热门文章

  1. boost::range_result_iterator相关的测试程序
  2. boost::mp11::tuple_for_each相关用法的测试程序
  3. boost::gil::bit_aligned_pixel_reference用法的测试程序
  4. boost::coroutine模块实现分段堆栈的测试程序
  5. ITK:在图像区域上运行图像过滤器
  6. VTK:PolyData之PointsProjectedHull
  7. VTK:几何对象之GeometricObjectsDemo
  8. VTK:几何对象之ConvexPointSet
  9. OpenCV视差图后过滤
  10. 在Windows中安装OpenCV