Skip to content

Commit 2d3e3b7

Browse files
committed
Merge branch 'master' of github.com:seetaface/SeetaFaceEngine
2 parents 18691ae + 8f91907 commit 2d3e3b7

File tree

10 files changed

+192
-12
lines changed

10 files changed

+192
-12
lines changed

FaceDetection/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

FaceDetection/CMakeLists.txt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
cmake_minimum_required(VERSION 3.1.0)
2+
3+
project(seeta_facedet_lib)
4+
5+
# Build options
6+
option(BUILD_EXAMPLES "Set to ON to build examples" ON)
7+
option(USE_OPENMP "Set to ON to build use openmp" ON)
8+
option(USE_SSE "Set to ON to build use SSE" ON)
9+
10+
# Use C++11
11+
set(CMAKE_CXX_STANDARD 11)
12+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
13+
message(STATUS "C++11 support has been enabled by default.")
14+
15+
# Use SSE
16+
if (USE_SSE)
17+
add_definitions(-DUSE_SSE)
18+
message(STATUS "Use SSE")
19+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
20+
endif()
21+
22+
# Use OpenMP
23+
if (USE_OPENMP)
24+
find_package(OpenMP QUIET)
25+
if (OPENMP_FOUND)
26+
message(STATUS "Use OpenMP")
27+
add_definitions(-DUSE_OPENMP)
28+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
29+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
30+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
31+
endif()
32+
endif()
33+
34+
include_directories(include)
35+
36+
set(src_files
37+
src/util/nms.cpp
38+
src/util/image_pyramid.cpp
39+
src/io/lab_boost_model_reader.cpp
40+
src/io/surf_mlp_model_reader.cpp
41+
src/feat/lab_feature_map.cpp
42+
src/feat/surf_feature_map.cpp
43+
src/classifier/lab_boosted_classifier.cpp
44+
src/classifier/mlp.cpp
45+
src/classifier/surf_mlp.cpp
46+
src/face_detection.cpp
47+
src/fust.cpp
48+
)
49+
50+
# Build shared library
51+
add_library(seeta_facedet_lib SHARED ${src_files})
52+
set(facedet_required_libs seeta_facedet_lib)
53+
54+
# Build examples
55+
if (BUILD_EXAMPLES)
56+
message(STATUS "Build with examples.")
57+
find_package(OpenCV)
58+
if (NOT OpenCV_FOUND)
59+
message(WARNING "OpenCV not found. Test will not be built.")
60+
else()
61+
include_directories(${OpenCV_INCLUDE_DIRS})
62+
list(APPEND facedet_required_libs ${OpenCV_LIBS})
63+
64+
add_executable(facedet_test src/test/facedetection_test.cpp)
65+
target_link_libraries(facedet_test ${facedet_required_libs})
66+
endif()
67+
endif()

FaceDetection/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ FacenessNet [2] | 80x80 | n/a | 20 FPS
5858
7. *(Optional) Enable OpenMP support: (Project) Properities -> Configuration Properties -> C/C++ -> Language -> Open MP Support (or ... C/C++ -> Language [Intel C++] -> OpenMP Support). Define `USE_OPENMP` macro if necessary.*
5959
8. Build.
6060

61+
### How to Build in Linux
62+
- Build
63+
```shell
64+
mkdir build
65+
cd build
66+
cmake ..
67+
make -j${nproc}
68+
```
69+
70+
- Run demo
71+
```shell
72+
./build/facedet_test image_file model/seeta_fd_frontal_v1.0.bin
73+
```
74+
6175
### How to run SeetaFace Detector
6276

6377
The class for face detection is included in `seeta` namespace. To detect faces on an image, one should first
@@ -110,4 +124,4 @@ If you find SeetaFace Detection (FuSt) useful in your research work, please cons
110124

111125
### License
112126

113-
SeetaFace Detection is released under the [BSD 2-Clause license](../LICENSE).
127+
SeetaFace Detection is released under the [BSD 2-Clause license](../LICENSE).

FaceDetection/include/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,17 @@
3434

3535
#include <cstdint>
3636

37+
#if defined _WIN32
3738
#ifdef SEETA_EXPORTS
3839
#define SEETA_API __declspec(dllexport)
3940
#else
4041
#define SEETA_API __declspec(dllimport)
4142
#endif
4243

44+
#else
45+
#define SEETA_API
46+
#endif
47+
4348
#define DISABLE_COPY_AND_ASSIGN(classname) \
4449
private: \
4550
classname(const classname&); \

FaceDetection/include/feat/surf_feature_map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#define SEETA_FD_FEAT_SURF_FEATURE_MAP_H_
3434

3535
#include <cstdint>
36+
#include <cstring>
3637
#include <vector>
3738

3839
#include "common.h"

FaceDetection/include/util/image_pyramid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include <cstdint>
3636
#include <string>
37+
#include <cstring>
3738

3839
#include "common.h"
3940

FaceDetection/include/util/math_func.h

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
#ifndef SEETA_FD_UTIL_MATH_FUNC_H_
3333
#define SEETA_FD_UTIL_MATH_FUNC_H_
3434

35+
#ifdef USE_SSE
3536
#include <immintrin.h>
37+
#endif
3638

3739
#include <cstdint>
3840

@@ -49,31 +51,37 @@ class MathFunction {
4951

5052
static inline void VectorAdd(const int32_t* x, const int32_t* y, int32_t* z,
5153
int32_t len) {
54+
int32_t i;
55+
#ifdef USE_SSE
5256
__m128i x1;
5357
__m128i y1;
5458
const __m128i* x2 = reinterpret_cast<const __m128i*>(x);
5559
const __m128i* y2 = reinterpret_cast<const __m128i*>(y);
5660
__m128i* z2 = reinterpret_cast<__m128i*>(z);
5761

58-
int32_t i;
5962
for (i = 0; i < len - 4; i += 4) {
6063
x1 = _mm_loadu_si128(x2++);
6164
y1 = _mm_loadu_si128(y2++);
6265
_mm_storeu_si128(z2++, _mm_add_epi32(x1, y1));
6366
}
6467
for (; i < len; i++)
6568
*(z + i) = (*(x + i)) + (*(y + i));
69+
#else
70+
for (i = 0; i < len; i++)
71+
*(z + i) = (*(x + i)) + (*(y + i));
72+
#endif
6673
}
6774

6875
static inline void VectorSub(const int32_t* x, const int32_t* y, int32_t* z,
6976
int32_t len) {
77+
int32_t i;
78+
#ifdef USE_SSE
7079
__m128i x1;
7180
__m128i y1;
7281
const __m128i* x2 = reinterpret_cast<const __m128i*>(x);
7382
const __m128i* y2 = reinterpret_cast<const __m128i*>(y);
7483
__m128i* z2 = reinterpret_cast<__m128i*>(z);
7584

76-
int32_t i;
7785
for (i = 0; i < len - 4; i += 4) {
7886
x1 = _mm_loadu_si128(x2++);
7987
y1 = _mm_loadu_si128(y2++);
@@ -82,47 +90,62 @@ class MathFunction {
8290
}
8391
for (; i < len; i++)
8492
*(z + i) = (*(x + i)) - (*(y + i));
93+
#else
94+
for (i = 0; i < len; i++)
95+
*(z + i) = (*(x + i)) - (*(y + i));
96+
#endif
8597
}
8698

8799
static inline void VectorAbs(const int32_t* src, int32_t* dest, int32_t len) {
100+
int32_t i;
101+
#ifdef USE_SSE
88102
__m128i val;
89103
__m128i val_abs;
90104
const __m128i* x = reinterpret_cast<const __m128i*>(src);
91105
__m128i* y = reinterpret_cast<__m128i*>(dest);
92106

93-
int32_t i;
94107
for (i = 0; i < len - 4; i += 4) {
95108
val = _mm_loadu_si128(x++);
96109
val_abs = _mm_abs_epi32(val);
97110
_mm_storeu_si128(y++, val_abs);
98111
}
99112
for (; i < len; i++)
100113
dest[i] = (src[i] >= 0 ? src[i] : -src[i]);
114+
#else
115+
for (i = 0; i < len; i++)
116+
dest[i] = (src[i] >= 0 ? src[i] : -src[i]);
117+
#endif
101118
}
102119

103120
static inline void Square(const int32_t* src, uint32_t* dest, int32_t len) {
121+
int32_t i;
122+
#ifdef USE_SSE
104123
__m128i x1;
105124
const __m128i* x2 = reinterpret_cast<const __m128i*>(src);
106125
__m128i* y2 = reinterpret_cast<__m128i*>(dest);
107126

108-
int32_t i;
109127
for (i = 0; i < len - 4; i += 4) {
110128
x1 = _mm_loadu_si128(x2++);
111129
_mm_storeu_si128(y2++, _mm_mullo_epi32(x1, x1));
112130
}
113131
for (; i < len; i++)
114132
*(dest + i) = (*(src + i)) * (*(src + i));
133+
#else
134+
for (i = 0; i < len; i++)
135+
*(dest + i) = (*(src + i)) * (*(src + i));
136+
#endif
115137
}
116138

117139
static inline float VectorInnerProduct(const float* x, const float* y,
118140
int32_t len) {
141+
float prod = 0;
142+
int32_t i;
143+
#ifdef USE_SSE
119144
__m128 x1;
120145
__m128 y1;
121146
__m128 z1 = _mm_setzero_ps();
122-
float prod;
123147
float buf[4];
124148

125-
int32_t i;
126149
for (i = 0; i < len - 4; i += 4) {
127150
x1 = _mm_loadu_ps(x + i);
128151
y1 = _mm_loadu_ps(y + i);
@@ -132,7 +155,10 @@ class MathFunction {
132155
prod = buf[0] + buf[1] + buf[2] + buf[3];
133156
for (; i < len; i++)
134157
prod += x[i] * y[i];
135-
158+
#else
159+
for (i = 0; i < len; i++)
160+
prod += x[i] * y[i];
161+
#endif
136162
return prod;
137163
}
138164
};

FaceDetection/src/feat/surf_feature_map.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*
3030
*/
3131

32+
#include <cmath>
3233
#include "feat/surf_feature_map.h"
3334

3435
namespace seeta {
@@ -222,6 +223,8 @@ void SURFFeatureMap::ComputeIntegralImages() {
222223
void SURFFeatureMap::MaskIntegralChannel() {
223224
const int32_t* grad_x = grad_x_.data();
224225
const int32_t* grad_y = grad_y_.data();
226+
int32_t len = width_ * height_;
227+
#ifdef USE_SSE
225228
__m128i dx;
226229
__m128i dy;
227230
__m128i dx_mask;
@@ -231,7 +234,6 @@ void SURFFeatureMap::MaskIntegralChannel() {
231234
__m128i data;
232235
__m128i result;
233236
__m128i* src = reinterpret_cast<__m128i*>(int_img_.data());
234-
int32_t len = width_ * height_;
235237

236238
for (int32_t i = 0; i < len; i++) {
237239
dx = _mm_set1_epi32(*(grad_x++));
@@ -246,6 +248,32 @@ void SURFFeatureMap::MaskIntegralChannel() {
246248
result = _mm_and_si128(data, dx_mask);
247249
_mm_storeu_si128(src++, result);
248250
}
251+
#else
252+
int32_t dx, dy, dx_mask, dy_mask, cmp;
253+
int32_t xor_bits[] = {-1, -1, 0, 0};
254+
255+
int32_t* src = int_img_.data();
256+
for (int32_t i = 0; i < len; i++) {
257+
dy = *(grad_y++);
258+
dx = *(grad_x++);
259+
260+
cmp = dy < 0 ? 0xffffffff : 0x0;
261+
for (int32_t j = 0; j < 4; j++) {
262+
// cmp xor xor_bits
263+
dy_mask = cmp ^ xor_bits[j];
264+
*(src) = (*src) & dy_mask;
265+
src++;
266+
}
267+
268+
cmp = dx < 0 ? 0xffffffff : 0x0;
269+
for (int32_t j = 0; j < 4; j++) {
270+
// cmp xor xor_bits
271+
dx_mask = cmp ^ xor_bits[j];
272+
*(src) = (*src) & dx_mask;
273+
src++;
274+
}
275+
}
276+
#endif
249277
}
250278

251279
void SURFFeatureMap::Integral() {
@@ -265,6 +293,7 @@ void SURFFeatureMap::Integral() {
265293

266294
void SURFFeatureMap::VectorCumAdd(int32_t* x, int32_t len,
267295
int32_t num_channel) {
296+
#ifdef USE_SSE
268297
__m128i x1;
269298
__m128i y1;
270299
__m128i z1;
@@ -288,6 +317,14 @@ void SURFFeatureMap::VectorCumAdd(int32_t* x, int32_t len,
288317
_mm_storeu_si128(z2, z1);
289318
z2 = y2;
290319
}
320+
#else
321+
int32_t cols = len / num_channel - 1;
322+
for (int32_t i = 0; i < cols; i++) {
323+
int32_t* col1 = x + i * num_channel;
324+
int32_t* col2 = col1 + num_channel;
325+
seeta::fd::MathFunction::VectorAdd(col1, col2, col2, num_channel);
326+
}
327+
#endif
291328
}
292329

293330
void SURFFeatureMap::ComputeFeatureVector(const SURFFeature & feat,

FaceDetection/src/test/facedetection_test.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,18 @@
3939

4040
#include "face_detection.h"
4141

42+
using namespace std;
43+
4244
int main(int argc, char** argv) {
43-
const char* img_path = "test_image.jpg";
44-
seeta::FaceDetection detector("seeta_fd_frontal_v1.0.bin");
45+
if (argc < 3) {
46+
cout << "Usage: " << argv[0]
47+
<< " image_path model_path"
48+
<< endl;
49+
return -1;
50+
}
51+
52+
const char* img_path = argv[1];
53+
seeta::FaceDetection detector(argv[2]);
4554

4655
detector.SetMinFaceSize(40);
4756
detector.SetScoreThresh(2.f);
@@ -62,7 +71,26 @@ int main(int argc, char** argv) {
6271
img_data.height = img_gray.rows;
6372
img_data.num_channels = 1;
6473

74+
long t0 = cv::getTickCount();
6575
std::vector<seeta::FaceInfo> faces = detector.Detect(img_data);
76+
long t1 = cv::getTickCount();
77+
double secs = (t1 - t0)/cv::getTickFrequency();
78+
79+
cout << "Detections takes " << secs << " seconds " << endl;
80+
#ifdef USE_OPENMP
81+
cout << "OpenMP is used." << endl;
82+
#else
83+
cout << "OpenMP is not used. " << endl;
84+
#endif
85+
86+
#ifdef USE_SSE
87+
cout << "SSE is used." << endl;
88+
#else
89+
cout << "SSE is not used." << endl;
90+
#endif
91+
92+
cout << "Image size (wxh): " << img_data.width << "x"
93+
<< img_data.height << endl;
6694

6795
cv::Rect face_rect;
6896
int32_t num_face = static_cast<int32_t>(faces.size());

FaceIdentification/src/blob.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void Blob::Permute(int dim1, int dim2, int dim3, int dim4) {
126126
for (int i = 0; i < 4; ++ i)
127127
shape_[i] = tmp_shape[i];
128128
memcpy(dat, tmp, sizeof(float) * count_);
129-
delete tmp;
129+
delete[] tmp;
130130
}
131131

132132
void Blob::Release() {

0 commit comments

Comments
 (0)