Skip to content

Commit 28af521

Browse files
committed
makes dpm works too
1 parent 79e8de2 commit 28af521

File tree

4 files changed

+286
-4
lines changed

4 files changed

+286
-4
lines changed

serve/bbf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,12 @@ int uri_bbf_detect_objects(const void* context, const void* parsed, ebb_buf* buf
209209
bbf_param_parser_t* parser = (bbf_param_parser_t*)parsed;
210210
if (parser->state != s_bbf_start)
211211
uri_bbf_param_parser_terminate(parser);
212-
ccv_dense_matrix_t* image = 0;
213212
if (parser->source.data == 0)
214213
{
215214
free(parser);
216215
return -1;
217216
}
217+
ccv_dense_matrix_t* image = 0;
218218
ccv_read(parser->source.data, &image, CCV_IO_ANY_STREAM | CCV_IO_GRAY, parser->source.written);
219219
free(parser->source.data);
220220
if (image == 0)
@@ -229,10 +229,10 @@ int uri_bbf_detect_objects(const void* context, const void* parsed, ebb_buf* buf
229229
free(parser);
230230
return -1;
231231
}
232-
int i = 0;
233232
if (seq->rnum > 0)
234233
{
235-
buf->len = seq->rnum * 21 + 2;
234+
int i;
235+
buf->len = 192 + seq->rnum * 21 + 2;
236236
char* data = (char*)malloc(buf->len);
237237
data[0] = '[';
238238
buf->written = 1;
@@ -252,7 +252,7 @@ int uri_bbf_detect_objects(const void* context, const void* parsed, ebb_buf* buf
252252
data[buf->written - 1] = (i == seq->rnum - 1) ? ']' : ',';
253253
}
254254
char http_header[192];
255-
snprintf(http_header, 192, "HTTP/1.1 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: %zd\r\n\r\n", buf->written);
255+
snprintf(http_header, 192, ebb_http_header, buf->written);
256256
size_t len = strnlen(http_header, 192);
257257
if (buf->written + len + 1 >= buf->len)
258258
{

serve/dpm.c

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
#include "uri.h"
2+
#include "ccv.h"
3+
#include <stdlib.h>
4+
#include <stdio.h>
5+
#include <ctype.h>
6+
7+
typedef struct {
8+
ccv_dpm_mixture_model_t* pedestrian;
9+
ccv_dpm_mixture_model_t* car;
10+
} dpm_context_t;
11+
12+
typedef enum {
13+
s_dpm_start,
14+
s_dpm_skip,
15+
s_dpm_name_interval,
16+
s_dpm_name_min_neighbors,
17+
s_dpm_name_threshold,
18+
s_dpm_name_model,
19+
s_dpm_name_source,
20+
} dpm_param_parse_state_t;
21+
22+
typedef struct {
23+
dpm_context_t* context;
24+
dpm_param_parse_state_t state;
25+
form_data_parser_t form_data_parser;
26+
ccv_dpm_param_t params;
27+
int cursor;
28+
char name[16];
29+
ccv_dpm_mixture_model_t* mixture_model;
30+
ebb_buf source;
31+
union {
32+
numeric_parser_t numeric_parser;
33+
string_parser_t string_parser;
34+
};
35+
} dpm_param_parser_t;
36+
37+
static void on_form_data_name(void* context, const char* buf, size_t len)
38+
{
39+
dpm_param_parser_t* parser = (dpm_param_parser_t*)context;
40+
if (len + parser->cursor > 15)
41+
return;
42+
memcpy(parser->name + parser->cursor, buf, len);
43+
parser->cursor += len;
44+
}
45+
46+
static void uri_dpm_param_parser_init(dpm_param_parser_t* parser)
47+
{
48+
form_data_parser_init(&parser->form_data_parser, parser);
49+
parser->form_data_parser.on_name = on_form_data_name;
50+
parser->params = ccv_dpm_default_params;
51+
parser->state = s_dpm_start;
52+
parser->cursor = 0;
53+
parser->source.data = 0;
54+
parser->source.len = 0;
55+
parser->source.written = 0;
56+
memset(parser->name, 0, sizeof(parser->name));
57+
}
58+
59+
static void uri_dpm_param_parser_terminate(dpm_param_parser_t* parser)
60+
{
61+
switch (parser->state)
62+
{
63+
case s_dpm_name_interval:
64+
parser->params.interval = (int)(parser->numeric_parser.result + 0.5);
65+
break;
66+
case s_dpm_name_min_neighbors:
67+
parser->params.min_neighbors = (int)(parser->numeric_parser.result + 0.5);
68+
break;
69+
case s_dpm_name_threshold:
70+
parser->params.threshold = parser->numeric_parser.result;
71+
break;
72+
case s_dpm_name_model:
73+
if (parser->string_parser.state == s_string_start)
74+
{
75+
if (strcmp(parser->string_parser.string, "pedestrian") == 0)
76+
parser->mixture_model = parser->context->pedestrian;
77+
else if (strcmp(parser->string_parser.string, "car") == 0)
78+
parser->mixture_model = parser->context->car;
79+
}
80+
break;
81+
default:
82+
break;
83+
}
84+
if (parser->state != s_dpm_start)
85+
{
86+
parser->state = s_dpm_start;
87+
memset(parser->name, 0, sizeof(parser->name));
88+
parser->cursor = 0;
89+
}
90+
}
91+
92+
void* uri_dpm_detect_objects_parse(const void* context, void* parsed, const char* buf, size_t len, uri_parse_state_t state, int header_index)
93+
{
94+
dpm_param_parser_t* parser;
95+
if (parsed)
96+
parser = (dpm_param_parser_t*)parsed;
97+
else {
98+
parser = (dpm_param_parser_t*)malloc(sizeof(dpm_param_parser_t));
99+
uri_dpm_param_parser_init(parser);
100+
parser->context = (dpm_context_t*)context;
101+
}
102+
switch (state)
103+
{
104+
case URI_QUERY_STRING:
105+
break;
106+
case URI_PARSE_TERMINATE:
107+
if (parser->state != s_dpm_start)
108+
uri_dpm_param_parser_terminate(parser); // collect result
109+
break;
110+
case URI_MULTIPART_HEADER_FIELD:
111+
if (parser->state != s_dpm_start)
112+
uri_dpm_param_parser_terminate(parser); // collect previous result
113+
form_data_parser_execute(&parser->form_data_parser, buf, len, header_index);
114+
break;
115+
case URI_MULTIPART_HEADER_VALUE:
116+
if (parser->state != s_dpm_start)
117+
uri_dpm_param_parser_terminate(parser); // collect previous result
118+
form_data_parser_execute(&parser->form_data_parser, buf, len, header_index);
119+
break;
120+
case URI_MULTIPART_DATA:
121+
if (parser->state == s_dpm_start)
122+
{
123+
// need to use name to get the correct state
124+
if (strcmp(parser->name, "interval") == 0)
125+
{
126+
parser->state = s_dpm_name_interval;
127+
numeric_parser_init(&parser->numeric_parser);
128+
} else if (strcmp(parser->name, "min_neighbors") == 0) {
129+
parser->state = s_dpm_name_min_neighbors;
130+
numeric_parser_init(&parser->numeric_parser);
131+
} else if (strcmp(parser->name, "threshold") == 0) {
132+
parser->state = s_dpm_name_threshold;
133+
numeric_parser_init(&parser->numeric_parser);
134+
} else if (strcmp(parser->name, "model") == 0) {
135+
parser->state = s_dpm_name_model;
136+
string_parser_init(&parser->string_parser);
137+
} else if (strcmp(parser->name, "source") == 0) {
138+
parser->state = s_dpm_name_source;
139+
} else
140+
parser->state = s_dpm_skip;
141+
}
142+
switch (parser->state)
143+
{
144+
default:
145+
break;
146+
case s_dpm_name_interval:
147+
case s_dpm_name_min_neighbors:
148+
case s_dpm_name_threshold:
149+
numeric_parser_execute(&parser->numeric_parser, buf, len);
150+
break;
151+
case s_dpm_name_model:
152+
string_parser_execute(&parser->string_parser, buf, len);
153+
if (parser->string_parser.state == s_string_overflow)
154+
parser->state = s_dpm_skip;
155+
break;
156+
case s_dpm_name_source:
157+
if (parser->source.len == 0)
158+
{
159+
parser->source.len = (len * 3 + 1) / 2;
160+
parser->source.data = (unsigned char*)malloc(parser->source.len);
161+
} else if (parser->source.written + len > parser->source.len) {
162+
parser->source.len = ((parser->source.len + len) * 3 + 1) / 2;
163+
parser->source.data = (unsigned char*)realloc(parser->source.data, parser->source.len);
164+
}
165+
memcpy(parser->source.data + parser->source.written, buf, len);
166+
parser->source.written += len;
167+
break;
168+
}
169+
break;
170+
}
171+
return parser;
172+
}
173+
174+
void* uri_dpm_detect_objects_init(void)
175+
{
176+
dpm_context_t* context = (dpm_context_t*)malloc(sizeof(dpm_context_t));
177+
context->pedestrian = ccv_load_dpm_mixture_model("../samples/pedestrian.m");
178+
context->car = ccv_load_dpm_mixture_model("../samples/car.m");
179+
return context;
180+
}
181+
182+
int uri_dpm_detect_objects_intro(const void* context, const void* parsed, ebb_buf* buf)
183+
{
184+
const static char dpm_desc[] =
185+
"HTTP/1.1 200 OK\r\nCache-Control: no-cache\r\nAccept: \r\nContent-Type: text/html\r\nContent-Length: 163\r\n\r\n"
186+
"<html><body><form enctype='multipart/form-data' method='post'><input name='model' value='pedestrian'><input type='file' name='source'><input type='submit'></form>\n";
187+
buf->data = (void*)dpm_desc;
188+
buf->len = sizeof(dpm_desc);
189+
return 0;
190+
}
191+
192+
int uri_dpm_detect_objects(const void* context, const void* parsed, ebb_buf* buf)
193+
{
194+
dpm_param_parser_t* parser = (dpm_param_parser_t*)parsed;
195+
if (parser->state != s_dpm_start)
196+
uri_dpm_param_parser_terminate(parser);
197+
if (parser->source.data == 0)
198+
{
199+
free(parser);
200+
return -1;
201+
}
202+
ccv_dense_matrix_t* image = 0;
203+
ccv_read(parser->source.data, &image, CCV_IO_ANY_STREAM | CCV_IO_GRAY, parser->source.written);
204+
free(parser->source.data);
205+
if (image == 0)
206+
{
207+
free(parser);
208+
return -1;
209+
}
210+
ccv_array_t* seq = ccv_dpm_detect_objects(image, &parser->mixture_model, 1, parser->params);
211+
ccv_matrix_free(image);
212+
if (seq == 0)
213+
{
214+
free(parser);
215+
return -1;
216+
}
217+
if (seq->rnum > 0)
218+
{
219+
int i, j;
220+
buf->len = 192 + seq->rnum * 131 + 2;
221+
char* data = (char*)malloc(buf->len);
222+
data[0] = '[';
223+
buf->written = 1;
224+
for (i = 0; i < seq->rnum; i++)
225+
{
226+
char cell[64];
227+
ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i);
228+
snprintf(cell, 64, "[[%d,%d,%d,%d,%f],[", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->confidence);
229+
size_t len = strnlen(cell, 64);
230+
while (buf->written + len >= buf->len)
231+
{
232+
buf->len = (buf->len * 3 + 1) / 2;
233+
data = (char*)realloc(data, buf->len);
234+
}
235+
memcpy(data + buf->written, cell, len);
236+
buf->written += len;
237+
for (j = 0; j < comp->pnum; j++)
238+
{
239+
snprintf(cell, 64, "[%d,%d,%d,%d,%f]", comp->part[j].rect.x, comp->part[j].rect.y, comp->part[j].rect.width, comp->part[j].rect.height, comp->part[j].confidence);
240+
len = strnlen(cell, 64);
241+
while (buf->written + len + 3 >= buf->len)
242+
{
243+
buf->len = (buf->len * 3 + 1) / 2;
244+
data = (char*)realloc(data, buf->len);
245+
}
246+
memcpy(data + buf->written, cell, len);
247+
buf->written += len + 1;
248+
data[buf->written - 1] = (j == comp->pnum - 1) ? ']' : ',';
249+
}
250+
buf->written += 2;
251+
data[buf->written - 2] = ']';
252+
data[buf->written - 1] = (i == seq->rnum - 1) ? ']' : ',';
253+
}
254+
char http_header[192];
255+
snprintf(http_header, 192, ebb_http_header, buf->written);
256+
size_t len = strnlen(http_header, 192);
257+
if (buf->written + len + 1 >= buf->len)
258+
{
259+
buf->len = buf->written + len + 1;
260+
data = (char*)realloc(data, buf->len);
261+
}
262+
memmove(data + len, data, buf->written);
263+
memcpy(data, http_header, len);
264+
buf->written += len + 1;
265+
data[buf->written - 1] = '\n';
266+
buf->data = data;
267+
buf->len = buf->written;
268+
buf->on_release = uri_ebb_buf_free;
269+
} else {
270+
buf->data = (void*)ebb_http_empty_array;
271+
buf->len = sizeof(ebb_http_empty_array);
272+
buf->on_release = 0;
273+
}
274+
ccv_array_free(seq);
275+
free(parser);
276+
return 0;
277+
}

serve/uri.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <stdlib.h>
44
#include <stdio.h>
55

6+
const char ebb_http_header[] = "HTTP/1.1 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: %zd\r\n\r\n";
7+
68
void uri_ebb_buf_free(ebb_buf* buf)
79
{
810
free(buf->data);

serve/uri.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33

44
#include "ebb.h"
55

6+
/* have to be static const char so that can use sizeof */
67
static const char ebb_http_404[] = "HTTP/1.1 404 Not Found\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 6\r\n\r\nfalse\n";
78
static const char ebb_http_empty_object[] = "HTTP/1.1 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 3\r\n\r\n{}\n";
89
static const char ebb_http_empty_array[] = "HTTP/1.1 201 Created\r\nCache-Control: no-cache\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 3\r\n\r\n[]\n";
10+
/* we should never sizeof ebb_http_header */
11+
extern const char ebb_http_header[];
912

1013
void uri_ebb_buf_free(ebb_buf* buf);
1114

0 commit comments

Comments
 (0)