VOC Release 5在windows上的使用

Introduction

Unpack it in your [PATH] and open it using Matlab. Add voc-release5 file to path in MATLAB. And you should read README in voc-release5 file firstly.
If you want to use this code, you first step is run compile.m. But voc-release5 code can only run on linux or OS X, So let’s modify source code in order to make it work on Windows.

Requirements

  1. Visual Studio 2013 (I don’t know whether VS2012 or VS2010 works or not, but you can try)
  2. Matlab 2015a (I don’t know whether Matlab201*a\/b works or not, but you can try)
  3. pthread library

compile

You should run pwd to ensure your current path is [PATH]\\voc-release5.And run compile.m

Delete system juding code

Firstly, you will get error like this:

1
2
Error using compile (line 14)
This code is not supported on Windows.

Open your compile.m, you’ll find this code according to your error information.

1
2
3
if ispc
error('This code is not supported on Windows.');
end

Comment it using “%” (Or you can use ‘CTRL+R’ in Matlab) , like this:

1
2
3
4
%if ispc
% error('This code is not supported on Windows.');
%end
%this code judge what system you use, so you should Comment it.

Of course you can delete it directly.

Go on running compile.m, error information as follows:

1
2
3
4
5
Error using fv_compile (line 14)
This code is not supported on Windows.

Error in compile (line 48)
fv_compile(opt, verb);

And you can use the same way to find code causing error according to error information and then to fix this bug.

Modify time.h

And Go on(‘go on’ means run compile.m again), you’ll get error like this:

1
2
3
4
Error using mex
cascade.cc
e:\projects\pedestrain_detection\voc-release5\star-cascade\timer.h(6) : fatal error C1083: Cannot open include file:
'sys/time.h': No such file or directory

Open time.h, and you can use this code as follows to replace it. See more details in link 1.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef _TIMER_H_  
#define _TIMER_H_

#include <string>
#include <sstream>
//#include <sys/time.h> //windows下的time.h中没有timeval定义
#include<windows.h> //windows下代替<sys/time.h>
#include<time.h> //windows下代替<sys/time.h>


using namespace std;

//windows下没有gettimeofday函数,从网上找的一个替代函数
int gettimeofday(struct timeval *tp, void *tzp)
{

time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm. tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = clock;
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}


class timer {
public:
timer(string timer_name) {
name = timer_name;
total_time = 0;
calls = 0;
};

~timer() {};

void tic() {
struct timeval tv;
gettimeofday(&tv, NULL);
last_time = (double)tv.tv_sec + 1e-6*(double)tv.tv_usec;
calls++;
};

void toc() {
struct timeval tv;
gettimeofday(&tv, NULL);
double cur_time = (double)tv.tv_sec + 1e-6*(double)tv.tv_usec;
total_time += cur_time - last_time;
};

const char *msg() {
ostringstream oss;
oss << "timer '" << name
<< "' = " << total_time << " sec in "
<< calls << " call(s)";
return oss.str().c_str();
};

void mexPrintTimer() {
mexPrintf("timer '%s' = %f sec in %d call(s)\n", name.c_str(), total_time, calls);
};

double getTotalTime() {
return total_time;
};

private:
string name;
int calls;
double last_time;
double total_time;
};

#endif

Modify resize.cc

Go on , get error like this:

1
2
3
4
5
6
7
Error using mex
resize.cc
E:\Projects\pedestrain_detection\voc-release5\features\resize.cc(36) : error C2057: expected constant expression
E:\Projects\pedestrain_detection\voc-release5\features\resize.cc(36) : error C2466: cannot allocate an array of constant
size 0
E:\Projects\pedestrain_detection\voc-release5\features\resize.cc(36) : error C2133: 'ofs' : unknown size
E:\Projects\pedestrain_detection\voc-release5\features\resize.cc(70) : error C3861: 'bzero': identifier not found

Open features\resize.cc, on line 36, replace it using

1
alphainfo *ofs = new alphainfo[len];

And go on ,get error like this:

1
2
3
Error using mex
resize.cc
E:\Projects\pedestrain_detection\voc-release5\features\resize.cc(70) : error C3861: 'bzero': identifier not found

Add this code in resize.cc. See more details in link 2:

1
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)

Modify dt.cc

And Go on,get error like this:

1
2
3
4
5
6
7
8
Error using mex
dt.cc
E:\Projects\pedestrain_detection\voc-release5\gdetect\dt.cc(61) : error C2065: 'int32_t' : undeclared identifier
E:\Projects\pedestrain_detection\voc-release5\gdetect\dt.cc(61) : error C2065: 'Ix' : undeclared identifier
E:\Projects\pedestrain_detection\voc-release5\gdetect\dt.cc(61) : error C2059: syntax error : ')'
E:\Projects\pedestrain_detection\voc-release5\gdetect\dt.cc(62) : error C2065: 'int32_t' : undeclared identifier
E:\Projects\pedestrain_detection\voc-release5\gdetect\dt.cc(62) : error C2065: 'Iy' : undeclared identifier
....and so on

We have two ways to fix it. See more details in link 3.

  1. Add #include <stdint.h>
  2. Add typedef __int32 int32_t; typedef unsigned __int32 uint32_t;

Before fix this bug, you can run mex -setup to check what c compiler you use. If you use VS2013, you can use the first way.

Then go on and get same error and use same way to fix it.

Change -o to -output

Go on and get this error:

1
2
3
4
Error using mex
Unknown MEX argument '-o'.
Error in compile (line 64)
eval([mexcmd ' gdetect/fconvsse.cc -o fconv']);

change -o to -output to fix this bug.

If you see the code on line 72, you will find eval([mexcmd ' gdetect/fconv_var_dim_MT.cc -o fconv_var_dim']);, change it too.

Configure pthread on Windows

Go on and get this error:

1
2
3
4
Error using mex
fconvsse.cc
E:\Projects\pedestrain_detection\voc-release5\gdetect\fconvsse.cc(8) : fatal error C1083: Cannot open include file:
'pthread.h': No such file or directory

The pthread library is multi-thread library in linux, Windows does not provide it. So we should download it and configure it by myself.

You should go here to download pthread.h, sched.h,dll\x64\pthreadVC2.dll,lib\X64\pthreadVC2.lib to fix bugs. See more details in link 4.

Tips: If your Matlab and windows are 32bit, you should download *.dll and *.lib from x86 file.

And put pthread.h and sched.h in your [VS_PATH]\VC\include (For me, it’s D:\Program Files\Microsoft Visual Studio 12.0\VC\include, it’s up to your VS installations path),
put pthreadVC2.dll in C:\Windows\System32, put pthreadVC2.lib in [VS_PATH]\VC\lib(For me, it’s D:\Program Files\Microsoft Visual Studio 12.0\VC\lib).

Modify fconvsse.cc

Then go on and get error:

1
2
3
4
5
6
7
8
9
10
11
12
Error using mex
fconvsse.cc
E:\Projects\pedestrain_detection\code\voc-release5\gdetect\fconvsse.cc(120) : error C2146: syntax error : missing ';'
before identifier '__attribute__'
E:\Projects\pedestrain_detection\code\voc-release5\gdetect\fconvsse.cc(120) : error C3861: '__attribute__': identifier
not found
E:\Projects\pedestrain_detection\code\voc-release5\gdetect\fconvsse.cc(120) : error C3861: 'aligned': identifier not
found
E:\Projects\pedestrain_detection\code\voc-release5\gdetect\fconvsse.cc(130) : error C3861: 'memalign': identifier not
found
E:\Projects\pedestrain_detection\code\voc-release5\gdetect\fconvsse.cc(163) : warning C4267: 'initializing' : conversion
from 'size_t' to 'mwSize', possible loss of data

Add #define __attribute__(X). See more details in link 5 and line 6.

Change #define malloc_aligned(a,b) memalign(a,b) to #define malloc_aligned(a,b) _aligned_malloc(b,a) on line 19. (Be careful here, I change the order of a and b in _aligned_malloc function). See more details in link 7, link 8 and link 9.

Why do we change order of a and b? The reason is :

1
2
3
void * _aligned_malloc(size_t size, size_t alignment);
void * memalign (size_t boundary, size_t size);
//Both alignment value and boundary value must be an integer power of 2. This two function have same function.

And replace process function using this code. See more details in link 10.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
void *process(void *thread_arg) {
thread_data *args = (thread_data *)thread_arg;
float *A = args->A;

float *B = args->B;
double *C = args->C;

const mwSize *A_dims = args->A_dims;
const mwSize *B_dims = args->B_dims;

const mwSize *C_dims = args->C_dims;

__m128 a, b, c;
double *dst = C;

for (int x = 0; x < C_dims[1]; x++) {
for (int y = 0; y < C_dims[0]; y++) {
__m128 v = _mm_setzero_ps(), v1 = _mm_setzero_ps(), v2 = _mm_setzero_ps(), v3 = _mm_setzero_ps();
const float *A_src = A + y*NUM_FEATURES + x*A_dims[0] * NUM_FEATURES;
const float *B_src = B;


for (int xp = 0; xp < B_dims[1]; xp++) {
const float *A_off = A_src;
const float *B_off = B_src;

for (int yp = 0; yp < B_dims[0]; yp++) {
a = _mm_load_ps(A_off + 0);
b = _mm_load_ps(B_off + 0);
c = _mm_mul_ps(a, b);
v1 = _mm_add_ps(v1, c);

a = _mm_load_ps(A_off + 4);
b = _mm_load_ps(B_off + 4);
c = _mm_mul_ps(a, b);
v2 = _mm_add_ps(v2, c);

a = _mm_load_ps(A_off + 8);
b = _mm_load_ps(B_off + 8);
c = _mm_mul_ps(a, b);
v3 = _mm_add_ps(v3, c);

a = _mm_load_ps(A_off + 12);
b = _mm_load_ps(B_off + 12);
c = _mm_mul_ps(a, b);
v1 = _mm_add_ps(v1, c);

a = _mm_load_ps(A_off + 16);
b = _mm_load_ps(B_off + 16);
c = _mm_mul_ps(a, b);
v2 = _mm_add_ps(v2, c);

a = _mm_load_ps(A_off + 20);
b = _mm_load_ps(B_off + 20);
c = _mm_mul_ps(a, b);
v3 = _mm_add_ps(v3, c);

a = _mm_load_ps(A_off + 24);
b = _mm_load_ps(B_off + 24);
c = _mm_mul_ps(a, b);
v1 = _mm_add_ps(v1, c);

a = _mm_load_ps(A_off + 28);
b = _mm_load_ps(B_off + 28);
c = _mm_mul_ps(a, b);
v2 = _mm_add_ps(v2, c);

// N.B. Unroll me more/less if you change NUM_FEATURES

A_off += NUM_FEATURES;
B_off += NUM_FEATURES;
}
A_src += A_dims[0] * NUM_FEATURES;
B_src += B_dims[0] * NUM_FEATURES;

}
v = _mm_add_ps(v, v1);
v = _mm_add_ps(v, v2);
v = _mm_add_ps(v, v3);

// buf[] must be 16-byte aligned
__declspec(align(16)) float buf[4];
_mm_store_ps(buf, v);

*(dst++) = buf[0] + buf[1] + buf[2] + buf[3];
}
}
pthread_exit(NULL);
return 0;
}

Add this code in fconvsse.cc to prevent link error:

1
2
3
#pragma comment(lib, "[VS_PATH]\\VC\\lib\\pthreadVC2.lib")
//for me, it's #pragma comment(lib, "D:\\Program Files\\Microsoft Visual Studio 12.0\\VC\\lib\\pthreadVC2.lib")
//Here you should use absolute path to ensure that compiler can find this lib.

Modify fconv_var_dim_MT.cc

Replace process function as mentioned before.
Add #include <xmmintrin.h> and #pragma comment(lib, "D:\\Program Files\\Microsoft Visual Studio 12.0\\VC\\lib\\pthreadVC2.lib") and #define NUM_FEATURES 32.

Now, Run compile.m again, it completed successfully!!!

国内的朋友看到我全篇用英文写请不要说我装逼,因为我在下载完这个code发现在windows下运行不了,网上google发现了一些别人写的教程,但是人家直接把多线程这一块注释掉不用,加上他写的比较乱,所以我就自己配置了一下,因为想着肯定还有不少跟我一样的人,需要在windows下操作,本着分享的原则,所以就记录下这个过程,让我配置完再来写这篇博客,可能写的也会比较乱,不能按照整个顺序来,然而中文输入法和英文输入法切换还是比较麻烦的,所以就直接用英文写了,我英语水平仅仅过了六级而已,所以用词简单,大家应该能看懂的。