上一篇介绍了benchmark部分
本文针对NCNN项目https://github.com/Tencent/ncnn 其结构,做第二部分,即examples部分的详解,进入ncnn/examples目录,你会看到如下文件:
首先 分析CMakeLists.txt内容:
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs)
if(NOT OpenCV_FOUND)
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)
set(NCNN_EXAMPLE_LINK_LIBRARIES ncnn ${OpenCV_LIBS})
if(NCNN_VULKAN)
list(APPEND NCNN_EXAMPLE_LINK_LIBRARIES ${Vulkan_LIBRARY})
endif()
add_executable(squeezenet squeezenet.cpp)
target_link_libraries(squeezenet ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(fasterrcnn fasterrcnn.cpp)
target_link_libraries(fasterrcnn ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(rfcn rfcn.cpp)
target_link_libraries(rfcn ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(yolov2 yolov2.cpp)
target_link_libraries(yolov2 ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(yolov3 yolov3.cpp)
target_link_libraries(yolov3 ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(mobilenetv2ssdlite mobilenetv2ssdlite.cpp)
target_link_libraries(mobilenetv2ssdlite ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(mobilenetssd mobilenetssd.cpp)
target_link_libraries(mobilenetssd ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(squeezenetssd squeezenetssd.cpp)
target_link_libraries(squeezenetssd ${NCNN_EXAMPLE_LINK_LIBRARIES})
add_executable(shufflenetv2 shufflenetv2.cpp)
target_link_libraries(shufflenetv2 ${NCNN_EXAMPLE_LINK_LIBRARIES})
涉及一些cmake的语法,在此做个简单解析,
在使用CMake组织工程时,如果我们需要依赖某个库文件,需要完成以下步骤:
1.查找库文件(find_package命令)
2.判断是否找到库文件(XXX_FOUND标记),并包含头文件(include_directories命令)
3.链接库文件到目标(target_link_libraries命令)
该句查找并加载外来工程的设置:find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodecs)
的函数原型是:
find_package(<package> [version] [EXACT] [QUIET]
[[REQUIRED|COMPONENTS] [components...]]
[NO_POLICY_SCOPE])
其中OpenCV是外部依赖的包名,实例中省去了OpenCV的版本号,QUIET选项将会禁掉包没有被发现时的警告信息;REQUIRED选项表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在它们的后面可以列出一些与包相关的部件清单(components list)。上面就列出了几个清单内容,如core,highgui,imgproc,imgcodecs组件;(可参考:find_package详解)
一般该命令会设置<package>_FOUND变量,用来指示要找的包是否被找到了。上面代码中:
if(NOT OpenCV_FOUND)
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc)
endif()
如果没有找到OpenCV的core highgui imgproc imgcodecs,则寻找core highgui imgproc;
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src)
即包含ncnn/src的内容;
${CMAKE_CURRENT_SOURCE_DIR}是cmake内置变量,指定了CMakeLists.txt所在目录,找到其中的opencv.h头文件;
${CMAKE_CURRENT_BINARY_DIR}作用:当前正在处理的二进制目录路径。build目录完全路径,当前cmake正在处理。add_subdirectory()添加每个目录,这些目录会在build目录树中创建二进制目录,并且在处理时,设置该变量。对in-source而言,这是正在处理的当前源目录(当前处理的CMakeLists.txt所在路径),in-source编译与out-of-souce编译(编译输出文件和源文件不在同一目录)相对。
set(NCNN_EXAMPLE_LINK_LIBRARIES ncnn ${OpenCV_LIBS})
语法: SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
指令功能: 用来显式的定义变量;
源码中变量名为NCNN_EXAMPLE_LINK_LIBRARIES,为该变量赋予了ncnn库和opencv库;
add_executable(squeezenet squeezenet.cpp)
target_link_libraries(squeezenet ${NCNN_EXAMPLE_LINK_LIBRARIES})
使用给定的源文件squeezenet.cpp,为工程引入一个可执行文件squeezenet;为squeezenet添加依赖库;
其他几行代码雷同;
上图红框是squeezencnn相关的,bin是ncnn支持的模型文件格式,caffemodel是caffe训练得到的模型格式,param是ncnn支持的网络结构文件,prototxt是caffe支持的模型结构信息。synset_words.txt是label信息。这个是官方提供的分类用的demo以及相关模型,网络信息等。
之后会运行一个NCNN的squeezencnn的模型;
其他的cpp格式文件都是相应网络的demo程序,编译后会生成对应名的可执行文件。