When developing Factory pattern in c++, we usually want to automatically maintain a Function/Class table of children implementations to create, e.g.
- Apple -> Class Apple
- Banana -> Class Banana
The problem is that every time a new implementation is added, the table needs a update. Editing the table may incurs conflicts. The proper solution is to let each implementation register itself during dynamic linking.
The register process has the following components:
- a static std::map table in the factory class’s getTable() function
- a template class to create children implementation class
- when declaring the template class, the factory class’s std::map table is updated
Please find the example in http://blog.fourthwoods.com/2011/06/04/factory-design-pattern-in-c/
In the above example the declaration, the template class exist in .cpp files, here goes a linking problem.
If the .cpp file exist in the same project as main.cpp, or the .cpp exist in a dll, it works. The declaration of the template class works in runtime and success register the std::map table.
However, if the .cpp file exist in a static lib, the registering may not run. This happens because the declaration of the template class could be a static initialization which is done in compile-time, failing to update the std::map table.
The solution was answered here: http://stackoverflow.com/a/23799529/3082081
- enable Use Library Dependency Inputs add the static lib project as reference to the main.cpp project;
- or use /WHOLEARCHIVE:lib_name for the static lib
Even though the above methods can solve the linking problem, the best solution, however, is to make the project a dll instead of lib.
This post is a small example of start caffe from Visual Studio.
Usually caffe is called from command window for simplicity. Yet with Visual Studio, step into/over codes line by line make the Debugging much straight forward.
All codes are written in the “train-MNIST” project.
- “SolverParameter solver_param” reads the solver’s configuration from a .prototxt file.
- A “solver” is created upon the “solver_param” variable.
- Noted that if both TRAIN and TEST phase are defined in the net configuration file, the solver will have 2 nets attached to it.
- The training net is unique, which can be fetched by “solver->net()”.
- The first test net can be fetched by “solver->test_nets()”
- When doing fine-tune, the starting model can be loaded before the solver starts.
- The training net will share its weights with testing net automatically, so the starting model only needs to be push to training net.
- Before start training, the most important thing is the working directory. All the .prototxt file should use the same root path, so that required files can be loaded properly. The root path for caffe examples is the “caffe” folder, which is the “$(SolutionDir)caffe” I set below.
If you have the code compiled from the previous post: Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup. Now you can use caffe in the following two ways:
- Use the caffe.exe from cmd. The main function came from the “caffe/tools/caffe.cpp” file, which can be used for batch training and testing. For example the test on MNIST you did in the previous post.
- Change the caffe project to “Static library (.lib)” and use caffe.lib in another vs project.
I’ll give an example for the second method. Code for caffe and test-MNIST are given at GitHub.
Let’s look at the structure of the project folder:
Noted that “caffe” and “test-MNIST” are in the same solution file “caffe-vs2013.sln”, so they have the same “$(SolutionDir)”. You might noticed that in the 2 “.props” files the “OutDir”, which is “$(SolutionDir)build\$(Platform)\$(Configuration)\”, which is the “OutDir”, is also listed in “AdditionalLibraryDirectories”.
When you compile “caffe” as “Static library (.lib)”, a “caffe.lib” file will be generated at “build/x64/Release” folder for example. In the meantime, this “caffe.lib” can be used by “test-MNIST” project directly because the “build/x64/Release” folder is already listed in “AdditionalLibraryDirectories”.
The explanation was mouthful but the effect is straight forward: all projects in the same solution can share the output of each other. That was why I created the 2 .props files so that all projects can import them.
Now we can play with the projects.
- Make sure the “caffe” project is configured to produce “Static library (.lib)” and compile it to get “caffe.lib”.
- Right click “test-MNIST” project and choose “Set as StartUp Project”. Ctrl+F5 to run.
- A image for the figure “5” will be displayed.
- In cmd the probability for 5 will be the highest.
How things works:
- A caffe network to .prototxt file to describe its structure, based on google’s protobuf library.
- The training process generate .solverstate to for continue training, and .caffemodel file for the trained weights.
- In .prototxt file, weights related structure cannot be changed if you want to use trained model file, e.g. convolution layer, pooling layer, etc. While the date layer has to be adjusted to how you use the model.
- In “lenet_train_test-leveldb.prototxt” file, the data layer has the type of “DATA” and the source of “examples/mnist/mnist_train_leveldb”. (This file was used by training)
- In “lenet_test-memory-1.prototxt” file, the data layer’s type is changed to MEMORY_DATA so that it can get data from OpenCV later on. (This file will be used by test-MNIST.cpp)
- In “lenet_test-memory-1.prototxt” file, a SOFTMAX is added in stead of ACCURACY and SOFTMAX_LOSS because we don’t have ground truth label to compare to any more.
- Noted that the only thing you can change in data layer is the type and source. The number of channel and image size have to be exactly the same as the training.
- The batch_size is the number of images the caffe handle together during one forward propagation. Using “batch_size: 100” once is much faster than “batch_size: 1” 100 times.
- The “scale” means change the input image value by multiple with the number. The input image scales 0~255, after scaling it’s 0~1 now.
- In “test-MNIST.cpp“:
- “#pragma comment(lib, “caffe.lib”)” is equivalent to manually add “caffe.lib” into “AdditionalDependencies”.
- The default working path is “$(ProjectDir)”, which is the location of “test-MNIST.vcxproj” file, so “../caffe” points to the root path of caffe.
- Image is loaded by OpenCV.
- Caffe is set to GPU mode.
- Net is initialized from “lenet_test-memory-1.prototxt” file.
- The size of vector<Mat> need to be multiple of the batch_size in .prototxt file.
- For example if batch_size is 1 and the size of vector<Mat> is 10, you need to run “AddMatVector” once and run “ForwardPrefilled” 10 times to consume all the added data. Every time after “ForwardPrefilled”, the data in “results->mutable_cpu_data()” will be different.
The purpose of this series it to get caffe working in windows in the most quick and dirty way: I’ll provide 1) the modified file that can be compiled in windows right away; 2) the vs2013 project that I’m currently using. In short:
- Install CUDA, Boost, OpenCV.
- Download caffe code with vs2013 from GitHub.
- Download 3ryparty.zip and unzip to ‘3rdparty’ folder.
- Edit ‘Caffe-vs2013 – Debug.props’ and ‘Caffe-vs2013 – Release.props’ files so that the path of CUDA, Boost and OpenCV make sense for you. Also, the given ‘compute_50,sm_50’ is for Maxwell GPU. Change 50 to 20 for Fermi and 30 for Kepler.
- Open caffe-vs2013.sln.
- Set platform to Release, x64 and change ‘caffe’ project’s ‘Configuration Type’ to ‘Application (.exe)’.
- Right click on ‘caffe’ project and ‘compile’.
- Run test on MNIST.
- For caffe.exe, please use Release|x64 mode. Debug version of caffe.exe makes no sense and is slow.
- 32 bit version should work but lacking support for lmdb and hdf5 because I didn’t compile them. lol
- CUDA 6.5
- You have to have a Nvidia GPU on your PC to enable GPU version of Caffe. My impression was that you get maybe 10x speed-up using GPU over CPU, and another 10x speed-up by enable CuDNN library.
- The installation will create system variable for you, e.g. CUDA_PATH_V6_5.
- If you are using a GPU with the architecture of Fermi or Kepler: CUDA 6.5
- If you are using a GeForce GTX9xx GPU with the architecture of Maxwell: CUDA 6.5 for Maxwell
- Newer version of CUDA should be fine also.
- Pre-built version of boost are available. I’m using boost 1.56.0 myself. Get pre-built boost and install.
- Add boost’s path to system’s path. I added BOOST_1_56_0:
- Since we are not using GPU supported OpenCV here, e.g. GpuMat, etc. Pre-built version of OpenCV are good enough for a quick start.
- I use OpenCV 3.0 here as example. Add system path variable for OpenCV also:
- System variable need ‘log off’ or ‘restart’ your system to take effect
- Download the code for caffe from my GitHub
- The original code was forded from 7e465f2. Then I manually added the changes from #1416 to support “vector<Mat>”.
- Download the 3rdparty.zip and unzip its content to 3rdpary folder
Before compile (skip if you’re familiar with vs2013 already):
- When it comes to a big project, many errors can happen. Let’s get things a bit clear first.
- In a project, usually functions are declared in .h/.hpp files and implemented in .c/.cpp files. Missing .hpp file is usually shown in the editor and missing .cpp file usually gives linking error.
- All .cpp files added to the vs project will be compiled to .obj files which can be linked later. While no .hpp files will be compiled. Adding .hpp files to the vs project or not makes no difference to the compiling.
- If you want to include .hpp file from another project, e.g. OpenCV. You need to add the path of the header files to ‘AdditionalIncludeDirectories’.
- Adding header files to the vs project does NOT add the path automatically.
- Adding the path of .cpp files to ‘AdditionalIncludeDirectories’ is NOT needed and has NO effect.
- For example if the file path is “D:\toolkits\opencv-3.0.0\build\include\opencv2\opencv.hpp”, you can either:
- 1) add “D:\toolkits\opencv-3.0.0\build\include” to ‘AdditionalIncludeDirectories’ and write #include “opencv2/opencv.hpp”; or
- 2) add “D:\toolkits\opencv-3.0.0\build\include\opencv2” to ‘AdditionalIncludeDirectories’ and write #include “opencv.hpp”;
- After the .hpp file is included, the compiler knows that these functions exist so ‘unknown namespace cv’ kind of error will not happen any more.
- After all .cpp files in your project are compiled, here comes the linking. The implementation of functions have to be either in .cpp files of your project or .lib files generated by other projects.
- Enabling lib files requires 1) path to be added to ‘AdditionalLibraryDirectories’; and 2) file names to be added to ‘AdditionalDependencies’.
- For example, you might add “D:\toolkits\opencv-3.0.0\build\x86\vc12\lib” to ‘AdditionalLibraryDirectories’ and add “opencv_ts300.lib; opencv_world300.lib;” to ‘AdditionalDependencies’.
- Usually the path of lib files changes according to the ‘PlatformTarget’, i.e. ‘x86’, and the ‘Configuration’, i.e. ‘Debug’. I usually let Visual Studio handle the difference, e.g. I add “$(OPENCV_3_0_0)\$(PlatformTarget)\vc12\lib” for OpenCV in later sections.
- If you solve compile error by having proper .hpp files and solve linking error by have proper .lib files, you program will run. Yet it might have missing .dll error.
- Some library are compiled in the static way to generate .lib files only, like gflags, protobuf, etc.
- Some library are compiled in the dynamic way to generate both .lib and .dll files. In this case your program will require .dll files on run-time.
- Personally I like to copy required .dll files to the same folder of the .exe file for simplicity.
- Open the ‘caffe-vs2013.sln’
- In Property Manager you’ll see that 2 .props files are added to the project: ‘Caffe-vs2013 – Debug.props’ and ‘Caffe-vs2013 – Release.props’.
- This is a very handy way to setup you project quickly. The idea is that some fixed configuration are written in the property sheet file, i.g. ‘Caffe-vs2013 – Release.props’. After that the project’s property, i.e. ‘Release|x64’, can inherit from it.
- Open the ‘Caffe-vs2013 – Release.props’ from disk, you’ll see the setting for CUDA, Boost, OpenCV, etc. If your system path for CUDA, Boost, OpenCV are different from mine, you need to change them in these 2 .props files.
- Output folder is changed to ‘$(SolutionDir)build\$(Platform)\$(Configuration)\’ for later use caffe as a lib in other projects.
- Noted that ‘compute_50,sm_50′ in the 2 .props files means the generation of CUDA to use. ’50’ works for Maxwell GPU. Use ’20’ for Fermi and ’30’ for Kepler.
- If you changed things in the .props files, you need to close and reopen your vs solution to take effect.
- Right click on ‘caffe’ and click ‘Property’. In ‘General’ -> ‘Configuration Type’, make sure it’s ‘Application (.exe)’.
- Make sure it’s Release and x64. Right click on ‘caffe’ and click ‘compile’. ‘caffe.exe’ will be generated to ‘build/x64/Release’ folder.
- Copy ‘opencv_ffmpeg300_64.dll’, ‘opencv_world300.dll’ from OpenCV to the folder of ‘caffe.exe’
- Copy the following from 3rdparty folder (be aware of the configuration, i.e. Debug/Release, Win32/x86) to the same folder of ‘caffe.exe’:
- Run ‘caffe.exe’, should display like this:
Test on MNIST
- Go to ‘caffe/data/mnist’ folder and run ‘get_mnist.bat’ to fetch dataset for MNIST.
- Go to ‘caffe/examples/mnist’ folder and
- run ‘create_mnist-leveldb.bat’ to convert MNIST dataset to leveldb format.
- run ‘train_lenet-leveldb.bat’ to start the training.
- There’s a ‘lmdb’ version but it does NOT work. Fix was given by Kazukuni Hosoi here but I didn’t try it myself. Not a fan of lmdb.
- (II) Use caffe as lib like OpenCV in a normal vs2013 project.
Caffe is a deep learning framework popular in Linux with Python or Matlab interface. I just managed to compile Caffe in Windows, and I think it’s worth sharing. niuzhiheng’s GitHub was of great help. This repository is organized in a way that future update merging from Caffe’s GitHub would be very straight forward. For quick setup and usage go to my GitHub.
For quick and dirty start, go to Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup, where I’ll provide 1) the modified file that can be compiled in windows right away; 2) the vs2013 project that I’m currently using.
Below is my step by step record to compile Caffe from source in Windows 8.1 + vs2013 + OpenCV 2.4.9 + CUDA 6.5.
- Download source from Caffe’s GitHub and unzip.
- Create a new project in Visual Studio 2013.
- File -> New -> Project
- Choose Win32 Console Application
- Set location to the root of Caffe
- Change Name to caffe (the generated exe file later is named after the project name, so please use this low case word)
- Click OK
- Check Empty project, and then Finish
- Change the platform from Win32 to
- Build -> Configuration Manager -> Active solution platform -> new -> x64 -> OK
- An empty project called caffe is generated into the root of Caffe now. To compile big project like Caffe, good practice is to compile a few *.cpp files first and figure out dependencies one by one.
- Drag files in caffe/src/caffe to Source Files in VS.
- Let’s set some directories of the project.
- In Property Manager, both Debug|x64 and Release|x64 need to be set:
- In Configuration Properties -> General, set Output Directory to ‘../bin’. The generated exe files will be easy to use later. Change for both Debug and Release mode.
- In Configuration Properties -> C/C++ -> General, edit Additional Include Directories (Both Debug and Release) to include:
- Make sure to check Inherit from parent or project defaults.
- Now let’s fix dependencies one by one: (My pre-built 3rdparty folder can be downloaded: 3rdparty.zip, if you are using Windows 64bit + vs2013)
- CUDA 6.5
- Download and install (You have to have a GPU on your PC lol)
- OpenCV 2.4.9 + CUDA 6.5
- Pre-built OpenCV libraries should work. If you want to build OpenCV with CUDA to enable OpenCV’s GPU support such as GpuMat, a tutorial can be found here. Seems it’s not required by Caffe though.
- Add OpenCV + CUDA + Boost into the project:
- I used to put these 3 libraries outside Caffe folder because they are so useful.
- Add include path to Additional Include Directories: (Both Debug and Release)
$(CUDA_PATH_V6_5)\include $(OPENCV_X64_VS2013_2_4_9)\include $(OPENCV_X64_VS2013_2_4_9)\include\opencv $(BOOST_1_56_0)
- CUDA_PATH_V6_5 is added by CUDA initialization. OPENCV_X64_VS2013_2_4_9 and BOOST_1_56_0 need to be added to the Environment Variables Also, the bin (e.g. /to/opencv-2.4.9/x64-vs2013/bin) folder of OpenCV need to be added to Path. You may need to log off to enable them.
- Add lib path to Additional Library Directories in Configuration Properties -> Linker -> General: (Both Debug and Release)
$(CUDA_PATH_V6_5)\lib\$(PlatformName) $(OPENCV_X64_VS2013_2_4_9)\lib $(BOOST_1_56_0)\lib64-msvc-12.0
- Add libraries to Additional Dependencies in Configuration Properties -> Linker -> Input
- GFlags + GLog + ProtoBuf + LevelDB
- Download source code from the internet.
- Use CMake to generate .sln for vs2013. Remember to set “CMAKE_INSTALL_PREFIX”, which is where the output files will be generated by build “INSTALL”.
- Build in vs2013. Usually build “BUILD_ALL” first, then “INSTALL”. Both Debug and Release mode.
- Copy compiled files to caffe/3rdparty. Debug versions should be renamed “+d” before copy, e.g. “lib” -> “gflagsd.lib”.
- Google’s code are very good maintained. Nothing much to say.
- Download source code form the internet.
- In CMake, enable HDF5_BUILD_HL_LIB.
- Copy compiled files to caffe/3rdparty.
- Download source code from the internet.
- In Visual Studio 2013, File -> New -> Project From Existing Code…
- In c, a header file called unistd.h is needed. A walk around is found here. Or one can download here: unistd.h, getopt.h and getopt.c.
- The compiled LMDB has some problem which I’ll mention later.
- Copy some .dll files so that caffe can run
- Copy libglog.dll from GLog to caffe/bin.
- Copy libopenblas.dll from OpenBLAS to caffe/bin.
- Copy msvcp120.dll and msvcr120.dll from HDF5 to caffe/bin.
- More paths added to Additional Include Directories (Both Debug and Release):
../3rdparty/include; ../3rdparty/include/openblas; ../3rdparty/include/hdf5; ../3rdparty/include/lmdb;
- More paths added to Additional Library Directories (Both Debug and Release):
- More files added to Additional Dependencies:
- My pre-built 3rdparty folder can be downloaded: 3rdparty.zip, if you are using Windows 64bit + vs2013.
- Now compile “common.cpp” to fix errors.
- Add “#include <process.h>” to common.cpp fix “getpid” error.
- Add “_CRT_SECURE_NO_WARNINGS” to Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions to fix “fopen_s” error.
- Change the line used “getpid” in common.cpp to fix POSIX error.
// port for Win32 #ifndef _MSC_VER pid = getpid(); #else pid = _getpid(); #endif
- common.cpp should be compiled without error now.
- Now compile “blob.cpp”
- To enable #include “caffe/proto/caffe.pb.h”. We need to generate it from caffe.proto.
- Put proto.exe in caffe/3rdparty/bin folder.
- Put GeneratePB.bat in caffe/scripts folder.
- Add the line below (with the quote mark) to Configuration Properties -> Build Events -> Pre-Build Event -> Command Line:
- Right click caffe to build to project, you will see “caffe.pb.h is being generated” and “caffe_pretty_print.pb.h is being generated”
- Now blop.cpp can be compiled without errors.
- Now compile “net.cpp”
- “unistd.h” missing error can be fixed like above. (also included in 3rdparty.zip already)
- “mkstemp” missing error can be fixed according to this (download here: mkstep.h and mkstep.cpp or find in 3rdparty.zip)
- Add “#include “mkstemp.h”” to io.hpp.
- Change the line used “close” the below in io.hpp to fix close error. (Don’t do “#define close _close” in io.hpp. Such define are dangerous in any .hpp files, but acceptable in .cpp files)
#ifndef _MSC_VER close(fd); #else _close(fd); #endif
- Change the line used “mkdtemp” function to below in io.hpp (to use _mktemp_s as a walk-around for mkdtemp):
#ifndef _MSC_VER char* mkdtemp_result = mkdtemp(temp_dirname_cstr); #else errno_t mkdtemp_result = _mktemp_s(temp_dirname_cstr, sizeof(temp_dirname_cstr)); #endif
- Now compile “solver.cpp”
- Add these line to solver.cpp to fix “snprintf” error to below:
// port for Win32 #ifdef _MSC_VER #define snprintf sprintf_s #endif
- Now compile files in caffe/src/layers
- Create a folder in Source Files and drag ONE .cu files in layer folder into it.
- Enable CUDA 6.5(.targets, .props) in PROJECT -> Build Customization.
- In the property of any .cu file, change Item Type to CUDA C/C++
- Drag the rest files in layer folder to the project. All new added .cu file will have its Item Type Otherwise you have to change them one by one.
- In bnll_layer.cu, change “const float kBNLL_THRESHOLD = 50.;” to “#define kBNLL_THRESHOLD 50.0” to avoid error.
- Now every files in layer folder compiles fine.
- Now compile files in caffe/src/util folder
- Goto ReadProtoFromBinaryFile function. Change “O_RDONLY” to “O_RDONLY | O_BINARY”. When loading a binary file in Windows, you have to specify that it’s binary. Otherwise you might have error loading a *_mean.binaryproto file later.
- Add these lines to io.cpp file to avoid POSIX error:
// port for Win32 #ifdef _MSC_VER #define open _open
#define close _close #endif
- Change “close()” to “_close()” manually expect the “file.close()”.
- Add these lines to math_functions.cpp to fix __builtin_popcount and __builtin_popcountl error:
#define __builtin_popcount __popcnt #define __builtin_popcountl __popcnt
- Now compile files in caffe/src/proto
- Previously 2 .cc files were generated by GeneratePB.bat.
- Create a folder in Source Files and drag 2 .cc files (“caffe.pb.cc” and “caffe_pretty_print.pb.cc”) into it.
- Add “-D_SCL_SECURE_NO_WARNINGS” to Configuration Properties -> C/C++ -> Command Line (Both Debug and Release mode) to fix ‘std::_Copy_impl’ unsafe error.
- Now we have every file compliable in Visual Studio.
- Finally compile caffe.cpp in caffe/tools folder
- Drag caffe/tools/caffe.cpp file into Visual Studio’s Source Files
- Right click project name caffe, and BUILD!
- Now everything should work! If you got some linking error, check the missing function’s name to decide what library is missing.
- Change to Release mode and BUILD again to get a caffe/bin/caffe.exe of Release mode.
- Copy caffe.exe to get a backup, e.g. caffe-backup.exe. For if you build the project again, caffe.exe will be overwritten.
- Let’s do a QUICK TEST on MNIST!
- Get MNIST Dataset
- Generate convert_mnist_data.exe
- Check the project in Visual Studio is in Release|x64.
- Exclude “caffe.cpp” from the project.
- Drag “caffe/examples/mnist/convert_mnist_data.cpp” to the project.
- Add these lines in convert_mnist_data.cpp:
// port for Win32 #ifdef _MSC_VER #include <direct.h> #define snprintf sprintf_s #endif
- Change “mkdir” to “_mkdir” in convert_mnist_data.cpp:
// port for Win32 #ifndef _MSC_VER CHECK_EQ(mkdir(db_path, 0744), 0) << “mkdir ” << db_path << “failed”; #else CHECK_EQ(_mkdir(db_path), 0) << “mkdir ” << db_path << “failed”; #endif
- The “potentially uninitialized local pointer variable” error can be fixed by initialize db, mdb_env and mdb_txn with NULL in convert_mnist_data.cpp. Change “MDB_env *mdb_env;” to “MDB_env *mdb_env = NULL;”, and similar for “mdb_txn” and “db”.
- BUILD the project to get caffe.exe in caffe/bin. Rename it to convert_mnist_data.exe.
- Create LevelDB data for training
- Put create_mnist.bat in caffe/examples/mnist and run. Here we generate mnist_train_leveldb and mnist_test_leveldb. If lmdb was used as backend, error occurs. Fortunately, leveldb works fine. It would be great if someone can fix the error of lmdb.
- Let’s get caffe.exe back from the copied caffe-backup.exe if you copied it before.
- Now modify caffe/examples/mnist/lenet_train_test.prototxt, substitute “lmdb” with “leveldb”, because we generate “leveldb” data instead of “lmdb”.
- Do training
- Put train_lenet.bat in caffe/examples/mnist and run. Cool! The training is on! The accuracy is around 0.98 after hundreds of iterations.
Update – 2015.1.26
- The above steps didn’t include cuDNN acceleration.
- One can add “USE_CUDNN” to Preprocessor of the project to enable cuDNN. (Currently Caffe works with cuDNN v1. The set-up is pretty straight forward. Noted that the “Code Generation” for CUDA should be at least “compute_30, sm_30”.)
- My practice showed that for LeNet layout, testing 800 images with the size of 32*32 (excluding the time for reading input images):
- CPU takes around 400~500 ms
- GPU takes around 50 ms
- cuDNN takes around 15 ms
I used to use OpenCV 2.4.6 + CUDA 5.0 + Visual Studio 2010. Recently I decided to upgrade to Visual Studio 2013. Yet as you may noticed that the CUDA 5.0 does not support vs2013, so re-compile OpenCV with newer version of CUDA is a must.
Below is the tutorial of how to compile OpenCV code from source. If you want a quick setup:
- Pre-built OpenCV library WITHOUT CUDA is here;
- Pre-built OpenCV 2.4.9 + CUDA 6.5 + vs2013 is here (Noted that the architecture of my GPU is Kepler, supporting up to 3.5). For other versions you may need to follow the steps below.
The steps below are similar to:
with some explanation and a few tricks to make the compiling really works.
- Latest CMAKE
- I used the CMAKE 3.0.2 Windows Win32 Installer
- Latest CUDA
- I used CUDA v6.5 (Noted that CUDA v6.5 has a special version that supports Maxwell architecture)
- OpenCV 2.4.9 Source Files
- Notice that from 2.4.9 to the latest 3.0.0, OpenCV changed a plenty of functions and header files. It is your own decision that which version to use. For me, I choose 2.4.9 because I have functions related to CUDA that cannot upgrade to 3.0.0.
- Intel TBB
- For building OpenCV Core.
- Python 2.7
- Visual Studio 2013
- Open CMAKE
- Choose Source Folder
- Choose Output Folder
- Press ‘Advanced’
- Choose compiler
- Press ‘Configure’
- Choose ‘Visual Studio 12 2013 Win64’
- CMAKE Setting No.1 – New configuration entry will be shown in RED.
- Cancel ‘BUILD_DOCS’ and ‘BUILD_EXAMPLES’
- Check ‘CMAKE_LINKER’, make sure it’s Visual Studio 12.0 for vs2013
- Cancel ‘CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE’, otherwise you’ll have some CUDA related errors.
- Choose ‘WITH_CUBLAS’, ‘WITH_CUDA’, ‘WITH_OPENGL’, ‘WITH_TBB’ (TBB is optional)
- Press ‘Configure’ to refresh
- CMAKE Setting No.2
- Set include path for tbb
- My path is “D:\toolkits\tbb43_20140724oss\include”
- Press ‘Configure’ to refresh
- The path for tbb lib will be added, but it’s not correct. You need to make sure that ‘Debug’ and ‘Release’ is inside that path directly.
- My path is “D:/toolkits/tbb43_20140724oss/lib/intel64”
- I have to add ‘vc12’ in the end: “D:/toolkits/tbb43_20140724oss/lib/intel64/vc12”
- Press ‘Configure’ to refresh until nothing is in RED
- Press ‘Generate’
- OpenCV.sln file will be generated to your Output Folder
- Modify NCV.cu
- Add ‘#include <algorithm>’ to “opencv-2.4.9\modules\gpu\src\nvidia\core\NCV.cu”. Otherwise you’ll have ‘max’ undefined error.
- Compile OpenCV.sln
- If any of your libraries (OpenCV, tbb, Python, etc.) is in “C:\Program Files”, you need to run Visual Studio 2013 as administrator before you open the solution file with it.
- I suggest building the ‘opencv_core’ and ‘opencv_gpu’ first. Otherwise it’ll take hours before you find an error.
- You can right click ‘ALL_BUILD’ to build the entire OpenCV.
- After that build ‘INSTALL’
- Build ‘ALL_BUILD’ and ‘INSTALL’ in Release mode again.
- The building took around 1~2 hours for each mode on my PC.
- You should have 1 error in Debug mode and no error in Release mode for ‘ALL_BUILD’
- No error for ‘INSTALL’
- You will find the final ‘include’ and libraries in your ‘Output Folder’\install
- Mine is “D:\toolkits\opencv-2.4.9\build-vs2013\install”
Follow-up about using the libraries:
- In objdetect.hpp, I have an error about ‘std::min’.
- I changed it to ‘min’, it worked.
- In matrix.h, I have an error about the free() function.
- I changed it to ‘_free()’, it worked.
- tbb’s dll path needs to be added to the system path
- Mine is “D:\toolkits\tbb43_20140724oss\bin\intel64\vc12”