01 使用cmake编译的添加代码方式
阅读caffe\tools\CMakeLists.txt
# Collect source files
file(GLOB_RECURSE srcs ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
# Build each source file independently
foreach(source ${srcs})
get_filename_component(name ${source} NAME_WE)
# caffe target already exits
if(name MATCHES "caffe")
set(name ${name}.bin)
endif()
# target
add_executable(${name} ${source})
target_link_libraries(${name} ${Caffe_LINK})
caffe_default_properties(${name})
可以看出caffe\tools下面的cpp文件除了caffe.cpp被命名为caffe.bin工程外,其他的cpp文件都以文件名称命名为工程。
所以只要把我们的类tools代码,放到caffe\tools文件下,运行cmake-gui,【configure】、【generate】,重新生成工程文件,这样工程会自动加载include、和lib依赖。
02 添加测试代码
在caffe\tools\my_first_test.cpp文件,这里使用《深度学习-21天实战caffe》中的第八天《Caffe数据结构》中的代码。
#include <vector>
#include <iostream>
#include <caffe/blob.hpp>
#include <caffe/util/io.hpp> // test03()
#include <caffe/net.hpp> // TestNet()
using namespace caffe;
using namespace std;
void test01()
{
Blob<float> a;
// 默认维度0
cout << "Size: " << a.shape_string() << endl;
a.Reshape(1, 2, 3, 4); // 重置维度
cout << "Size: " << a.shape_string() << endl;
// 设置data值
float* p = a.mutable_cpu_data();
for (int i = 0; i < a.count(); i++) {
p[i] = i;
}
// 打印data值
for (int u = 0; u < a.num(); u++) {
for (int v = 0; v < a.channels(); v++) {
for (int w = 0; w < a.height(); w++) {
for (int x = 0; x < a.width(); x++) {
cout << "a[" << u << "][" << v << "][" << w << "][" << x << "] = " << a.data_at(u, v, w, x) << endl;
}
}
}
}
cout << "ASUM = " << a.asum_data() << endl; // 元素绝对值和(L1-范数)
cout << "SUMQ = " << a.sumsq_data() << endl; // 平方和(L2-范数)
}
void test02(Blob<float> &b)
{
cout << "Size: " << b.shape_string() << endl;
b.Reshape(1, 2, 3, 4);
cout << "Size: " << b.shape_string() << endl;
float* p = b.mutable_cpu_data();
float* q = b.mutable_cpu_diff();
for (int i = 0; i < b.count(); i++) {
p[i] = i; // 将data初始化为 1,2,3...
q[i] = b.count() - 1 - i; // 将diff初始化为23,22,21...
}
b.Update(); // 执行Update操作,将diff与data融合
// 这也是CNN权值更新步骤的最终实施者
for (int u = 0; u < b.num(); u++) {
for (int v = 0; v < b.channels(); v++) {
for (int w = 0; w < b.height(); w++) {
for (int x = 0; x < b.width(); x++) {
cout << "b[" << u << "][" << v << "][" << w << "][" << x << "] = " << b.data_at(u, v, w, x) << endl;
}
}
}
}
cout << "ASUM = " << b.asum_data() << endl;
cout << "SUMSQ = " << b.sumsq_data() << endl;
}
void test03(Blob<float> &a)
{
BlobProto bp; // 构造一个BlobProto对象
a.ToProto(&bp, true); // 将a 序列化,连同diff(默认不带)
WriteProtoToBinaryFile(bp, "a.blob"); // 写入磁盘文件"a.blog"
BlobProto bp2; // 构造一个新的 BlobProto对象
ReadProtoFromBinaryFileOrDie("a.blob", &bp2); // 读取磁盘文件
Blob<float> b;
b.FromProto(bp2, true); // 从序列化对象bp2中克隆b(连同形状)
cout << "output a.blob" << endl;
for (int u = 0; u < b.num(); u++) {
for (int v = 0; v < b.channels(); v++) {
for (int w = 0; w < b.height(); w++) {
for (int x = 0; x < b.width(); x++) {
cout << "b[" << u << "][" << v << "][" << w << "][" << x << "] = " << b.data_at(u, v, w, x) << endl;
}
}
}
}
}
void TestNet()
{
// deploy.prototxt 来自models\bvlc_reference_caffenet\deploy.prototxt
// debug调试时把depoly.prototxt放在my_first_test工程同目录下,直接运行exe时,放在exe同目录下
std::string proto("deploy.prototxt");
Net<float> nn(proto, caffe::TEST);
vector<string> bn = nn.blob_names(); // 获取Net中所有blob对象名称
for (int i = 0; i < bn.size(); i++) {
cout << "Blob #" << i << " : " << bn[i] << endl;
}
}
int main(void)
{
test01();
Blob<float> b;
test02(b);
test03(b);
TestNet();
return 0;
}
03 重新运行cmake-gui,重新生成vs工程
04 运行my_first_test工程
设置my_first_test工程为启动项,设置断点,运行调试。