├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── README.md ├── deeplandmark ├── 1_F.caffemodel ├── 1_F.prototxt ├── 2_LE1.caffemodel ├── 2_LE1.prototxt ├── 2_LE2.caffemodel ├── 2_LE2.prototxt ├── 2_LM1.caffemodel ├── 2_LM1.prototxt ├── 2_LM2.caffemodel ├── 2_LM2.prototxt ├── 2_N1.caffemodel ├── 2_N1.prototxt ├── 2_N2.caffemodel ├── 2_N2.prototxt ├── 2_RE1.caffemodel ├── 2_RE1.prototxt ├── 2_RE2.caffemodel ├── 2_RE2.prototxt ├── 2_RM1.caffemodel ├── 2_RM1.prototxt ├── 2_RM2.caffemodel └── 2_RM2.prototxt ├── ex.cpp ├── ex.hpp ├── fix.png ├── haarcascade_frontalface_alt.xml ├── main.cpp └── test.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | build/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "mini-caffe"] 2 | path = mini-caffe 3 | url = https://github.com/luoyetx/mini-caffe.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(ex) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | find_package(OpenCV REQUIRED) 5 | include(mini-caffe/mini-caffe.cmake) 6 | 7 | add_executable(ex ex.hpp ex.cpp main.cpp) 8 | target_link_libraries(ex caffe ${OpenCV_LIBS}) 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | caffe-ex 2 | ======== 3 | 4 | **This project is merged into Mini-Caffe, Check [here](https://github.com/luoyetx/mini-caffe/tree/master/example).** 5 | 6 | 利用 mini-caffe 在 Windows VS 开发测试 Caffe 相关项目。 7 | 8 | ### mini-caffe 安装 9 | 10 | 参考 mini-caffe 安装文档,编译生成 mini-caffe 依赖的第三方库。 11 | 12 | ### 工程配置(参考本项目) 13 | 14 | 由于目前的静态库局限性和为调试代码的方便性(顺便学习 Caffe 源码),我们将 mini-caffe 作为工程项目的子项目(如果你做版本控制就将 mini-caffe 作为本 git 项目的子 git 项目存在,不然就直接拷贝一份到现在的工程目录下),直接参与整个工程的构建。具体配置可参考本项目。 15 | 16 | ``` 17 | git submodule add https://github.com/luoyetx/mini-caffe.git mini-caffe 18 | ``` 19 | 20 | 可以将 mini-caffe 作为当前git项目的子项目,方便后期更新 mini-caffe 的代码。 21 | 22 | 假设当前项目为 caffe-ex,我们设置源码目录树如下: 23 | 24 | ``` 25 | + caffe-ex 26 | |__CMakeLists.txt 27 | |__mini-caffe 28 | | |__*** 29 | | |__mini-caffe.cmake 30 | | |__*** 31 | | 32 | |__ex.cpp 33 | |__ex.hpp 34 | |__main.cpp 35 | |__*** 36 | ``` 37 | 38 | caffe-ex 的 CMakeLists.txt 写法参考本项目。生成工程文件便可以开始开发了。 39 | -------------------------------------------------------------------------------- /deeplandmark/1_F.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/1_F.caffemodel -------------------------------------------------------------------------------- /deeplandmark/1_F.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict all landmark in LEVEL-1 2 | layer { 3 | name: "data" 4 | type: "Input" 5 | top: "data" 6 | input_param { 7 | shape: { 8 | dim: 1 9 | dim: 1 10 | dim: 39 11 | dim: 39 12 | } 13 | } 14 | } 15 | layer { 16 | name: "conv1" 17 | type: "Convolution" 18 | bottom: "data" 19 | top: "conv1" 20 | param { 21 | lr_mult: 1 22 | } 23 | param { 24 | lr_mult: 2 25 | } 26 | convolution_param { 27 | num_output: 20 28 | kernel_size: 4 29 | weight_filler { 30 | type: "xavier" 31 | } 32 | bias_filler { 33 | type: "constant" 34 | } 35 | } 36 | } 37 | layer { 38 | name: "relu1" 39 | type: "ReLU" 40 | bottom: "conv1" 41 | top: "conv1" 42 | } 43 | layer { 44 | name: "pool1" 45 | type: "Pooling" 46 | bottom: "conv1" 47 | top: "pool1" 48 | pooling_param { 49 | pool: MAX 50 | kernel_size: 2 51 | stride: 2 52 | } 53 | } 54 | layer { 55 | name: "conv2" 56 | type: "Convolution" 57 | bottom: "pool1" 58 | top: "conv2" 59 | param { 60 | lr_mult: 1 61 | } 62 | param { 63 | lr_mult: 2 64 | } 65 | convolution_param { 66 | num_output: 40 67 | kernel_size: 3 68 | weight_filler { 69 | type: "xavier" 70 | } 71 | bias_filler { 72 | type: "constant" 73 | } 74 | } 75 | } 76 | layer { 77 | name: "relu2" 78 | type: "ReLU" 79 | bottom: "conv2" 80 | top: "conv2" 81 | } 82 | layer { 83 | name: "pool2" 84 | type: "Pooling" 85 | bottom: "conv2" 86 | top: "pool2" 87 | pooling_param { 88 | pool: MAX 89 | kernel_size: 2 90 | stride: 2 91 | } 92 | } 93 | layer { 94 | name: "conv3" 95 | type: "Convolution" 96 | bottom: "pool2" 97 | top: "conv3" 98 | param { 99 | lr_mult: 1 100 | } 101 | param { 102 | lr_mult: 2 103 | } 104 | convolution_param { 105 | num_output: 60 106 | kernel_size: 3 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu3" 117 | type: "ReLU" 118 | bottom: "conv3" 119 | top: "conv3" 120 | } 121 | layer { 122 | name: "pool3" 123 | type: "Pooling" 124 | bottom: "conv3" 125 | top: "pool3" 126 | pooling_param { 127 | pool: MAX 128 | kernel_size: 2 129 | stride: 2 130 | } 131 | } 132 | layer { 133 | name: "conv4" 134 | type: "Convolution" 135 | bottom: "pool3" 136 | top: "conv4" 137 | param { 138 | lr_mult: 1 139 | } 140 | param { 141 | lr_mult: 2 142 | } 143 | convolution_param { 144 | num_output: 80 145 | kernel_size: 2 146 | weight_filler { 147 | type: "xavier" 148 | } 149 | bias_filler { 150 | type: "constant" 151 | } 152 | } 153 | } 154 | layer { 155 | name: "relu4" 156 | type: "ReLU" 157 | bottom: "conv4" 158 | top: "conv4" 159 | } 160 | layer { 161 | name: "pool3_flat" 162 | type: "Flatten" 163 | bottom: "pool3" 164 | top: "pool3_flat" 165 | } 166 | layer { 167 | name: "conv4_flat" 168 | type: "Flatten" 169 | bottom: "conv4" 170 | top: "conv4_flat" 171 | } 172 | layer { 173 | name: "concat" 174 | type: "Concat" 175 | bottom: "pool3_flat" 176 | bottom: "conv4_flat" 177 | top: "faker" 178 | concat_param { 179 | concat_dim: 1 180 | } 181 | } 182 | layer { 183 | name: "fc1" 184 | type: "InnerProduct" 185 | bottom: "faker" 186 | top: "fc1" 187 | param { 188 | lr_mult: 1 189 | } 190 | param { 191 | lr_mult: 2 192 | } 193 | inner_product_param { 194 | num_output: 120 195 | weight_filler { 196 | type: "xavier" 197 | } 198 | bias_filler { 199 | type: "constant" 200 | } 201 | } 202 | } 203 | layer { 204 | name: "relu_fc1" 205 | type: "ReLU" 206 | bottom: "fc1" 207 | top: "fc1" 208 | } 209 | layer { 210 | name: "fc2" 211 | type: "InnerProduct" 212 | bottom: "fc1" 213 | top: "fc2" 214 | param { 215 | lr_mult: 1 216 | } 217 | param { 218 | lr_mult: 2 219 | } 220 | inner_product_param { 221 | num_output: 10 222 | weight_filler { 223 | type: "xavier" 224 | } 225 | bias_filler { 226 | type: "constant" 227 | } 228 | } 229 | } 230 | layer { 231 | name: "relu_fc2" 232 | type: "ReLU" 233 | bottom: "fc2" 234 | top: "fc2" 235 | } 236 | -------------------------------------------------------------------------------- /deeplandmark/2_LE1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_LE1.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_LE1.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_LE1" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_LE2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_LE2.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_LE2.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_LE2" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_LM1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_LM1.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_LM1.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_LM1" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_LM2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_LM2.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_LM2.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_LM2" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_N1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_N1.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_N1.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_N1" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_N2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_N2.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_N2.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_N2" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_RE1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_RE1.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_RE1.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_RE1" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_RE2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_RE2.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_RE2.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_RE2" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_RM1.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_RM1.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_RM1.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_RM1" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /deeplandmark/2_RM2.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/deeplandmark/2_RM2.caffemodel -------------------------------------------------------------------------------- /deeplandmark/2_RM2.prototxt: -------------------------------------------------------------------------------- 1 | # This file gives the CNN model to predict landmark in LEVEL-2 2 | name: "landmark_2_RM2" 3 | layer { 4 | name: "data" 5 | type: "Input" 6 | top: "data" 7 | input_param { 8 | shape: { 9 | dim: 1 10 | dim: 1 11 | dim: 15 12 | dim: 15 13 | } 14 | } 15 | } 16 | layer { 17 | name: "conv1" 18 | type: "Convolution" 19 | bottom: "data" 20 | top: "conv1" 21 | param { 22 | lr_mult: 1 23 | } 24 | param { 25 | lr_mult: 2 26 | } 27 | convolution_param { 28 | num_output: 20 29 | kernel_size: 4 30 | weight_filler { 31 | type: "xavier" 32 | } 33 | bias_filler { 34 | type: "constant" 35 | } 36 | } 37 | } 38 | layer { 39 | name: "relu1" 40 | type: "ReLU" 41 | bottom: "conv1" 42 | top: "conv1" 43 | } 44 | layer { 45 | name: "pool1" 46 | type: "Pooling" 47 | bottom: "conv1" 48 | top: "pool1" 49 | pooling_param { 50 | pool: MAX 51 | kernel_size: 2 52 | stride: 2 53 | } 54 | } 55 | layer { 56 | name: "conv2" 57 | type: "Convolution" 58 | bottom: "pool1" 59 | top: "conv2" 60 | param { 61 | lr_mult: 1 62 | } 63 | param { 64 | lr_mult: 2 65 | } 66 | convolution_param { 67 | num_output: 40 68 | kernel_size: 3 69 | weight_filler { 70 | type: "xavier" 71 | } 72 | bias_filler { 73 | type: "constant" 74 | } 75 | } 76 | } 77 | layer { 78 | name: "relu2" 79 | type: "ReLU" 80 | bottom: "conv2" 81 | top: "conv2" 82 | } 83 | layer { 84 | name: "pool2" 85 | type: "Pooling" 86 | bottom: "conv2" 87 | top: "pool2" 88 | pooling_param { 89 | pool: MAX 90 | kernel_size: 2 91 | stride: 2 92 | } 93 | } 94 | layer { 95 | name: "fc1" 96 | type: "InnerProduct" 97 | bottom: "pool2" 98 | top: "fc1" 99 | param { 100 | lr_mult: 1 101 | } 102 | param { 103 | lr_mult: 2 104 | } 105 | inner_product_param { 106 | num_output: 60 107 | weight_filler { 108 | type: "xavier" 109 | } 110 | bias_filler { 111 | type: "constant" 112 | } 113 | } 114 | } 115 | layer { 116 | name: "relu_fc1" 117 | type: "ReLU" 118 | bottom: "fc1" 119 | top: "fc1" 120 | } 121 | layer { 122 | name: "fc2" 123 | type: "InnerProduct" 124 | bottom: "fc1" 125 | top: "fc2" 126 | param { 127 | lr_mult: 1 128 | } 129 | param { 130 | lr_mult: 2 131 | } 132 | inner_product_param { 133 | num_output: 2 134 | weight_filler { 135 | type: "xavier" 136 | } 137 | bias_filler { 138 | type: "constant" 139 | } 140 | } 141 | } 142 | layer { 143 | name: "relu_fc2" 144 | type: "ReLU" 145 | bottom: "fc2" 146 | top: "fc2" 147 | } 148 | -------------------------------------------------------------------------------- /ex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ex.hpp" 8 | 9 | using namespace cv; 10 | using namespace std; 11 | using namespace caffe; 12 | 13 | 14 | BBox::BBox(int x, int y, int w, int h) { 15 | this->x = x; this->y = y; 16 | this->width = w; this->height = h; 17 | this->rect = Rect(x, y, w, h); 18 | } 19 | 20 | BBox::BBox(const Rect &rect) { 21 | this->x = rect.x; this->y = rect.y; 22 | this->width = rect.width; this->height = rect.height; 23 | this->rect = rect; 24 | } 25 | 26 | void BBox::Project(const vector &absLandmark, vector &relLandmark) const { 27 | assert(absLandmark.size() == relLandmark.size()); 28 | for (int i = 0; i < absLandmark.size(); i++) { 29 | const Point2f &point1 = absLandmark[i]; 30 | Point2f &point2 = relLandmark[i]; 31 | point2.x = (point1.x - this->x) / this->width; 32 | point2.y = (point1.y - this->y) / this->height; 33 | } 34 | } 35 | 36 | void BBox::ReProject(const vector &relLandmark, vector &absLandmark) const { 37 | assert(relLandmark.size() == absLandmark.size()); 38 | for (int i = 0; i < relLandmark.size(); i++) { 39 | const Point2f &point1 = relLandmark[i]; 40 | Point2f &point2 = absLandmark[i]; 41 | point2.x = point1.x*this->width + this->x; 42 | point2.y = point1.y*this->height + this->y; 43 | } 44 | } 45 | 46 | BBox BBox::subBBox(float left, float right, float top, float bottom) const { 47 | assert(right>left && bottom>top); 48 | float x, y, w, h; 49 | x = this->x + left*this->width; 50 | y = this->y + top*this->height; 51 | w = this->width*(right - left); 52 | h = this->height*(bottom - top); 53 | return BBox(x, y, w, h); 54 | } 55 | 56 | 57 | CNN::CNN(const string &network, const string &model) { 58 | cnn = new Net(network); 59 | assert(cnn); 60 | cnn->CopyTrainedLayersFrom(model); 61 | } 62 | 63 | vector CNN::forward(const Mat &data, const string &layer) { 64 | shared_ptr blob = cnn->blob_by_name("data"); 65 | float *blob_data = blob->mutable_cpu_data(); 66 | const float *ptr = NULL; 67 | for (int i = 0; i < data.rows; i++) { 68 | ptr = data.ptr(i); 69 | for (int j = 0; j < data.cols; j++) { 70 | blob_data[i*data.cols + j] = ptr[j]; 71 | } 72 | } 73 | 74 | cnn->Forward(); 75 | 76 | shared_ptr landmarks = cnn->blob_by_name(layer); 77 | vector points(landmarks->count() / 2); 78 | for (int i = 0; i < points.size(); i++) { 79 | Point2f &point = points[i]; 80 | point.x = landmarks->data_at(0, 2 * i, 0, 0); 81 | point.y = landmarks->data_at(0, 2 * i + 1, 0, 0); 82 | } 83 | return points; 84 | } 85 | 86 | 87 | void FaceDetector::LoadXML(const string &path) { 88 | bool res = cc.load(path); 89 | assert(res); 90 | } 91 | 92 | int FaceDetector::DetectFace(const Mat &img, vector &rects) { 93 | assert(img.type() == CV_8UC1); 94 | Mat gray(img.rows, img.cols, CV_8UC1); 95 | img.copyTo(gray); 96 | 97 | cc.detectMultiScale(gray, rects, 1.2, 2, 0 | CV_HAAR_SCALE_IMAGE, \ 98 | Size(30, 30), Size(gray.cols, gray.rows)); 99 | 100 | return rects.size(); 101 | } 102 | 103 | void Landmarker::LoadModel(const string &path) { 104 | string network = path + "/1_F.prototxt"; 105 | string model = path + "/1_F.caffemodel"; 106 | F = new CNN(network, model); 107 | string networks[10] = { "/2_LE1.prototxt", "/2_LE2.prototxt", "/2_RE1.prototxt", "/2_RE2.prototxt", \ 108 | "/2_N1.prototxt", "/2_N2.prototxt", "/2_LM1.prototxt", "/2_LM2.prototxt", \ 109 | "/2_RM1.prototxt", "/2_RM2.prototxt" }; 110 | string models[10] = { "/2_LE1.caffemodel", "/2_LE2.caffemodel", "/2_RE1.caffemodel", "/2_RE2.caffemodel", \ 111 | "/2_N1.caffemodel", "/2_N2.caffemodel", "/2_LM1.caffemodel", "/2_LM2.caffemodel", \ 112 | "/2_RM1.caffemodel", "/2_RM2.caffemodel" }; 113 | for (int i = 0; i < 5; i++) { 114 | network = path + networks[2 * i]; 115 | model = path + models[2 * i]; 116 | level2[2 * i] = new CNN(network, model); 117 | network = path + networks[2 * i + 1]; 118 | model = path + models[2 * i + 1]; 119 | level2[2 * i + 1] = new CNN(network, model); 120 | } 121 | } 122 | 123 | Mat GetPatch(const Mat &img, const BBox &bbox, const Point2f &point, \ 124 | double padding, BBox& patch_bbox) { 125 | double x = bbox.x + point.x*bbox.width; 126 | double y = bbox.y + point.y*bbox.height; 127 | Rect roi; 128 | roi.x = x - bbox.width*padding; 129 | roi.y = y - bbox.height*padding; 130 | roi.width = 2 * padding*bbox.width; 131 | roi.height = 2 * padding*bbox.height; 132 | patch_bbox = BBox(roi); 133 | return img(roi).clone(); 134 | } 135 | 136 | Mat process(const Mat &img, Size size) { 137 | Mat data; 138 | resize(img, data, size); 139 | data.convertTo(data, CV_32FC1); 140 | Scalar meanScalar, stdScalar; 141 | cv::meanStdDev(data, meanScalar, stdScalar); 142 | float mean = meanScalar.val[0]; 143 | float std = stdScalar.val[0]; 144 | data = (data - mean) / std; 145 | return data; 146 | } 147 | 148 | vector Landmarker::DetectLandmark(const Mat &img, const BBox &bbox){ 149 | assert(img.type() == CV_8UC1); 150 | Mat data = process(img(bbox.rect), Size(39, 39)); 151 | // level 1 152 | vector landmarks = F->forward(data, "fc2"); 153 | // level 2 154 | for (int i = 0; i < 5; i++) { 155 | Point2f point = landmarks[i]; 156 | BBox patch_bbox(0, 0, 0, 0); 157 | 158 | Mat roi = GetPatch(img, bbox, point, 0.16, patch_bbox); 159 | data = process(roi, Size(15, 15)); 160 | CNN *net = level2[2 * i]; 161 | vector res = net->forward(data, "fc2"); 162 | patch_bbox.ReProject(res, res); 163 | bbox.Project(res, res); 164 | Point2f p1 = res[0]; 165 | 166 | roi = GetPatch(img, bbox, point, 0.18, patch_bbox); 167 | data = process(roi, Size(15, 15)); 168 | net = level2[2 * i + 1]; 169 | res = net->forward(data, "fc2"); 170 | patch_bbox.ReProject(res, res); 171 | bbox.Project(res, res); 172 | Point2f p2 = res[0]; 173 | 174 | landmarks[i] = Point2f((p1.x + p2.x) / 2., (p1.y + p2.y) / 2.); 175 | } 176 | bbox.ReProject(landmarks, landmarks); 177 | return landmarks; 178 | } 179 | -------------------------------------------------------------------------------- /ex.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __EX_HPP__ 2 | #define __EX_HPP__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | struct BBox { 12 | int x, y; 13 | int width, height; 14 | cv::Rect rect; 15 | 16 | BBox(int x, int y, int w, int h); 17 | BBox(const cv::Rect &rect); 18 | BBox(BBox const &other); 19 | void Project(const std::vector &absLandmark, std::vector &relLandmark) const; 20 | void ReProject(const std::vector &realLandmark, std::vector &absLandmark) const; 21 | BBox subBBox(float left, float right, float top, float bottom) const; 22 | }; 23 | 24 | struct FaceDetector { 25 | cv::CascadeClassifier cc; 26 | 27 | void LoadXML(const std::string &path); 28 | int DetectFace(const cv::Mat &img, std::vector &rects); 29 | }; 30 | 31 | struct CNN { 32 | caffe::Net *cnn; 33 | 34 | CNN(const std::string &network, const std::string &model); 35 | std::vector forward(const cv::Mat &data, const std::string &layer); 36 | }; 37 | 38 | struct Landmarker { 39 | CNN *F; 40 | CNN *level2[10]; 41 | 42 | void LoadModel(const std::string &path); 43 | std::vector DetectLandmark(const cv::Mat &img, const BBox &bbox); 44 | }; 45 | 46 | #endif // __EX_HPP__ 47 | -------------------------------------------------------------------------------- /fix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/fix.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ex.hpp" 8 | 9 | using namespace cv; 10 | using namespace std; 11 | using namespace caffe; 12 | 13 | /*! \brief Timer */ 14 | class Timer { 15 | using Clock = std::chrono::high_resolution_clock; 16 | public: 17 | /*! \brief start or restart timer */ 18 | inline void Tic() { 19 | start_ = Clock::now(); 20 | } 21 | /*! \brief stop timer */ 22 | inline void Toc() { 23 | end_ = Clock::now(); 24 | } 25 | /*! \brief return time in ms */ 26 | inline double Elasped() { 27 | auto duration = std::chrono::duration_cast(end_ - start_); 28 | return duration.count(); 29 | } 30 | 31 | private: 32 | Clock::time_point start_, end_; 33 | }; 34 | 35 | void showLandmarks(Mat &image, Rect &bbox, vector &landmarks) { 36 | Mat img; 37 | image.copyTo(img); 38 | rectangle(img, bbox, Scalar(0, 0, 255), 2); 39 | for (int i = 0; i < landmarks.size(); i++) { 40 | Point2f &point = landmarks[i]; 41 | circle(img, point, 2, Scalar(0, 255, 0), -1); 42 | } 43 | imshow("landmark", img); 44 | waitKey(0); 45 | } 46 | 47 | int main(int argc, char *argv[]) { 48 | 49 | caffe::Caffe::set_mode(caffe::Caffe::CPU); 50 | 51 | FaceDetector fd; 52 | Landmarker lder; 53 | fd.LoadXML("../haarcascade_frontalface_alt.xml"); 54 | lder.LoadModel("../deeplandmark"); 55 | 56 | Mat image; 57 | Mat gray; 58 | image = imread("../test.jpg"); 59 | if (image.data == NULL) return -1; 60 | cvtColor(image, gray, CV_BGR2GRAY); 61 | 62 | vector bboxes; 63 | fd.DetectFace(gray, bboxes); 64 | 65 | vector landmarks; 66 | for (int i = 0; i < bboxes.size(); i++) { 67 | BBox bbox_ = BBox(bboxes[i]).subBBox(0.1, 0.9, 0.2, 1); 68 | const int kTestN = 1000; 69 | Timer timer; 70 | double time = 0; 71 | for (int j = 0; j < kTestN; j++) { 72 | timer.Tic(); 73 | landmarks = lder.DetectLandmark(gray, bbox_); 74 | timer.Toc(); 75 | time += timer.Elasped(); 76 | } 77 | cout << "costs " << time / kTestN << " ms" << endl; 78 | showLandmarks(image, bbox_.rect, landmarks); 79 | } 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoyetx/mini-caffe-example/e3109d79b2fc83439088983ed55178055de9f7b1/test.jpg --------------------------------------------------------------------------------