├── .idea
├── codeStyles
│ └── Project.xml
└── vcs.xml
├── 2.png
├── 4.jpg
├── CMakeLists.txt
├── Makefile
├── README.md
├── det1_relu.caffemodel
├── det1_relu.prototxt
├── det2_relu.caffemodel
├── det2_relu.prototxt
├── det3_relu.caffemodel
├── det3_relu.prototxt
├── main
├── pictures
├── QR.png
├── modification.png
├── qrcode.png
├── result.jpg
└── vrcode.jpg
├── result.jpg
├── src
├── baseEngine.cpp
├── baseEngine.h
├── common.cpp
├── common.h
├── demo.cpp
├── mtcnn.cpp
├── mtcnn.h
├── network.cpp
├── network.h
├── onet_rt.cpp
├── onet_rt.h
├── pBox.h
├── pnet_rt.cpp
├── pnet_rt.h
├── rnet_rt.cpp
└── rnet_rt.h
└── temp.prototxt
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/2.png
--------------------------------------------------------------------------------
/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/4.jpg
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 | project(main)
3 |
4 | add_definitions(-std=c++11)
5 | #set(QMAKE_CXXFLAGS "-std=c++11")
6 | include_directories(/opt/OpenBLAS/include)
7 | include_directories(/usr/local/cuda/include)
8 | include_directories(/home/zhou/tensorrt/include)
9 | link_directories(/home/zhou/tensorrt/lib)
10 | link_directories(/opt/cuda/lib64)
11 |
12 | find_package( OpenCV REQUIRED)
13 |
14 | AUX_SOURCE_DIRECTORY(./src DIR_SRCS)
15 | add_executable( main ${DIR_SRCS} src/pnet_rt.cpp src/common.h src/common.cpp src/pnet_rt.h src/rnet_rt.cpp src/rnet_rt.h src/baseEngine.cpp src/baseEngine.h src/onet_rt.h src/onet_rt.cpp)
16 |
17 | set(CMAKE_CXX_FLAGS "-lpthread")
18 | set(CMAKE_CXX_FLAGS "-O3")
19 | target_link_libraries( main ${OpenCV_LIBS} )
20 | target_link_libraries( main openblas)
21 | target_link_libraries( main cudart)
22 | target_link_libraries( main nvinfer)
23 | target_link_libraries( main nvparsers)
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # CMAKE generated file: DO NOT EDIT!
2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.10
3 |
4 | # Default target executed when no arguments are given to make.
5 | default_target: all
6 |
7 | .PHONY : default_target
8 |
9 | # Allow only one "make -f Makefile2" at a time, but pass parallelism.
10 | .NOTPARALLEL:
11 |
12 |
13 | #=============================================================================
14 | # Special targets provided by cmake.
15 |
16 | # Disable implicit rules so canonical targets will work.
17 | .SUFFIXES:
18 |
19 |
20 | # Remove some rules from gmake that .SUFFIXES does not remove.
21 | SUFFIXES =
22 |
23 | .SUFFIXES: .hpux_make_needs_suffix_list
24 |
25 |
26 | # Suppress display of executed commands.
27 | $(VERBOSE).SILENT:
28 |
29 |
30 | # A target that is always out of date.
31 | cmake_force:
32 |
33 | .PHONY : cmake_force
34 |
35 | #=============================================================================
36 | # Set environment variables for the build.
37 |
38 | # The shell in which to execute make rules.
39 | SHELL = /bin/sh
40 |
41 | # The CMake executable.
42 | CMAKE_COMMAND = /usr/bin/cmake
43 |
44 | # The command to remove a file.
45 | RM = /usr/bin/cmake -E remove -f
46 |
47 | # Escaping for special characters.
48 | EQUALS = =
49 |
50 | # The top-level source directory on which CMake was run.
51 | CMAKE_SOURCE_DIR = /home/zhou/MTCNN_TensorRT
52 |
53 | # The top-level build directory on which CMake was run.
54 | CMAKE_BINARY_DIR = /home/zhou/MTCNN_TensorRT
55 |
56 | #=============================================================================
57 | # Targets provided globally by CMake.
58 |
59 | # Special rule for the target rebuild_cache
60 | rebuild_cache:
61 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
62 | /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
63 | .PHONY : rebuild_cache
64 |
65 | # Special rule for the target rebuild_cache
66 | rebuild_cache/fast: rebuild_cache
67 |
68 | .PHONY : rebuild_cache/fast
69 |
70 | # Special rule for the target edit_cache
71 | edit_cache:
72 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
73 | /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
74 | .PHONY : edit_cache
75 |
76 | # Special rule for the target edit_cache
77 | edit_cache/fast: edit_cache
78 |
79 | .PHONY : edit_cache/fast
80 |
81 | # The main all target
82 | all: cmake_check_build_system
83 | $(CMAKE_COMMAND) -E cmake_progress_start /home/zhou/MTCNN_TensorRT/CMakeFiles /home/zhou/MTCNN_TensorRT/CMakeFiles/progress.marks
84 | $(MAKE) -f CMakeFiles/Makefile2 all
85 | $(CMAKE_COMMAND) -E cmake_progress_start /home/zhou/MTCNN_TensorRT/CMakeFiles 0
86 | .PHONY : all
87 |
88 | # The main clean target
89 | clean:
90 | $(MAKE) -f CMakeFiles/Makefile2 clean
91 | .PHONY : clean
92 |
93 | # The main clean target
94 | clean/fast: clean
95 |
96 | .PHONY : clean/fast
97 |
98 | # Prepare targets for installation.
99 | preinstall: all
100 | $(MAKE) -f CMakeFiles/Makefile2 preinstall
101 | .PHONY : preinstall
102 |
103 | # Prepare targets for installation.
104 | preinstall/fast:
105 | $(MAKE) -f CMakeFiles/Makefile2 preinstall
106 | .PHONY : preinstall/fast
107 |
108 | # clear depends
109 | depend:
110 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
111 | .PHONY : depend
112 |
113 | #=============================================================================
114 | # Target rules for targets named main
115 |
116 | # Build rule for target.
117 | main: cmake_check_build_system
118 | $(MAKE) -f CMakeFiles/Makefile2 main
119 | .PHONY : main
120 |
121 | # fast build rule for target.
122 | main/fast:
123 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
124 | .PHONY : main/fast
125 |
126 | src/baseEngine.o: src/baseEngine.cpp.o
127 |
128 | .PHONY : src/baseEngine.o
129 |
130 | # target to build an object file
131 | src/baseEngine.cpp.o:
132 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/baseEngine.cpp.o
133 | .PHONY : src/baseEngine.cpp.o
134 |
135 | src/baseEngine.i: src/baseEngine.cpp.i
136 |
137 | .PHONY : src/baseEngine.i
138 |
139 | # target to preprocess a source file
140 | src/baseEngine.cpp.i:
141 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/baseEngine.cpp.i
142 | .PHONY : src/baseEngine.cpp.i
143 |
144 | src/baseEngine.s: src/baseEngine.cpp.s
145 |
146 | .PHONY : src/baseEngine.s
147 |
148 | # target to generate assembly for a file
149 | src/baseEngine.cpp.s:
150 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/baseEngine.cpp.s
151 | .PHONY : src/baseEngine.cpp.s
152 |
153 | src/common.o: src/common.cpp.o
154 |
155 | .PHONY : src/common.o
156 |
157 | # target to build an object file
158 | src/common.cpp.o:
159 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/common.cpp.o
160 | .PHONY : src/common.cpp.o
161 |
162 | src/common.i: src/common.cpp.i
163 |
164 | .PHONY : src/common.i
165 |
166 | # target to preprocess a source file
167 | src/common.cpp.i:
168 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/common.cpp.i
169 | .PHONY : src/common.cpp.i
170 |
171 | src/common.s: src/common.cpp.s
172 |
173 | .PHONY : src/common.s
174 |
175 | # target to generate assembly for a file
176 | src/common.cpp.s:
177 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/common.cpp.s
178 | .PHONY : src/common.cpp.s
179 |
180 | src/demo.o: src/demo.cpp.o
181 |
182 | .PHONY : src/demo.o
183 |
184 | # target to build an object file
185 | src/demo.cpp.o:
186 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/demo.cpp.o
187 | .PHONY : src/demo.cpp.o
188 |
189 | src/demo.i: src/demo.cpp.i
190 |
191 | .PHONY : src/demo.i
192 |
193 | # target to preprocess a source file
194 | src/demo.cpp.i:
195 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/demo.cpp.i
196 | .PHONY : src/demo.cpp.i
197 |
198 | src/demo.s: src/demo.cpp.s
199 |
200 | .PHONY : src/demo.s
201 |
202 | # target to generate assembly for a file
203 | src/demo.cpp.s:
204 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/demo.cpp.s
205 | .PHONY : src/demo.cpp.s
206 |
207 | src/mtcnn.o: src/mtcnn.cpp.o
208 |
209 | .PHONY : src/mtcnn.o
210 |
211 | # target to build an object file
212 | src/mtcnn.cpp.o:
213 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mtcnn.cpp.o
214 | .PHONY : src/mtcnn.cpp.o
215 |
216 | src/mtcnn.i: src/mtcnn.cpp.i
217 |
218 | .PHONY : src/mtcnn.i
219 |
220 | # target to preprocess a source file
221 | src/mtcnn.cpp.i:
222 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mtcnn.cpp.i
223 | .PHONY : src/mtcnn.cpp.i
224 |
225 | src/mtcnn.s: src/mtcnn.cpp.s
226 |
227 | .PHONY : src/mtcnn.s
228 |
229 | # target to generate assembly for a file
230 | src/mtcnn.cpp.s:
231 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/mtcnn.cpp.s
232 | .PHONY : src/mtcnn.cpp.s
233 |
234 | src/network.o: src/network.cpp.o
235 |
236 | .PHONY : src/network.o
237 |
238 | # target to build an object file
239 | src/network.cpp.o:
240 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/network.cpp.o
241 | .PHONY : src/network.cpp.o
242 |
243 | src/network.i: src/network.cpp.i
244 |
245 | .PHONY : src/network.i
246 |
247 | # target to preprocess a source file
248 | src/network.cpp.i:
249 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/network.cpp.i
250 | .PHONY : src/network.cpp.i
251 |
252 | src/network.s: src/network.cpp.s
253 |
254 | .PHONY : src/network.s
255 |
256 | # target to generate assembly for a file
257 | src/network.cpp.s:
258 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/network.cpp.s
259 | .PHONY : src/network.cpp.s
260 |
261 | src/onet_rt.o: src/onet_rt.cpp.o
262 |
263 | .PHONY : src/onet_rt.o
264 |
265 | # target to build an object file
266 | src/onet_rt.cpp.o:
267 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/onet_rt.cpp.o
268 | .PHONY : src/onet_rt.cpp.o
269 |
270 | src/onet_rt.i: src/onet_rt.cpp.i
271 |
272 | .PHONY : src/onet_rt.i
273 |
274 | # target to preprocess a source file
275 | src/onet_rt.cpp.i:
276 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/onet_rt.cpp.i
277 | .PHONY : src/onet_rt.cpp.i
278 |
279 | src/onet_rt.s: src/onet_rt.cpp.s
280 |
281 | .PHONY : src/onet_rt.s
282 |
283 | # target to generate assembly for a file
284 | src/onet_rt.cpp.s:
285 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/onet_rt.cpp.s
286 | .PHONY : src/onet_rt.cpp.s
287 |
288 | src/pnet_rt.o: src/pnet_rt.cpp.o
289 |
290 | .PHONY : src/pnet_rt.o
291 |
292 | # target to build an object file
293 | src/pnet_rt.cpp.o:
294 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/pnet_rt.cpp.o
295 | .PHONY : src/pnet_rt.cpp.o
296 |
297 | src/pnet_rt.i: src/pnet_rt.cpp.i
298 |
299 | .PHONY : src/pnet_rt.i
300 |
301 | # target to preprocess a source file
302 | src/pnet_rt.cpp.i:
303 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/pnet_rt.cpp.i
304 | .PHONY : src/pnet_rt.cpp.i
305 |
306 | src/pnet_rt.s: src/pnet_rt.cpp.s
307 |
308 | .PHONY : src/pnet_rt.s
309 |
310 | # target to generate assembly for a file
311 | src/pnet_rt.cpp.s:
312 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/pnet_rt.cpp.s
313 | .PHONY : src/pnet_rt.cpp.s
314 |
315 | src/rnet_rt.o: src/rnet_rt.cpp.o
316 |
317 | .PHONY : src/rnet_rt.o
318 |
319 | # target to build an object file
320 | src/rnet_rt.cpp.o:
321 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/rnet_rt.cpp.o
322 | .PHONY : src/rnet_rt.cpp.o
323 |
324 | src/rnet_rt.i: src/rnet_rt.cpp.i
325 |
326 | .PHONY : src/rnet_rt.i
327 |
328 | # target to preprocess a source file
329 | src/rnet_rt.cpp.i:
330 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/rnet_rt.cpp.i
331 | .PHONY : src/rnet_rt.cpp.i
332 |
333 | src/rnet_rt.s: src/rnet_rt.cpp.s
334 |
335 | .PHONY : src/rnet_rt.s
336 |
337 | # target to generate assembly for a file
338 | src/rnet_rt.cpp.s:
339 | $(MAKE) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/src/rnet_rt.cpp.s
340 | .PHONY : src/rnet_rt.cpp.s
341 |
342 | # Help Target
343 | help:
344 | @echo "The following are some of the valid targets for this Makefile:"
345 | @echo "... all (the default if no target is provided)"
346 | @echo "... clean"
347 | @echo "... depend"
348 | @echo "... rebuild_cache"
349 | @echo "... main"
350 | @echo "... edit_cache"
351 | @echo "... src/baseEngine.o"
352 | @echo "... src/baseEngine.i"
353 | @echo "... src/baseEngine.s"
354 | @echo "... src/common.o"
355 | @echo "... src/common.i"
356 | @echo "... src/common.s"
357 | @echo "... src/demo.o"
358 | @echo "... src/demo.i"
359 | @echo "... src/demo.s"
360 | @echo "... src/mtcnn.o"
361 | @echo "... src/mtcnn.i"
362 | @echo "... src/mtcnn.s"
363 | @echo "... src/network.o"
364 | @echo "... src/network.i"
365 | @echo "... src/network.s"
366 | @echo "... src/onet_rt.o"
367 | @echo "... src/onet_rt.i"
368 | @echo "... src/onet_rt.s"
369 | @echo "... src/pnet_rt.o"
370 | @echo "... src/pnet_rt.i"
371 | @echo "... src/pnet_rt.s"
372 | @echo "... src/rnet_rt.o"
373 | @echo "... src/rnet_rt.i"
374 | @echo "... src/rnet_rt.s"
375 | .PHONY : help
376 |
377 |
378 |
379 | #=============================================================================
380 | # Special targets to cleanup operation of make.
381 |
382 | # Special rule to run CMake to check the build system integrity.
383 | # No rule that depends on this can have commands that come from listfiles
384 | # because they might be regenerated.
385 | cmake_check_build_system:
386 | $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
387 | .PHONY : cmake_check_build_system
388 |
389 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | blob# MTCNN_TensorRT
2 |
3 | **MTCNN Face detection algorithm's C++ implementation with NVIDIA TensorRT Inference acceleration SDK.**
4 |
5 | This repository is based on https://github.com/AlphaQi/MTCNN-light.git
6 |
7 | ## Notations
8 |
9 | 2018/11/14: I have ported most of the computing to GPU using OpenCV CUDA warper and CUDA kernels wrote by myself.
10 | See branch all_gpu for more details, note that you need opencv 3.0+ built with CUDA support to run the projects. The speed is about 5-10 times faster on my GTX1080 GPU than master branch.
11 |
12 | 2018/10/2: Good news! Now you can run the whole MTCNN using TenorRT 3.0 or 4.0!
13 |
14 | I adopt the original models from offical project https://github.com/kpzhang93/MTCNN_face_detection_alignment and do the following modifications:
15 | Considering TensorRT don't support PRelu layer, which is widely used in MTCNN, one solution is to add Plugin Layer (costome layer) but experiments show that this method breaks the CBR process in TensorRT and is very slow. I use Relu layer, Scale layer and ElementWise addition Layer to replace Prelu (as illustrated below), which only adds a bit of computation and won't affect CBR process, the weights of scale layers derive from original Prelu layers.
16 |
17 | 
18 |
19 |
20 | ## Required environments
21 | 1) OpenCV (on ubuntu just run sudo apt-get install libopencv-dev to install opencv)
22 | 1) CUDA 9.0
23 | 1) TensorRT 3.04 or TensorRT 4.16 (I only test these two versions)
24 | 1) Cmake >=3.5
25 | 1) A digital camera to run camera test.
26 |
27 | ## Build
28 | 1) Replace the tensorrt and cuda path in CMakeLists.txt
29 | 1) Configure the detection parameters in mtcnn.cpp (min face size, the nms thresholds , etc)
30 | 1) Choose the running modes (camera test or single image test)
31 | 1) cmake .
32 | 1) make -j
33 | 1) ./main
34 |
35 | ## Results
36 | The result will be like this in single image test mode:
37 |
38 | 
39 |
40 | ## Speed
41 | On my computer with nvidia-gt730 grapic card (its performance is very very poor) and intel i5 6500 cpu, when the min face-size is set to 60 pixels, the above image costs 20 to 30ms.
42 |
43 | ## TODO
44 | Inplement the whole processing using GPU computing.
45 |
46 |
47 |
--------------------------------------------------------------------------------
/det1_relu.caffemodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/det1_relu.caffemodel
--------------------------------------------------------------------------------
/det1_relu.prototxt:
--------------------------------------------------------------------------------
1 | name: "PNet"
2 | layer
3 | {
4 | name: "data"
5 | type: "Input"
6 | top: "data"
7 | input_param{shape:{dim:1 dim:3 dim:12 dim:12}}
8 | }
9 |
10 | layer {
11 | name: "conv1"
12 | type: "Convolution"
13 | bottom: "data"
14 | top: "conv1"
15 | param {
16 | lr_mult: 1
17 | }
18 | param {
19 | lr_mult: 2
20 | }
21 | convolution_param {
22 | num_output: 10
23 | kernel_size: 3
24 | stride: 1
25 | weight_filler {
26 | type: "xavier"
27 | }
28 | bias_filler {
29 | type: "constant"
30 | }
31 | }
32 | }
33 | layer {
34 | name: "ReLU1"
35 | type: "ReLU"
36 | bottom: "conv1"
37 | top: "conv1_1"
38 | }
39 |
40 | layer {
41 | name: "scale1_1"
42 | bottom: "conv1"
43 | top: "conv1_2"
44 | type: "Scale"
45 | scale_param {
46 | axis: 1
47 | bias_term:false
48 | }
49 | }
50 | layer {
51 | name: "ReLU1_2"
52 | type: "ReLU"
53 | bottom: "conv1_2"
54 | top: "conv1_2"
55 | }
56 | layer {
57 | name: "scale1_2"
58 | bottom: "conv1_2"
59 | top: "conv1_2"
60 | type: "Scale"
61 | scale_param {
62 | axis: 1
63 | bias_term:false
64 |
65 | }
66 | }
67 | layer {
68 | name: "eltwise-sum1"
69 | type: "Eltwise"
70 | bottom: "conv1_1"
71 | bottom: "conv1_2"
72 | top: "conv1_3"
73 | eltwise_param { operation: SUM }
74 | }
75 | layer {
76 | name: "pool1"
77 | type: "Pooling"
78 | bottom: "conv1_3"
79 | top: "pool1"
80 | pooling_param {
81 | pool: MAX
82 | kernel_size: 2
83 | stride: 2
84 | }
85 | }
86 |
87 | layer {
88 | name: "conv2"
89 | type: "Convolution"
90 | bottom: "pool1"
91 | top: "conv2"
92 | param {
93 | lr_mult: 1
94 | }
95 | param {
96 | lr_mult: 2
97 | }
98 | convolution_param {
99 | num_output: 16
100 | kernel_size: 3
101 | stride: 1
102 | weight_filler {
103 | type: "xavier"
104 | }
105 | bias_filler {
106 | type: "constant"
107 | }
108 | }
109 | }
110 | layer {
111 | name: "ReLU2"
112 | type: "ReLU"
113 | bottom: "conv2"
114 | top: "conv2_1"
115 | }
116 |
117 | layer {
118 | name: "scale2_1"
119 | bottom: "conv2"
120 | top: "conv2_2"
121 | type: "Scale"
122 | scale_param {
123 | axis: 1
124 | bias_term:false
125 |
126 | }
127 | }
128 | layer {
129 | name: "ReLU2_2"
130 | type: "ReLU"
131 | bottom: "conv2_2"
132 | top: "conv2_2"
133 | }
134 | layer {
135 | name: "scale2_2"
136 | bottom: "conv2_2"
137 | top: "conv2_2"
138 | type: "Scale"
139 | scale_param {
140 | axis: 1
141 | bias_term:false
142 | }
143 | }
144 | layer {
145 | name: "eltwise-sum2"
146 | type: "Eltwise"
147 | bottom: "conv2_1"
148 | bottom: "conv2_2"
149 | top: "conv2_3"
150 | eltwise_param { operation: SUM }
151 | }
152 |
153 |
154 | layer {
155 | name: "conv3"
156 | type: "Convolution"
157 | bottom: "conv2_3"
158 | top: "conv3"
159 | param {
160 | lr_mult: 1
161 | }
162 | param {
163 | lr_mult: 2
164 | }
165 | convolution_param {
166 | num_output: 32
167 | kernel_size: 3
168 | stride: 1
169 | weight_filler {
170 | type: "xavier"
171 | }
172 | bias_filler {
173 | type: "constant"
174 | }
175 | }
176 | }
177 | layer {
178 | name: "ReLU3"
179 | type: "ReLU"
180 | bottom: "conv3"
181 | top: "conv3_1"
182 | }
183 | layer {
184 | name: "scale3_1"
185 | bottom: "conv3"
186 | top: "conv3_2"
187 | type: "Scale"
188 | scale_param {
189 | axis: 1
190 | bias_term:false
191 | }
192 | }
193 | layer {
194 | name: "ReLU3_2"
195 | type: "ReLU"
196 | bottom: "conv3_2"
197 | top: "conv3_2"
198 | }
199 | layer {
200 | name: "scale3_2"
201 | bottom: "conv3_2"
202 | top: "conv3_2"
203 | type: "Scale"
204 | scale_param {
205 | axis: 1
206 | bias_term:false
207 | }
208 | }
209 | layer {
210 | name: "eltwise-sum3"
211 | type: "Eltwise"
212 | bottom: "conv3_1"
213 | bottom: "conv3_2"
214 | top: "conv3_3"
215 | eltwise_param { operation: SUM }
216 | }
217 |
218 | layer {
219 | name: "conv4-1"
220 | type: "Convolution"
221 | bottom: "conv3_3"
222 | top: "conv4-1"
223 | param {
224 | lr_mult: 1
225 | decay_mult: 1
226 | }
227 | param {
228 | lr_mult: 2
229 | }
230 | convolution_param {
231 | num_output: 2
232 | kernel_size: 1
233 | stride: 1
234 | weight_filler {
235 | type: "xavier"
236 | }
237 | bias_filler {
238 | type: "constant"
239 | }
240 | }
241 | }
242 |
243 | layer {
244 | name: "conv4-2"
245 | type: "Convolution"
246 | bottom: "conv3_3"
247 | top: "conv4-2"
248 | param {
249 | lr_mult: 1
250 | }
251 | param {
252 | lr_mult: 2
253 | }
254 | convolution_param {
255 | num_output: 4
256 | kernel_size: 1
257 | stride: 1
258 | weight_filler {
259 | type: "xavier"
260 | }
261 | bias_filler {
262 | type: "constant"
263 | }
264 | }
265 | }
266 | layer {
267 | name: "prob1"
268 | type: "Softmax"
269 | bottom: "conv4-1"
270 | top: "prob1"
271 | }
--------------------------------------------------------------------------------
/det2_relu.caffemodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/det2_relu.caffemodel
--------------------------------------------------------------------------------
/det2_relu.prototxt:
--------------------------------------------------------------------------------
1 | name: "RNet"
2 | layer
3 | {
4 | name: "data"
5 | type: "Input"
6 | top: "data"
7 | input_param{shape:{dim:1 dim:3 dim:24 dim:24}}
8 | }
9 |
10 | layer {
11 | name: "conv1"
12 | type: "Convolution"
13 | bottom: "data"
14 | top: "conv1"
15 | param {
16 | lr_mult: 0
17 | decay_mult: 0
18 | }
19 | param {
20 | lr_mult: 0
21 | decay_mult: 0
22 | }
23 | convolution_param {
24 | num_output: 28
25 | kernel_size: 3
26 | stride: 1
27 | weight_filler {
28 | type: "xavier"
29 | }
30 | bias_filler {
31 | type: "constant"
32 | value: 0
33 | }
34 | }
35 | }
36 | layer {
37 | name: "relu1_1"
38 | type: "ReLU"
39 | bottom: "conv1"
40 | top: "conv1_1"
41 | propagate_down: true
42 | }
43 |
44 | layer {
45 | name: "scale1_1"
46 | bottom: "conv1"
47 | top: "conv1_2"
48 | type: "Scale"
49 | scale_param {
50 | axis: 1
51 | bias_term:false
52 | }
53 | }
54 | layer {
55 | name: "ReLU1_2"
56 | type: "ReLU"
57 | bottom: "conv1_2"
58 | top: "conv1_2"
59 | }
60 | layer {
61 | name: "scale1_2"
62 | bottom: "conv1_2"
63 | top: "conv1_2"
64 | type: "Scale"
65 | scale_param {
66 | axis: 1
67 | bias_term:false
68 | }
69 | }
70 | layer {
71 | name: "eltwise-sum1"
72 | type: "Eltwise"
73 | bottom: "conv1_1"
74 | bottom: "conv1_2"
75 | top: "conv1_3"
76 | eltwise_param { operation: SUM }
77 | }
78 | layer {
79 | name: "pool1"
80 | type: "Pooling"
81 | bottom: "conv1_3"
82 | top: "pool1"
83 | pooling_param {
84 | pool: MAX
85 | kernel_size: 3
86 | stride: 2
87 | }
88 | }
89 |
90 | layer {
91 | name: "conv2"
92 | type: "Convolution"
93 | bottom: "pool1"
94 | top: "conv2"
95 | param {
96 | lr_mult: 0
97 | decay_mult: 0
98 | }
99 | param {
100 | lr_mult: 0
101 | decay_mult: 0
102 | }
103 | convolution_param {
104 | num_output: 48
105 | kernel_size: 3
106 | stride: 1
107 | weight_filler {
108 | type: "xavier"
109 | }
110 | bias_filler {
111 | type: "constant"
112 | value: 0
113 | }
114 | }
115 | }
116 | layer {
117 | name: "relu2_1"
118 | type: "ReLU"
119 | bottom: "conv2"
120 | top: "conv2_1"
121 | propagate_down: true
122 | }
123 |
124 | layer {
125 | name: "scale2_1"
126 | bottom: "conv2"
127 | top: "conv2_2"
128 | type: "Scale"
129 | scale_param {
130 | axis: 1
131 | bias_term:false
132 | }
133 | }
134 | layer {
135 | name: "ReLU2_2"
136 | type: "ReLU"
137 | bottom: "conv2_2"
138 | top: "conv2_2"
139 | }
140 | layer {
141 | name: "scale2_2"
142 | bottom: "conv2_2"
143 | top: "conv2_2"
144 | type: "Scale"
145 | scale_param {
146 | axis: 1
147 | bias_term:false
148 | }
149 | }
150 | layer {
151 | name: "eltwise-sum2"
152 | type: "Eltwise"
153 | bottom: "conv2_1"
154 | bottom: "conv2_2"
155 | top: "conv2_3"
156 | eltwise_param { operation: SUM }
157 | }
158 |
159 | layer {
160 | name: "pool2"
161 | type: "Pooling"
162 | bottom: "conv2_3"
163 | top: "pool2"
164 | pooling_param {
165 | pool: MAX
166 | kernel_size: 3
167 | stride: 2
168 | }
169 | }
170 | ####################################
171 |
172 | ##################################
173 | layer {
174 | name: "conv3"
175 | type: "Convolution"
176 | bottom: "pool2"
177 | top: "conv3"
178 | param {
179 | lr_mult: 0
180 | decay_mult: 0
181 | }
182 | param {
183 | lr_mult: 0
184 | decay_mult: 0
185 | }
186 | convolution_param {
187 | num_output: 64
188 | kernel_size: 2
189 | stride: 1
190 | weight_filler {
191 | type: "xavier"
192 | }
193 | bias_filler {
194 | type: "constant"
195 | value: 0
196 | }
197 | }
198 | }
199 |
200 | layer {
201 | name: "scale3_1"
202 | bottom: "conv3"
203 | top: "conv3_2"
204 | type: "Scale"
205 | scale_param {
206 | axis: 1
207 | bias_term:false
208 | }
209 | }
210 | layer {
211 | name: "ReLU3_2"
212 | type: "ReLU"
213 | bottom: "conv3_2"
214 | top: "conv3_2"
215 | }
216 | layer {
217 | name: "scale3_2"
218 | bottom: "conv3_2"
219 | top: "conv3_2"
220 | type: "Scale"
221 | scale_param {
222 | axis: 1
223 | bias_term:false
224 | }
225 | }
226 | layer {
227 | name: "relu3"
228 | type: "ReLU"
229 | bottom: "conv3"
230 | top: "conv3_1"
231 | propagate_down: true
232 | }
233 | layer {
234 | name: "eltwise-sum3"
235 | type: "Eltwise"
236 | bottom: "conv3_1"
237 | bottom: "conv3_2"
238 | top: "conv3_3"
239 | eltwise_param { operation: SUM }
240 | }
241 |
242 | ###############################
243 |
244 | ###############################
245 |
246 | layer {
247 | name: "conv4"
248 | type: "InnerProduct"
249 | bottom: "conv3_3"
250 | top: "conv4"
251 | param {
252 | lr_mult: 0
253 | decay_mult: 0
254 | }
255 | param {
256 | lr_mult: 0
257 | decay_mult: 0
258 | }
259 | inner_product_param {
260 | num_output: 128
261 | weight_filler {
262 | type: "xavier"
263 | }
264 | bias_filler {
265 | type: "constant"
266 | value: 0
267 | }
268 | }
269 | }
270 | layer {
271 | name: "relu4_1"
272 | type: "ReLU"
273 | bottom: "conv4"
274 | top: "conv4_1"
275 | }
276 |
277 | layer {
278 | name: "scale4_1"
279 | bottom: "conv4"
280 | top: "conv4_2"
281 | type: "Scale"
282 | scale_param {
283 | axis: 1
284 | bias_term:false
285 | }
286 | }
287 | layer {
288 | name: "ReLU4_2"
289 | type: "ReLU"
290 | bottom: "conv4_2"
291 | top: "conv4_2"
292 | }
293 | layer {
294 | name: "scale4_2"
295 | bottom: "conv4_2"
296 | top: "conv4_2"
297 | type: "Scale"
298 | scale_param {
299 | axis: 1
300 | bias_term:false
301 | }
302 | }
303 | layer {
304 | name: "eltwise-sum4"
305 | type: "Eltwise"
306 | bottom: "conv4_1"
307 | bottom: "conv4_2"
308 | top: "conv4_3"
309 | eltwise_param { operation: SUM }
310 | }
311 |
312 |
313 | layer {
314 | name: "conv5-1"
315 | type: "InnerProduct"
316 | bottom: "conv4_3"
317 | top: "conv5-1"
318 | param {
319 | lr_mult: 0
320 | decay_mult: 0
321 | }
322 | param {
323 | lr_mult: 0
324 | decay_mult: 0
325 | }
326 | inner_product_param {
327 | num_output: 2
328 | #kernel_size: 1
329 | #stride: 1
330 | weight_filler {
331 | type: "xavier"
332 | }
333 | bias_filler {
334 | type: "constant"
335 | value: 0
336 | }
337 | }
338 | }
339 | layer {
340 | name: "conv5-2"
341 | type: "InnerProduct"
342 | bottom: "conv4_3"
343 | top: "conv5-2"
344 | param {
345 | lr_mult: 1
346 | decay_mult: 1
347 | }
348 | param {
349 | lr_mult: 2
350 | decay_mult: 1
351 | }
352 | inner_product_param {
353 | num_output: 4
354 | #kernel_size: 1
355 | #stride: 1
356 | weight_filler {
357 | type: "xavier"
358 | }
359 | bias_filler {
360 | type: "constant"
361 | value: 0
362 | }
363 | }
364 | }
365 | layer {
366 | name: "prob1"
367 | type: "Softmax"
368 | bottom: "conv5-1"
369 | top: "prob1"
370 | }
--------------------------------------------------------------------------------
/det3_relu.caffemodel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/det3_relu.caffemodel
--------------------------------------------------------------------------------
/det3_relu.prototxt:
--------------------------------------------------------------------------------
1 | name: "ONet"
2 | input: "data"
3 | input_dim: 1
4 | input_dim: 3
5 | input_dim: 48
6 | input_dim: 48
7 | ##################################
8 | layer {
9 | name: "conv1"
10 | type: "Convolution"
11 | bottom: "data"
12 | top: "conv1"
13 | param {
14 | lr_mult: 1
15 | decay_mult: 1
16 | }
17 | param {
18 | lr_mult: 2
19 | decay_mult: 1
20 | }
21 | convolution_param {
22 | num_output: 32
23 | kernel_size: 3
24 | stride: 1
25 | weight_filler {
26 | type: "xavier"
27 | }
28 | bias_filler {
29 | type: "constant"
30 | value: 0
31 | }
32 | }
33 | }
34 | layer {
35 | name: "relu1_1"
36 | type: "ReLU"
37 | bottom: "conv1"
38 | top: "conv1_1"
39 | }
40 |
41 | layer {
42 | name: "scale1_1"
43 | bottom: "conv1"
44 | top: "conv1_2"
45 | type: "Scale"
46 | scale_param {
47 | axis: 1
48 | bias_term:false
49 | }
50 | }
51 | layer {
52 | name: "ReLU1_2"
53 | type: "ReLU"
54 | bottom: "conv1_2"
55 | top: "conv1_2"
56 | }
57 | layer {
58 | name: "scale1_2"
59 | bottom: "conv1_2"
60 | top: "conv1_2"
61 | type: "Scale"
62 | scale_param {
63 | axis: 1
64 | bias_term:false
65 | }
66 | }
67 | layer {
68 | name: "eltwise-sum1"
69 | type: "Eltwise"
70 | bottom: "conv1_1"
71 | bottom: "conv1_2"
72 | top: "conv1_3"
73 | eltwise_param { operation: SUM }
74 | }
75 |
76 | layer {
77 | name: "pool1"
78 | type: "Pooling"
79 | bottom: "conv1_3"
80 | top: "pool1"
81 | pooling_param {
82 | pool: MAX
83 | kernel_size: 3
84 | stride: 2
85 | }
86 | }
87 | layer {
88 | name: "conv2"
89 | type: "Convolution"
90 | bottom: "pool1"
91 | top: "conv2"
92 | param {
93 | lr_mult: 1
94 | decay_mult: 1
95 | }
96 | param {
97 | lr_mult: 2
98 | decay_mult: 1
99 | }
100 | convolution_param {
101 | num_output: 64
102 | kernel_size: 3
103 | stride: 1
104 | weight_filler {
105 | type: "xavier"
106 | }
107 | bias_filler {
108 | type: "constant"
109 | value: 0
110 | }
111 | }
112 | }
113 |
114 | layer {
115 | name: "relu2_1"
116 | type: "ReLU"
117 | bottom: "conv2"
118 | top: "conv2_1"
119 | }
120 | layer {
121 | name: "scale2_1"
122 | bottom: "conv2"
123 | top: "conv2_2"
124 | type: "Scale"
125 | scale_param {
126 | axis: 1
127 | bias_term:false
128 | }
129 | }
130 | layer {
131 | name: "ReLU2_2"
132 | type: "ReLU"
133 | bottom: "conv2_2"
134 | top: "conv2_2"
135 | }
136 | layer {
137 | name: "scale2_2"
138 | bottom: "conv2_2"
139 | top: "conv2_2"
140 | type: "Scale"
141 | scale_param {
142 | axis: 1
143 | bias_term:false
144 | }
145 | }
146 | layer {
147 | name: "eltwise-sum2"
148 | type: "Eltwise"
149 | bottom: "conv2_1"
150 | bottom: "conv2_2"
151 | top: "conv2_3"
152 | eltwise_param { operation: SUM }
153 | }
154 | layer {
155 | name: "pool2"
156 | type: "Pooling"
157 | bottom: "conv2_3"
158 | top: "pool2"
159 | pooling_param {
160 | pool: MAX
161 | kernel_size: 3
162 | stride: 2
163 | }
164 | }
165 |
166 | layer {
167 | name: "conv3"
168 | type: "Convolution"
169 | bottom: "pool2"
170 | top: "conv3"
171 | param {
172 | lr_mult: 1
173 | decay_mult: 1
174 | }
175 | param {
176 | lr_mult: 2
177 | decay_mult: 1
178 | }
179 | convolution_param {
180 | num_output: 64
181 | kernel_size: 3
182 | weight_filler {
183 | type: "xavier"
184 | }
185 | bias_filler {
186 | type: "constant"
187 | value: 0
188 | }
189 | }
190 | }
191 | layer {
192 | name: "relu3_1"
193 | type: "ReLU"
194 | bottom: "conv3"
195 | top: "conv3_1"
196 | }
197 | layer {
198 | name: "scale3_1"
199 | bottom: "conv3"
200 | top: "conv3_2"
201 | type: "Scale"
202 | scale_param {
203 | axis: 1
204 | bias_term:false
205 | }
206 | }
207 | layer {
208 | name: "ReLU3_2"
209 | type: "ReLU"
210 | bottom: "conv3_2"
211 | top: "conv3_2"
212 | }
213 | layer {
214 | name: "scale3_2"
215 | bottom: "conv3_2"
216 | top: "conv3_2"
217 | type: "Scale"
218 | scale_param {
219 | axis: 1
220 | bias_term:false
221 | }
222 | }
223 | layer {
224 | name: "eltwise-sum3"
225 | type: "Eltwise"
226 | bottom: "conv3_1"
227 | bottom: "conv3_2"
228 | top: "conv3_3"
229 | eltwise_param { operation: SUM }
230 | }
231 | layer {
232 | name: "pool3"
233 | type: "Pooling"
234 | bottom: "conv3_3"
235 | top: "pool3"
236 | pooling_param {
237 | pool: MAX
238 | kernel_size: 2
239 | stride: 2
240 | }
241 | }
242 | layer {
243 | name: "conv4"
244 | type: "Convolution"
245 | bottom: "pool3"
246 | top: "conv4"
247 | param {
248 | lr_mult: 1
249 | decay_mult: 1
250 | }
251 | param {
252 | lr_mult: 2
253 | decay_mult: 1
254 | }
255 | convolution_param {
256 | num_output: 128
257 | kernel_size: 2
258 | weight_filler {
259 | type: "xavier"
260 | }
261 | bias_filler {
262 | type: "constant"
263 | value: 0
264 | }
265 | }
266 | }
267 | layer {
268 | name: "relu4"
269 | type: "ReLU"
270 | bottom: "conv4"
271 | top: "conv4_1"
272 | }
273 |
274 | layer {
275 | name: "scale4_1"
276 | bottom: "conv4"
277 | top: "conv4_2"
278 | type: "Scale"
279 | scale_param {
280 | axis: 1
281 | bias_term:false
282 | }
283 | }
284 | layer {
285 | name: "ReLU4_2"
286 | type: "ReLU"
287 | bottom: "conv4_2"
288 | top: "conv4_2"
289 | }
290 | layer {
291 | name: "scale4_2"
292 | bottom: "conv4_2"
293 | top: "conv4_2"
294 | type: "Scale"
295 | scale_param {
296 | axis: 1
297 | bias_term:false
298 | }
299 | }
300 | layer {
301 | name: "eltwise-sum4"
302 | type: "Eltwise"
303 | bottom: "conv4_1"
304 | bottom: "conv4_2"
305 | top: "conv4_3"
306 | eltwise_param { operation: SUM }
307 | }
308 |
309 | layer {
310 | name: "conv5"
311 | type: "InnerProduct"
312 | bottom: "conv4_3"
313 | top: "conv5"
314 | param {
315 | lr_mult: 1
316 | decay_mult: 1
317 | }
318 | param {
319 | lr_mult: 2
320 | decay_mult: 1
321 | }
322 | inner_product_param {
323 | #kernel_size: 3
324 | num_output: 256
325 | weight_filler {
326 | type: "xavier"
327 | }
328 | bias_filler {
329 | type: "constant"
330 | value: 0
331 | }
332 | }
333 | }
334 |
335 | layer {
336 | name: "relu5_1"
337 | type: "ReLU"
338 | bottom: "conv5"
339 | top: "conv5_1"
340 | }
341 |
342 | layer {
343 | name: "scale5_1"
344 | bottom: "conv5"
345 | top: "conv5_2"
346 | type: "Scale"
347 | scale_param {
348 | axis: 1
349 | bias_term:false
350 | }
351 | }
352 | layer {
353 | name: "ReLU5_2"
354 | type: "ReLU"
355 | bottom: "conv5_2"
356 | top: "conv5_2"
357 | }
358 | layer {
359 | name: "scale5_2"
360 | bottom: "conv5_2"
361 | top: "conv5_2"
362 | type: "Scale"
363 | scale_param {
364 | axis: 1
365 | bias_term:false
366 | }
367 | }
368 | layer {
369 | name: "eltwise-sum5"
370 | type: "Eltwise"
371 | bottom: "conv5_1"
372 | bottom: "conv5_2"
373 | top: "conv5_3"
374 | eltwise_param { operation: SUM }
375 | }
376 |
377 | layer {
378 | name: "conv6-1"
379 | type: "InnerProduct"
380 | bottom: "conv5_3"
381 | top: "conv6-1"
382 | param {
383 | lr_mult: 1
384 | decay_mult: 1
385 | }
386 | param {
387 | lr_mult: 2
388 | decay_mult: 1
389 | }
390 | inner_product_param {
391 | #kernel_size: 1
392 | num_output: 2
393 | weight_filler {
394 | type: "xavier"
395 | }
396 | bias_filler {
397 | type: "constant"
398 | value: 0
399 | }
400 | }
401 | }
402 | layer {
403 | name: "conv6-2"
404 | type: "InnerProduct"
405 | bottom: "conv5_3"
406 | top: "conv6-2"
407 | param {
408 | lr_mult: 1
409 | decay_mult: 1
410 | }
411 | param {
412 | lr_mult: 2
413 | decay_mult: 1
414 | }
415 | inner_product_param {
416 | #kernel_size: 1
417 | num_output: 4
418 | weight_filler {
419 | type: "xavier"
420 | }
421 | bias_filler {
422 | type: "constant"
423 | value: 0
424 | }
425 | }
426 | }
427 | layer {
428 | name: "conv6-3"
429 | type: "InnerProduct"
430 | bottom: "conv5_3"
431 | top: "conv6-3"
432 | param {
433 | lr_mult: 1
434 | decay_mult: 1
435 | }
436 | param {
437 | lr_mult: 2
438 | decay_mult: 1
439 | }
440 | inner_product_param {
441 | #kernel_size: 1
442 | num_output: 10
443 | weight_filler {
444 | type: "xavier"
445 | }
446 | bias_filler {
447 | type: "constant"
448 | value: 0
449 | }
450 | }
451 | }
452 | layer {
453 | name: "prob1"
454 | type: "Softmax"
455 | bottom: "conv6-1"
456 | top: "prob1"
457 | }
--------------------------------------------------------------------------------
/main:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/main
--------------------------------------------------------------------------------
/pictures/QR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/pictures/QR.png
--------------------------------------------------------------------------------
/pictures/modification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/pictures/modification.png
--------------------------------------------------------------------------------
/pictures/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/pictures/qrcode.png
--------------------------------------------------------------------------------
/pictures/result.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/pictures/result.jpg
--------------------------------------------------------------------------------
/pictures/vrcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/pictures/vrcode.jpg
--------------------------------------------------------------------------------
/result.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PKUZHOU/MTCNN_FaceDetection_TensorRT/dfad60565216a68413f434b500168c456fdd2587/result.jpg
--------------------------------------------------------------------------------
/src/baseEngine.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-5-4.
3 | //
4 |
5 | #include "baseEngine.h"
6 | baseEngine::baseEngine(const char * prototxt,const char* model,const char* input_name,const char*location_name,
7 | const char* prob_name, const char *point_name) :
8 | prototxt(prototxt),
9 | model(model),
10 | INPUT_BLOB_NAME(input_name),
11 | OUTPUT_LOCATION_NAME(location_name),
12 | OUTPUT_PROB_NAME(prob_name),
13 | OUTPUT_POINT_NAME(point_name)
14 | {
15 | };
16 | baseEngine::~baseEngine() {
17 | shutdownProtobufLibrary();
18 | }
19 |
20 | void baseEngine::init(int row,int col) {
21 |
22 | }
23 | void baseEngine::caffeToGIEModel(const std::string &deployFile, // name for caffe prototxt
24 | const std::string &modelFile, // name for model
25 | const std::vector &outputs, // network outputs
26 | unsigned int maxBatchSize, // batch size - NB must be at least as large as the batch we want to run with)
27 | IHostMemory *&gieModelStream) // output buffer for the GIE model
28 | {
29 | // create the builder
30 | IBuilder *builder = createInferBuilder(gLogger);
31 |
32 | // parse the caffe model to populate the network, then set the outputs
33 | INetworkDefinition *network = builder->createNetwork();
34 | ICaffeParser *parser = createCaffeParser();
35 |
36 | const IBlobNameToTensor *blobNameToTensor = parser->parse(deployFile.c_str(),
37 | modelFile.c_str(),
38 | *network,
39 | nvinfer1::DataType::kFLOAT);
40 | // specify which tensors are outputs
41 | for (auto &s : outputs)
42 | network->markOutput(*blobNameToTensor->find(s.c_str()));
43 |
44 | // Build the engine
45 | builder->setMaxBatchSize(maxBatchSize);
46 | builder->setMaxWorkspaceSize(1 << 25);
47 | ICudaEngine*engine = builder->buildCudaEngine(*network);
48 | assert(engine);
49 | context = engine->createExecutionContext();
50 |
51 | // we don't need the network any more, and we can destroy the parser
52 | network->destroy();
53 | parser->destroy();
54 | builder->destroy();
55 |
56 | }
--------------------------------------------------------------------------------
/src/baseEngine.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-5-4.
3 | //
4 | #include "common.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "NvInfer.h"
13 | #include "NvCaffeParser.h"
14 | #ifndef MAIN_BASEENGINE_H
15 | #define MAIN_BASEENGINE_H
16 | using namespace nvinfer1;
17 | using namespace nvcaffeparser1;
18 | using namespace std;
19 |
20 | class baseEngine {
21 | public:
22 | baseEngine(const char *prototxt,const char*model,const char*out_name,
23 | const char*location_name,const char*prob_name,const char *point_name = NULL);
24 | virtual ~baseEngine();
25 | virtual void caffeToGIEModel(const std::string& deployFile, // name for caffe prototxt
26 | const std::string& modelFile, // name for model
27 | const std::vector& outputs, // network outputs
28 | unsigned int maxBatchSize, // batch size - NB must be at least as large as the batch we want to run with)
29 | IHostMemory *&gieModelStream); // output buffer for the GIE model
30 | virtual void init(int row,int col);
31 | friend class Pnet;
32 | const string prototxt;
33 | const string model ;
34 | const char *INPUT_BLOB_NAME;
35 | const char *OUTPUT_PROB_NAME;
36 | const char *OUTPUT_LOCATION_NAME;
37 | const char *OUTPUT_POINT_NAME;
38 | Logger gLogger;
39 | IExecutionContext *context;
40 | };
41 | #endif //MAIN_BASEENGINE_H
42 |
--------------------------------------------------------------------------------
/src/common.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-4-30.
3 | //
4 |
5 | #include "common.h"
6 | std::string locateFile(const std::string& input, const std::vector & directories)
7 | {
8 | std::string file;
9 | const int MAX_DEPTH{10};
10 | bool found{false};
11 | for (auto &dir : directories)
12 | {
13 | file = dir + input;
14 | for (int i = 0; i < MAX_DEPTH && !found; i++)
15 | {
16 | std::ifstream checkFile(file.c_str());
17 | found = checkFile.is_open();
18 | if (found) break;
19 | file = "../" + file;
20 | }
21 | if (found) break;
22 | file.clear();
23 | }
24 |
25 | assert(!file.empty() && "Could not find a file due to it not existing in the data directory.");
26 | return file;
27 | }
28 |
29 | void readPGMFile(const std::string& fileName, uint8_t *buffer, int inH, int inW)
30 | {
31 | std::ifstream infile(fileName, std::ifstream::binary);
32 | assert(infile.is_open() && "Attempting to read from a file that is not open.");
33 | std::string magic, h, w, max;
34 | infile >> magic >> h >> w >> max;
35 | infile.seekg(1, infile.cur);
36 | infile.read(reinterpret_cast(buffer), inH*inW);
37 | }
38 |
--------------------------------------------------------------------------------
/src/common.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-4-30.
3 | //
4 |
5 | #ifndef _TRT_COMMON_H_
6 | #define _TRT_COMMON_H_
7 | #include "NvInfer.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | //#include
13 | #include
14 | #define CHECK(status) \
15 | { \
16 | if (status != 0) \
17 | { \
18 | std::cout << "Cuda failure: " << status; \
19 | abort(); \
20 | } \
21 | }
22 |
23 |
24 | // Logger for GIE info/warning/errors
25 | class Logger : public nvinfer1::ILogger
26 | {
27 | public:
28 | void log(nvinfer1::ILogger::Severity severity, const char* msg) override
29 | {
30 | // suppress info-level messages
31 | if (severity == Severity::kINFO) return;
32 |
33 | switch (severity)
34 | {
35 | case Severity::kINTERNAL_ERROR: std::cerr << "INTERNAL_ERROR: "; break;
36 | case Severity::kERROR: std::cerr << "ERROR: "; break;
37 | case Severity::kWARNING: std::cerr << "WARNING: "; break;
38 | case Severity::kINFO: std::cerr << "INFO: "; break;
39 | default: std::cerr << "UNKNOWN: "; break;
40 | }
41 | std::cerr << msg << std::endl;
42 | }
43 | };
44 |
45 | std::string locateFile(const std::string& input, const std::vector & directories);
46 | void readPGMFile(const std::string& fileName, uint8_t *buffer, int inH, int inW);
47 | #endif // _TRT_COMMON_H_
48 |
--------------------------------------------------------------------------------
/src/demo.cpp:
--------------------------------------------------------------------------------
1 | #include "network.h"
2 | #include "mtcnn.h"
3 | #include
4 |
5 | void camera_test(int frames)
6 | {
7 | Mat image;
8 | VideoCapture cap(0);
9 | if(!cap.isOpened())
10 | cout<<"fail to open!"<>image;
12 | if(!image.data) {
13 | cout << "unable to open camera" << endl;
14 | return;
15 | }
16 | mtcnn find(image.rows, image.cols);
17 | clock_t start;
18 | int stop = frames;
19 | while(stop--){
20 | start = clock();
21 | cap>>image;
22 | find.findFace(image);
23 | imshow("result", image);
24 | waitKey(1);
25 | start = clock() -start;
26 | cout<<"time is "<<(double)start/CLOCKS_PER_SEC<MIN_DET_SIZE){
18 | if(factor_count>0)m = m*factor;
19 | scales_.push_back(m);
20 | minl *= factor;
21 | factor_count++;
22 | }
23 | float minside = row::iterator it = scales_.begin(); it != scales_.end(); it++){
26 | if (*it > 1){
27 | cout << "the minsize is too small" << endl;
28 | while (1);
29 | }
30 | if (*it < (MIN_DET_SIZE / minside)){
31 | scales_.resize(count);
32 | break;
33 | }
34 | count++;
35 | }
36 |
37 | cout<<"Start generating TenosrRT runtime models"<init(24,24);
51 | refineNet = new Rnet(*rnet_engine);
52 |
53 | //generate onet model
54 | onet_engine = new Onet_engine();
55 | onet_engine->init(48,48);
56 | outNet = new Onet(*onet_engine);
57 | cout<<"End generating TensorRT runtime models"<::iterator it=(*simpleFace_[i]).boundingBox_.begin(); it!= (*simpleFace_[i]).boundingBox_.end();it++){
83 | if((*it).exist){
84 | firstBbox_.push_back(*it);
85 | order.score = (*it).score;
86 | order.oriOrder = count;
87 | firstOrderScore_.push_back(order);
88 | count++;
89 | }
90 | }
91 | (*simpleFace_[i]).bboxScore_.clear();
92 | (*simpleFace_[i]).boundingBox_.clear();
93 | }
94 | //the first stage's nms
95 | if(count<1)return;
96 | nms(firstBbox_, firstOrderScore_, nms_threshold[0]);
97 | refineAndSquareBbox(firstBbox_, image.rows, image.cols,true);
98 | #ifdef LOG
99 | first_time = clock() - first_time;
100 | cout<<"first time is "<<1000*(double)first_time/CLOCKS_PER_SEC<::iterator it=firstBbox_.begin(); it!=firstBbox_.end();it++){
106 | if((*it).exist){
107 | Rect temp((*it).y1, (*it).x1, (*it).y2-(*it).y1, (*it).x2-(*it).x1);
108 | Mat secImage;
109 | resize(image(temp), secImage, Size(24, 24), 0, 0, cv::INTER_LINEAR);
110 | transpose(secImage,secImage);
111 | refineNet->run(secImage,*rnet_engine);
112 | if(*(refineNet->score_->pdata+1)>refineNet->Rthreshold){
113 | memcpy(it->regreCoord, refineNet->location_->pdata, 4*sizeof(mydataFmt));
114 | it->area = (it->x2 - it->x1)*(it->y2 - it->y1);
115 | it->score = *(refineNet->score_->pdata+1);
116 | secondBbox_.push_back(*it);
117 | order.score = it->score;
118 | order.oriOrder = count++;
119 | secondBboxScore_.push_back(order);
120 | }
121 | else{
122 | (*it).exist=false;
123 | }
124 | }
125 | }
126 | if(count<1)return;
127 | nms(secondBbox_, secondBboxScore_, nms_threshold[1]);
128 | refineAndSquareBbox(secondBbox_, image.rows, image.cols,true);
129 | second_time = clock() - second_time;
130 | #ifdef LOG
131 | cout<<"second time is "<<1000*(double)second_time/CLOCKS_PER_SEC<::iterator it=secondBbox_.begin(); it!=secondBbox_.end();it++){
137 | if((*it).exist){
138 | Rect temp((*it).y1, (*it).x1, (*it).y2-(*it).y1, (*it).x2-(*it).x1);
139 | Mat thirdImage;
140 | resize(image(temp), thirdImage, Size(48, 48), 0, 0, cv::INTER_LINEAR);
141 | transpose(thirdImage,thirdImage);
142 | outNet->run(thirdImage,*onet_engine);
143 | mydataFmt *pp=NULL;
144 | if(*(outNet->score_->pdata+1)>outNet->Othreshold){
145 | memcpy(it->regreCoord, outNet->location_->pdata, 4*sizeof(mydataFmt));
146 | it->area = (it->x2 - it->x1)*(it->y2 - it->y1);
147 | it->score = *(outNet->score_->pdata+1);
148 | pp = outNet->points_->pdata;
149 | for(int num=0;num<5;num++){
150 | (it->ppoint)[num] = it->y1 + (it->y2 - it->y1)*(*(pp+num));
151 | }
152 | for(int num=0;num<5;num++){
153 | (it->ppoint)[num+5] = it->x1 + (it->x2 - it->x1)*(*(pp+num+5));
154 | }
155 | thirdBbox_.push_back(*it);
156 | order.score = it->score;
157 | order.oriOrder = count++;
158 | thirdBboxScore_.push_back(order);
159 | }
160 | else{
161 | it->exist=false;
162 | }
163 | }
164 | }
165 |
166 | if(count<1)return;
167 | refineAndSquareBbox(thirdBbox_, image.rows, image.cols, true);
168 | nms(thirdBbox_, thirdBboxScore_, nms_threshold[2], "Min");
169 | #ifdef LOG
170 | third_time = clock() - third_time;
171 | cout<<"third time is "<<1000*(double)third_time/CLOCKS_PER_SEC<::iterator it=thirdBbox_.begin(); it!=thirdBbox_.end();it++){
174 | if((*it).exist){
175 | rectangle(image, Point((*it).y1, (*it).x1), Point((*it).y2, (*it).x2), Scalar(0,0,255), 2,8,0);
176 | for(int num=0;num<5;num++)circle(image,Point((int)*(it->ppoint+num), (int)*(it->ppoint+num+5)),3,Scalar(0,255,255), -1);
177 | }
178 | }
179 | firstBbox_.clear();
180 | firstOrderScore_.clear();
181 | secondBbox_.clear();
182 | secondBboxScore_.clear();
183 | thirdBbox_.clear();
184 | thirdBboxScore_.clear();
185 | }
186 |
--------------------------------------------------------------------------------
/src/mtcnn.h:
--------------------------------------------------------------------------------
1 | #ifndef MTCNN_H
2 | #define MTCNN_H
3 | #include "network.h"
4 | #include "pnet_rt.h"
5 | #include "rnet_rt.h"
6 | #include "onet_rt.h"
7 | class mtcnn
8 | {
9 | public:
10 | mtcnn(int row, int col);
11 | ~mtcnn();
12 | void findFace(Mat &image);
13 | private:
14 | Mat reImage;
15 | float nms_threshold[3];
16 | vector scales_;
17 | Pnet_engine *pnet_engine;
18 | Pnet **simpleFace_;
19 | vector firstBbox_;
20 | vector firstOrderScore_;
21 | Rnet *refineNet;
22 | Rnet_engine *rnet_engine;
23 | vector secondBbox_;
24 | vector secondBboxScore_;
25 | Onet *outNet;
26 | Onet_engine *onet_engine;
27 | vector thirdBbox_;
28 | vector thirdBboxScore_;
29 | };
30 |
31 | #endif
--------------------------------------------------------------------------------
/src/network.cpp:
--------------------------------------------------------------------------------
1 | #include "network.h"
2 | void image2Matrix(const Mat &image, const struct pBox *pbox){
3 | if ((image.data == NULL) || (image.type() != CV_8UC3)){
4 | cout << "image's type is wrong!!Please set CV_8UC3" << endl;
5 | return;
6 | }
7 | if (pbox->pdata == NULL){
8 | return;
9 | }
10 | mydataFmt *p = pbox->pdata;
11 | for (int rowI = 0; rowI < image.rows; rowI++){
12 | for (int colK = 0; colK < image.cols; colK++){
13 | *p = (image.at(rowI, colK)[2] - 127.5)*0.007812;
14 | *(p + image.rows*image.cols) = (image.at(rowI, colK)[1] - 127.5)*0.0078125;
15 | *(p + 2*image.rows*image.cols) = (image.at(rowI, colK)[0] - 127.5)*0.0078125;
16 | p++;
17 | }
18 | }
19 | }
20 | bool cmpScore(struct orderScore lsh, struct orderScore rsh){
21 | if(lsh.score &boundingBox_, vector &bboxScore_, const float overlap_threshold, string modelname){
27 | if(boundingBox_.empty()){
28 | return;
29 | }
30 | std::vector heros;
31 | //sort the score
32 | sort(bboxScore_.begin(), bboxScore_.end(), cmpScore);
33 |
34 | int order = 0;
35 | float IOU = 0;
36 | float maxX = 0;
37 | float maxY = 0;
38 | float minX = 0;
39 | float minY = 0;
40 | while(bboxScore_.size()>0){
41 | order = bboxScore_.back().oriOrder;
42 | bboxScore_.pop_back();
43 | if(order<0)continue;
44 | heros.push_back(order);
45 | boundingBox_.at(order).exist = false;//delete it
46 |
47 | for(int num=0;numboundingBox_.at(order).x1)?boundingBox_.at(num).x1:boundingBox_.at(order).x1;
51 | maxY = (boundingBox_.at(num).y1>boundingBox_.at(order).y1)?boundingBox_.at(num).y1:boundingBox_.at(order).y1;
52 | minX = (boundingBox_.at(num).x20)?(minX-maxX+1):0;
56 | maxY = ((minY-maxY+1)>0)?(minY-maxY+1):0;
57 | //IOU reuse for the area of two bbox
58 | IOU = maxX * maxY;
59 | if(!modelname.compare("Union"))
60 | IOU = IOU/(boundingBox_.at(num).area + boundingBox_.at(order).area - IOU);
61 | else if(!modelname.compare("Min")){
62 | IOU = IOU/((boundingBox_.at(num).areaoverlap_threshold){
65 | boundingBox_.at(num).exist=false;
66 | for(vector::iterator it=bboxScore_.begin(); it!=bboxScore_.end();it++){
67 | if((*it).oriOrder == num) {
68 | (*it).oriOrder = -1;
69 | break;
70 | }
71 | }
72 | }
73 | }
74 | }
75 | }
76 | for(int i=0;i &vecBbox, const int &height, const int &width, bool square = true){
80 | if(vecBbox.empty()){
81 | cout<<"Bbox is empty!!"<::iterator it=vecBbox.begin(); it!=vecBbox.end();it++){
88 | if((*it).exist){
89 | bbh = (*it).x2 - (*it).x1 + 1;
90 | bbw = (*it).y2 - (*it).y1 + 1;
91 | x1 = (*it).x1 + (*it).regreCoord[1]*bbh;
92 | y1 = (*it).y1 + (*it).regreCoord[0]*bbw;
93 | x2 = (*it).x2 + (*it).regreCoord[3]*bbh;
94 | y2 = (*it).y2 + (*it).regreCoord[2]*bbw;
95 |
96 |
97 |
98 | h = x2 - x1 + 1;
99 | w = y2 - y1 + 1;
100 |
101 | if(square)
102 | {
103 | maxSide = (h>w)?h:w;
104 | x1 = x1 + h*0.5 - maxSide*0.5;
105 | y1 = y1 + w*0.5 - maxSide*0.5;
106 | (*it).x2 = round(x1 + maxSide - 1);
107 | (*it).y2 = round(y1 + maxSide - 1);
108 | (*it).x1 = round(x1);
109 | (*it).y1 = round(y1);
110 | } else
111 | {
112 | (*it).x1 = x1;
113 | (*it).y1 = y1;
114 | (*it).x2 = x2;
115 | (*it).y2 = y2;
116 | }
117 |
118 |
119 |
120 | //boundary check
121 | if((*it).x1<0)(*it).x1=0;
122 | if((*it).y1<0)(*it).y1=0;
123 | if((*it).x2>height)(*it).x2 = height - 1;
124 | if((*it).y2>width)(*it).y2 = width - 1;
125 |
126 | it->area = (it->x2 - it->x1)*(it->y2 - it->y1);
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/src/network.h:
--------------------------------------------------------------------------------
1 | //c++ network author : liqi
2 | //Nangjing University of Posts and Telecommunications
3 | //date 2017.5.21,20:27
4 | #ifndef NETWORK_H
5 | #define NETWORK_H
6 | #include "opencv2/imgproc/imgproc.hpp"
7 | #include "opencv2/highgui/highgui.hpp"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include "pBox.h"
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include "NvInfer.h"
25 | #include "NvCaffeParser.h"
26 | using namespace cv;
27 |
28 | void image2Matrix(const Mat &image, const struct pBox *pbox);
29 | bool cmpScore(struct orderScore lsh, struct orderScore rsh);
30 | void nms(vector &boundingBox_, vector &bboxScore_, const float overlap_threshold, string modelname = "Union");
31 | void refineAndSquareBbox(vector &vecBbox, const int &height, const int &width,bool square);
32 |
33 | #endif
--------------------------------------------------------------------------------
/src/onet_rt.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-10-2.
3 | //
4 |
5 | #include "onet_rt.h"
6 |
7 | Onet_engine::Onet_engine() : baseEngine("det3_relu.prototxt",
8 | "det3_relu.caffemodel",
9 | "data",
10 | "conv6-2",
11 | "prob1",
12 | "conv6-3"
13 | ) {
14 | };
15 |
16 | Onet_engine::~Onet_engine() {
17 | shutdownProtobufLibrary();
18 | }
19 |
20 | void Onet_engine::init(int row, int col) {
21 | IHostMemory *gieModelStream{nullptr};
22 | const int max_batch_size = 1;
23 | //generate Tensorrt model
24 | caffeToGIEModel(prototxt, model, std::vector{OUTPUT_PROB_NAME, OUTPUT_LOCATION_NAME,OUTPUT_POINT_NAME}, max_batch_size,
25 | gieModelStream);
26 |
27 | }
28 |
29 |
30 | Onet::Onet(const Onet_engine &onet_engine) : BatchSize(1),
31 | INPUT_C(3),
32 | Engine(onet_engine.context->getEngine()) {
33 |
34 | Othreshold = 0.8;
35 | this->score_ = new pBox;
36 | this->location_ = new pBox;
37 | this->rgb = new pBox;
38 | this->points_ = new pBox;
39 | INPUT_W = 48;
40 | INPUT_H = 48;
41 | //calculate output shape
42 | this->score_->width = 1;
43 | this->score_->height = 1;
44 | this->score_->channel = 2;
45 |
46 | this->location_->width = 1;
47 | this->location_->height = 1;
48 | this->location_->channel = 4;
49 |
50 | this->points_->width = 1;
51 | this->points_->height = 1;
52 | this->points_->channel = 10;
53 |
54 |
55 | OUT_PROB_SIZE = this->score_->width * this->score_->height * this->score_->channel;
56 | OUT_LOCATION_SIZE = this->location_->width * this->location_->height * this->location_->channel;
57 | OUT_POINTS_SIZE = this->points_->width * this->points_->height * this->points_->channel;
58 | //allocate memory for outputs
59 | this->rgb->pdata = (float *) malloc(INPUT_C * INPUT_H * INPUT_W * sizeof(float));
60 | this->score_->pdata = (float *) malloc(2 * sizeof(float));
61 | this->location_->pdata = (float *) malloc(4 * sizeof(float));
62 | this->points_->pdata = (float *) malloc(10 * sizeof(float));
63 |
64 | assert(Engine.getNbBindings() == 4);
65 | inputIndex = Engine.getBindingIndex(onet_engine.INPUT_BLOB_NAME);
66 | outputProb = Engine.getBindingIndex(onet_engine.OUTPUT_PROB_NAME);
67 | outputLocation = Engine.getBindingIndex(onet_engine.OUTPUT_LOCATION_NAME);
68 | outputPoints = Engine.getBindingIndex(onet_engine.OUTPUT_POINT_NAME);
69 |
70 | //creat GPU buffers and stream
71 | CHECK(cudaMalloc(&buffers[inputIndex], BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float)));
72 | CHECK(cudaMalloc(&buffers[outputProb], BatchSize * OUT_PROB_SIZE * sizeof(float)));
73 | CHECK(cudaMalloc(&buffers[outputLocation], BatchSize * OUT_LOCATION_SIZE * sizeof(float)));
74 | CHECK(cudaMalloc(&buffers[outputPoints], BatchSize * OUT_POINTS_SIZE * sizeof(float)));
75 | CHECK(cudaStreamCreate(&stream));
76 | }
77 |
78 | Onet::~Onet() {
79 |
80 | delete (score_);
81 | delete (location_);
82 | cudaStreamDestroy(stream);
83 | CHECK(cudaFree(buffers[inputIndex]));
84 | CHECK(cudaFree(buffers[outputProb]));
85 | CHECK(cudaFree(buffers[outputLocation]));
86 | CHECK(cudaFree(buffers[outputPoints]));
87 | }
88 |
89 | void Onet::run(Mat &image, const Onet_engine &onet_engine) {
90 |
91 |
92 | //DMA the input to the GPU ,execute the batch asynchronously and DMA it back;
93 | image2Matrix(image, this->rgb);
94 | CHECK(cudaMemcpyAsync(buffers[inputIndex], this->rgb->pdata,
95 | BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float),
96 | cudaMemcpyHostToDevice, stream));
97 | onet_engine.context->enqueue(BatchSize, buffers, stream, nullptr);
98 | CHECK(cudaMemcpyAsync(this->location_->pdata, buffers[outputLocation], BatchSize * OUT_LOCATION_SIZE* sizeof(float),
99 | cudaMemcpyDeviceToHost, stream));
100 | CHECK(cudaMemcpyAsync(this->score_->pdata, buffers[outputProb], BatchSize * OUT_PROB_SIZE* sizeof(float),
101 | cudaMemcpyDeviceToHost, stream));
102 | CHECK(cudaMemcpyAsync(this->points_->pdata, buffers[outputPoints], BatchSize * OUT_POINTS_SIZE* sizeof(float),
103 | cudaMemcpyDeviceToHost, stream));
104 | cudaStreamSynchronize(stream);
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/onet_rt.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-10-2.
3 | //
4 |
5 | #ifndef MAIN_ONET_RT_H
6 | #define MAIN_ONET_RT_H
7 | #include "baseEngine.h"
8 | #include "network.h"
9 |
10 |
11 | class Onet_engine : public baseEngine {
12 |
13 | public:
14 | Onet_engine();
15 | ~Onet_engine();
16 | void init(int row, int col);
17 | friend class Onet;
18 |
19 | };
20 |
21 | class Onet {
22 | public:
23 | Onet(const Onet_engine &onet_engine);
24 | ~Onet();
25 | void run(Mat &image, const Onet_engine &engine);
26 | mydataFmt Othreshold;
27 | cudaStream_t stream;
28 | struct pBox *location_;
29 | struct pBox *score_;
30 | struct pBox *points_;
31 | struct pBox *rgb;
32 | private:
33 | const int BatchSize;
34 | const int INPUT_C;
35 | const ICudaEngine &Engine;
36 | //must be computed at runtime
37 | int INPUT_H;
38 | int INPUT_W;
39 | int OUT_PROB_SIZE;
40 | int OUT_LOCATION_SIZE;
41 | int OUT_POINTS_SIZE;
42 | int inputIndex,outputProb,outputLocation,outputPoints;
43 | void *buffers[4];
44 |
45 | };
46 | #endif //MAIN_ONET_RT_H
47 |
--------------------------------------------------------------------------------
/src/pBox.h:
--------------------------------------------------------------------------------
1 | #ifndef PBOX_H
2 | #define PBOX_H
3 | #include
4 | #include
5 |
6 | using namespace std;
7 | #define mydataFmt float
8 |
9 |
10 | struct pBox
11 | {
12 | mydataFmt *pdata;
13 | int width;
14 | int height;
15 | int channel;
16 | };
17 | struct Bbox
18 | {
19 | float score;
20 | int x1;
21 | int y1;
22 | int x2;
23 | int y2;
24 | float area;
25 | bool exist;
26 | mydataFmt ppoint[10];
27 | mydataFmt regreCoord[4];
28 | };
29 |
30 | struct orderScore
31 | {
32 | mydataFmt score;
33 | int oriOrder;
34 | };
35 | #endif
--------------------------------------------------------------------------------
/src/pnet_rt.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-4-30.
3 | //
4 | #include "pnet_rt.h"
5 | #include
6 |
7 | // stuff we know about the network and the caffe input/output blobs
8 | Pnet_engine::Pnet_engine() : baseEngine("det1_relu.prototxt",
9 | "det1_relu.caffemodel",
10 | "data",
11 | "conv4-2",
12 | "prob1") {
13 | };
14 |
15 | Pnet_engine::~Pnet_engine() {
16 | shutdownProtobufLibrary();
17 | }
18 |
19 | void Pnet_engine::init(int row, int col) {
20 |
21 | //modifiy the input shape of prototxt, write to temp.prototxt
22 | int first_spce = 16, second_space = 4;
23 | fstream protofile;
24 | protofile.open(prototxt, ios::in);
25 | std::stringstream buffer;
26 | buffer << protofile.rdbuf();
27 | std::string contents(buffer.str());
28 | string::size_type position_h, position_w;
29 | position_h = contents.find("dim");
30 | while (isdigit(contents[position_h + first_spce])) {
31 | contents.erase(position_h + first_spce, 1);
32 | }
33 | contents.insert(position_h + first_spce, to_string(row));
34 | position_w = contents.find("dim", position_h + first_spce);
35 | while (isdigit(contents[position_w + second_space])) {
36 | contents.erase(position_w + second_space, 1);
37 | }
38 | contents.insert(position_w + second_space, to_string(col));
39 | protofile.close();
40 | protofile.open("temp.prototxt", ios::out);
41 | protofile.write(contents.c_str(), contents.size());
42 | protofile.close();
43 | IHostMemory *gieModelStream{nullptr};
44 | //generate Tensorrt model
45 | caffeToGIEModel("temp.prototxt", model, std::vector{OUTPUT_PROB_NAME, OUTPUT_LOCATION_NAME}, 1,
46 | gieModelStream);
47 |
48 | }
49 |
50 |
51 | Pnet::Pnet(int row, int col, const Pnet_engine &pnet_engine) : BatchSize(1),
52 | INPUT_C(3), Engine(pnet_engine.context->getEngine()) {
53 | Pthreshold = 0.6;
54 | nms_threshold = 0.5;
55 | this->score_ = new pBox;
56 | this->location_ = new pBox;
57 | this->rgb = new pBox;
58 | INPUT_W = col;
59 | INPUT_H = row;
60 | //calculate output shape
61 | this->score_->width = int(ceil((INPUT_W - 2) / 2.) - 4);
62 | this->score_->height = int(ceil((INPUT_H - 2) / 2.) - 4);
63 | this->score_->channel = 2;
64 |
65 | this->location_->width = int(ceil((INPUT_W - 2) / 2.) - 4);
66 | this->location_->height = int(ceil((INPUT_H - 2) / 2.) - 4);
67 | this->location_->channel = 4;
68 |
69 | OUT_PROB_SIZE = this->score_->width * this->score_->height * this->score_->channel;
70 | OUT_LOCATION_SIZE = this->location_->width * this->location_->height * this->location_->channel;
71 | //allocate memory for outputs
72 | this->rgb->pdata = (float *) malloc(INPUT_C * INPUT_H * INPUT_W * sizeof(float));
73 | this->score_->pdata = (float *) malloc(OUT_PROB_SIZE * sizeof(float));
74 | this->location_->pdata = (float *) malloc(OUT_LOCATION_SIZE * sizeof(float));
75 |
76 | assert(Engine.getNbBindings() == 3);
77 | inputIndex = Engine.getBindingIndex(pnet_engine.INPUT_BLOB_NAME),
78 | outputProb = Engine.getBindingIndex(pnet_engine.OUTPUT_PROB_NAME),
79 | outputLocation = Engine.getBindingIndex(pnet_engine.OUTPUT_LOCATION_NAME);
80 |
81 | //creat GPU buffers and stream
82 | CHECK(cudaMalloc(&buffers[inputIndex], BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float)));
83 | CHECK(cudaMalloc(&buffers[outputProb], BatchSize * OUT_PROB_SIZE * sizeof(float)));
84 | CHECK(cudaMalloc(&buffers[outputLocation], BatchSize * OUT_LOCATION_SIZE * sizeof(float)));
85 | CHECK(cudaStreamCreate(&stream));
86 | }
87 |
88 | Pnet::~Pnet() {
89 |
90 | delete (score_);
91 | delete (location_);
92 |
93 | cudaStreamDestroy(stream);
94 | CHECK(cudaFree(buffers[inputIndex]));
95 | CHECK(cudaFree(buffers[outputProb]));
96 | CHECK(cudaFree(buffers[outputLocation]));
97 | }
98 |
99 | void Pnet::run(Mat &image, float scale, const Pnet_engine &pnet_engine) {
100 |
101 |
102 | //DMA the input to the GPU ,execute the batch asynchronously and DMA it back;
103 | image2Matrix(image, this->rgb);
104 | CHECK(cudaMemcpyAsync(buffers[inputIndex], this->rgb->pdata,
105 | BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float),
106 | cudaMemcpyHostToDevice, stream));
107 | pnet_engine.context->enqueue(BatchSize, buffers, stream, nullptr);
108 | CHECK(cudaMemcpyAsync(this->score_->pdata, buffers[outputProb], BatchSize * OUT_PROB_SIZE * sizeof(float),
109 | cudaMemcpyDeviceToHost, stream));
110 | CHECK(cudaMemcpyAsync(this->location_->pdata, buffers[outputLocation],
111 | BatchSize * OUT_LOCATION_SIZE * sizeof(float), cudaMemcpyDeviceToHost, stream));
112 | cudaStreamSynchronize(stream);
113 | generateBbox(this->score_, this->location_, scale);
114 |
115 | }
116 |
117 | void Pnet::generateBbox(const struct pBox *score, const struct pBox *location, mydataFmt scale) {
118 | //for pooling
119 | int stride = 2;
120 | int cellsize = 12;
121 | int count = 0;
122 | //score p
123 | mydataFmt *p = score->pdata + score->width * score->height;
124 | mydataFmt *plocal = location->pdata;
125 | struct Bbox bbox;
126 | struct orderScore order;
127 | for (int row = 0; row < score->height; row++) {
128 | for (int col = 0; col < score->width; col++) {
129 | if (*p > Pthreshold) {
130 | bbox.score = *p;
131 | order.score = *p;
132 | order.oriOrder = count;
133 | bbox.x1 = round((stride * row + 1) / scale);
134 | bbox.y1 = round((stride * col + 1) / scale);
135 | bbox.x2 = round((stride * row + 1 + cellsize) / scale);
136 | bbox.y2 = round((stride * col + 1 + cellsize) / scale);
137 | bbox.exist = true;
138 | bbox.area = (bbox.x2 - bbox.x1) * (bbox.y2 - bbox.y1);
139 | for (int channel = 0; channel < 4; channel++)
140 | bbox.regreCoord[channel] = *(plocal + channel * location->width * location->height);
141 | boundingBox_.push_back(bbox);
142 | bboxScore_.push_back(order);
143 | count++;
144 | }
145 | p++;
146 | plocal++;
147 | }
148 | }
149 |
150 | }
--------------------------------------------------------------------------------
/src/pnet_rt.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-4-30.
3 | //
4 |
5 | #ifndef MAIN_PNET_RT_H
6 | #define MAIN_PNET_RT_H
7 |
8 | #include "network.h"
9 | #include "common.h"
10 | #include "baseEngine.h"
11 | #endif //MAIN_PNET_RT_H
12 | using namespace nvinfer1;
13 | using namespace nvcaffeparser1;
14 |
15 | class Pnet_engine:public baseEngine
16 | {
17 |
18 | public:
19 | Pnet_engine();
20 | ~Pnet_engine();
21 | void init(int row,int col);
22 | friend class Pnet;
23 |
24 | };
25 |
26 |
27 |
28 | class Pnet
29 | {
30 | public:
31 | Pnet(int row,int col,const Pnet_engine& pnet_engine);
32 | ~Pnet();
33 | void run(Mat &image, float scale,const Pnet_engine& engine);
34 | float nms_threshold;
35 | mydataFmt Pthreshold;
36 | cudaStream_t stream;
37 |
38 | vector boundingBox_;
39 | vector bboxScore_;
40 | private:
41 |
42 | const int BatchSize ;
43 | const int INPUT_C ;
44 | const ICudaEngine &Engine;
45 | //must be computed at runtime
46 | int INPUT_H ;
47 | int INPUT_W ;
48 | int OUT_PROB_SIZE;
49 | int OUT_LOCATION_SIZE;
50 | int inputIndex,
51 | outputProb,
52 | outputLocation;
53 | void *buffers[3];
54 | struct pBox *location_;
55 | struct pBox *score_;
56 | struct pBox *rgb;
57 |
58 | void generateBbox(const struct pBox *score, const struct pBox *location, mydataFmt scale);
59 | };
60 |
61 |
--------------------------------------------------------------------------------
/src/rnet_rt.cpp:
--------------------------------------------------------------------------------
1 |
2 | //Created by zhou on 18-5-4.
3 |
4 | #include "rnet_rt.h"
5 |
6 |
7 | Rnet_engine::Rnet_engine() : baseEngine("det2_relu.prototxt",
8 | "det2_relu.caffemodel",
9 | "data",
10 | "conv5-2",
11 | "prob1"
12 |
13 | ) {
14 | };
15 |
16 | Rnet_engine::~Rnet_engine() {
17 | shutdownProtobufLibrary();
18 | }
19 |
20 | void Rnet_engine::init(int row, int col) {
21 |
22 | IHostMemory *gieModelStream{nullptr};
23 | const int max_batch_size = 1;
24 | //generate Tensorrt model
25 | caffeToGIEModel(prototxt, model, std::vector{OUTPUT_PROB_NAME, OUTPUT_LOCATION_NAME}, max_batch_size,
26 | gieModelStream);
27 |
28 | }
29 |
30 |
31 | Rnet::Rnet(const Rnet_engine &rnet_engine) : BatchSize(1),
32 | INPUT_C(3),
33 | Engine(rnet_engine.context->getEngine()) {
34 |
35 | Rthreshold = 0.7;
36 | this->score_ = new pBox;
37 | this->location_ = new pBox;
38 | this->rgb = new pBox;
39 | INPUT_W = 24;
40 | INPUT_H = 24;
41 | //calculate output shape
42 | this->score_->width = 1;
43 | this->score_->height = 1;
44 | this->score_->channel = 2;
45 |
46 | this->location_->width = 1;
47 | this->location_->height = 1;
48 | this->location_->channel= 4;
49 |
50 | OUT_PROB_SIZE = this->score_->width * this->score_->height * this->score_->channel;
51 | OUT_LOCATION_SIZE = this->location_->width * this->location_->height * this->location_->channel;
52 | //allocate memory for outputs
53 | this->rgb->pdata = (float *) malloc(INPUT_C * INPUT_H * INPUT_W * sizeof(float));
54 | this->score_->pdata = (float *) malloc(2 * sizeof(float));
55 | this->location_->pdata = (float *) malloc(4 * sizeof(float));
56 |
57 | assert(Engine.getNbBindings() == 3);
58 | inputIndex = Engine.getBindingIndex(rnet_engine.INPUT_BLOB_NAME);
59 | outputProb = Engine.getBindingIndex(rnet_engine.OUTPUT_PROB_NAME);
60 | outputLocation = Engine.getBindingIndex(rnet_engine.OUTPUT_LOCATION_NAME);
61 | //creat GPU buffers and stream
62 | CHECK(cudaMalloc(&buffers[inputIndex], BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float)));
63 | CHECK(cudaMalloc(&buffers[outputProb], BatchSize * OUT_PROB_SIZE * sizeof(float)));
64 | CHECK(cudaMalloc(&buffers[outputLocation], BatchSize * OUT_LOCATION_SIZE * sizeof(float)));
65 | CHECK(cudaStreamCreate(&stream));
66 | }
67 |
68 | Rnet::~Rnet() {
69 | delete (score_);
70 | delete (location_);
71 | cudaStreamDestroy(stream);
72 | CHECK(cudaFree(buffers[inputIndex]));
73 | CHECK(cudaFree(buffers[outputProb]));
74 | CHECK(cudaFree(buffers[outputLocation]));
75 | }
76 |
77 | void Rnet::run(Mat &image, const Rnet_engine &rnet_engine) {
78 | //DMA the input to the GPU ,execute the batch asynchronously and DMA it back;
79 | image2Matrix(image, this->rgb);
80 | CHECK(cudaMemcpyAsync(buffers[inputIndex], this->rgb->pdata,
81 | BatchSize * INPUT_C * INPUT_H * INPUT_W * sizeof(float),
82 | cudaMemcpyHostToDevice, stream));
83 | rnet_engine.context->enqueue(BatchSize, buffers, stream, nullptr);
84 | CHECK(cudaMemcpyAsync(this->location_->pdata, buffers[outputLocation], BatchSize * OUT_LOCATION_SIZE* sizeof(float),
85 | cudaMemcpyDeviceToHost, stream));
86 | CHECK(cudaMemcpyAsync(this->score_->pdata, buffers[outputProb], BatchSize * OUT_PROB_SIZE* sizeof(float),
87 | cudaMemcpyDeviceToHost, stream));
88 | cudaStreamSynchronize(stream);
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/rnet_rt.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhou on 18-5-4.
3 | //
4 |
5 | #ifndef MAIN_RNET_RT_H
6 | #define MAIN_RNET_RT_H
7 |
8 | #include "baseEngine.h"
9 | #include "network.h"
10 |
11 |
12 | class Rnet_engine : public baseEngine {
13 |
14 | public:
15 | Rnet_engine();
16 | ~Rnet_engine();
17 | void init(int row, int col);
18 | friend class Rnet;
19 |
20 | };
21 |
22 | class Rnet {
23 | public:
24 | Rnet(const Rnet_engine &rnet_engine);
25 | ~Rnet();
26 | void run(Mat &image, const Rnet_engine &engine);
27 | mydataFmt Rthreshold;
28 | cudaStream_t stream;
29 | struct pBox *location_;
30 | struct pBox *score_;
31 | struct pBox *rgb;
32 | private:
33 | const int BatchSize;
34 | const int INPUT_C;
35 | const ICudaEngine &Engine;
36 | //must be computed at runtime
37 | int INPUT_H;
38 | int INPUT_W;
39 | int OUT_PROB_SIZE;
40 | int OUT_LOCATION_SIZE;
41 | int inputIndex,outputProb,outputLocation;
42 | void *buffers[3];
43 |
44 | };
45 |
46 |
47 | #endif //MAIN_RNET_RT_H
48 |
--------------------------------------------------------------------------------
/temp.prototxt:
--------------------------------------------------------------------------------
1 | name: "PNet"
2 | layer
3 | {
4 | name: "data"
5 | type: "Input"
6 | top: "data"
7 | input_param{shape:{dim:1 dim:3 dim:13 dim:17}}
8 | }
9 |
10 | layer {
11 | name: "conv1"
12 | type: "Convolution"
13 | bottom: "data"
14 | top: "conv1"
15 | param {
16 | lr_mult: 1
17 | }
18 | param {
19 | lr_mult: 2
20 | }
21 | convolution_param {
22 | num_output: 10
23 | kernel_size: 3
24 | stride: 1
25 | weight_filler {
26 | type: "xavier"
27 | }
28 | bias_filler {
29 | type: "constant"
30 | }
31 | }
32 | }
33 | layer {
34 | name: "ReLU1"
35 | type: "ReLU"
36 | bottom: "conv1"
37 | top: "conv1_1"
38 | }
39 |
40 | layer {
41 | name: "scale1_1"
42 | bottom: "conv1"
43 | top: "conv1_2"
44 | type: "Scale"
45 | scale_param {
46 | axis: 1
47 | bias_term:false
48 | }
49 | }
50 | layer {
51 | name: "ReLU1_2"
52 | type: "ReLU"
53 | bottom: "conv1_2"
54 | top: "conv1_2"
55 | }
56 | layer {
57 | name: "scale1_2"
58 | bottom: "conv1_2"
59 | top: "conv1_2"
60 | type: "Scale"
61 | scale_param {
62 | axis: 1
63 | bias_term:false
64 |
65 | }
66 | }
67 | layer {
68 | name: "eltwise-sum1"
69 | type: "Eltwise"
70 | bottom: "conv1_1"
71 | bottom: "conv1_2"
72 | top: "conv1_3"
73 | eltwise_param { operation: SUM }
74 | }
75 | layer {
76 | name: "pool1"
77 | type: "Pooling"
78 | bottom: "conv1_3"
79 | top: "pool1"
80 | pooling_param {
81 | pool: MAX
82 | kernel_size: 2
83 | stride: 2
84 | }
85 | }
86 |
87 | layer {
88 | name: "conv2"
89 | type: "Convolution"
90 | bottom: "pool1"
91 | top: "conv2"
92 | param {
93 | lr_mult: 1
94 | }
95 | param {
96 | lr_mult: 2
97 | }
98 | convolution_param {
99 | num_output: 16
100 | kernel_size: 3
101 | stride: 1
102 | weight_filler {
103 | type: "xavier"
104 | }
105 | bias_filler {
106 | type: "constant"
107 | }
108 | }
109 | }
110 | layer {
111 | name: "ReLU2"
112 | type: "ReLU"
113 | bottom: "conv2"
114 | top: "conv2_1"
115 | }
116 |
117 | layer {
118 | name: "scale2_1"
119 | bottom: "conv2"
120 | top: "conv2_2"
121 | type: "Scale"
122 | scale_param {
123 | axis: 1
124 | bias_term:false
125 |
126 | }
127 | }
128 | layer {
129 | name: "ReLU2_2"
130 | type: "ReLU"
131 | bottom: "conv2_2"
132 | top: "conv2_2"
133 | }
134 | layer {
135 | name: "scale2_2"
136 | bottom: "conv2_2"
137 | top: "conv2_2"
138 | type: "Scale"
139 | scale_param {
140 | axis: 1
141 | bias_term:false
142 | }
143 | }
144 | layer {
145 | name: "eltwise-sum2"
146 | type: "Eltwise"
147 | bottom: "conv2_1"
148 | bottom: "conv2_2"
149 | top: "conv2_3"
150 | eltwise_param { operation: SUM }
151 | }
152 |
153 |
154 | layer {
155 | name: "conv3"
156 | type: "Convolution"
157 | bottom: "conv2_3"
158 | top: "conv3"
159 | param {
160 | lr_mult: 1
161 | }
162 | param {
163 | lr_mult: 2
164 | }
165 | convolution_param {
166 | num_output: 32
167 | kernel_size: 3
168 | stride: 1
169 | weight_filler {
170 | type: "xavier"
171 | }
172 | bias_filler {
173 | type: "constant"
174 | }
175 | }
176 | }
177 | layer {
178 | name: "ReLU3"
179 | type: "ReLU"
180 | bottom: "conv3"
181 | top: "conv3_1"
182 | }
183 | layer {
184 | name: "scale3_1"
185 | bottom: "conv3"
186 | top: "conv3_2"
187 | type: "Scale"
188 | scale_param {
189 | axis: 1
190 | bias_term:false
191 | }
192 | }
193 | layer {
194 | name: "ReLU3_2"
195 | type: "ReLU"
196 | bottom: "conv3_2"
197 | top: "conv3_2"
198 | }
199 | layer {
200 | name: "scale3_2"
201 | bottom: "conv3_2"
202 | top: "conv3_2"
203 | type: "Scale"
204 | scale_param {
205 | axis: 1
206 | bias_term:false
207 | }
208 | }
209 | layer {
210 | name: "eltwise-sum3"
211 | type: "Eltwise"
212 | bottom: "conv3_1"
213 | bottom: "conv3_2"
214 | top: "conv3_3"
215 | eltwise_param { operation: SUM }
216 | }
217 |
218 | layer {
219 | name: "conv4-1"
220 | type: "Convolution"
221 | bottom: "conv3_3"
222 | top: "conv4-1"
223 | param {
224 | lr_mult: 1
225 | decay_mult: 1
226 | }
227 | param {
228 | lr_mult: 2
229 | }
230 | convolution_param {
231 | num_output: 2
232 | kernel_size: 1
233 | stride: 1
234 | weight_filler {
235 | type: "xavier"
236 | }
237 | bias_filler {
238 | type: "constant"
239 | }
240 | }
241 | }
242 |
243 | layer {
244 | name: "conv4-2"
245 | type: "Convolution"
246 | bottom: "conv3_3"
247 | top: "conv4-2"
248 | param {
249 | lr_mult: 1
250 | }
251 | param {
252 | lr_mult: 2
253 | }
254 | convolution_param {
255 | num_output: 4
256 | kernel_size: 1
257 | stride: 1
258 | weight_filler {
259 | type: "xavier"
260 | }
261 | bias_filler {
262 | type: "constant"
263 | }
264 | }
265 | }
266 | layer {
267 | name: "prob1"
268 | type: "Softmax"
269 | bottom: "conv4-1"
270 | top: "prob1"
271 | }
--------------------------------------------------------------------------------