/
process_frame.c
251 lines (207 loc) · 6.19 KB
/
process_frame.c
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#include "template.h"
#include <string.h>
#include <stdlib.h>
#define IMAGE(a) (data.u8TempImage[a])
#define SZ (sizeof(IMAGE(GRAYSCALE)))
#define NC (OSC_CAM_MAX_IMAGE_WIDTH / 2u)
#define LABEL_COLOR 0x80
OSC_ERR draw_bbox(struct OSC_PICTURE *picIn, struct OSC_VIS_REGIONS *regions, uint8 Color);
static void imhist(uint32_t hist[], const uint8_t* image);
static void erosion(uint8_t* dst, const uint8_t* src);
static void dilation(uint8_t* dst, const uint8_t* src);
static void thresh(uint8_t* dst, const uint8_t* src, uint8_t threshold);
static void region_labeling(uint8_t* dst);
static uint8_t otsu(const uint8_t* img);
void ProcessFrame(uint8 *pInputImg)
{
uint8_t thres = (uint8_t)data.ipc.state.nThreshold;
/* if the threshold is 0, the otsu algorithm is used */
if(thres == 0)
{
thres = otsu(IMAGE(GRAYSCALE));
}
data.ipc.state.thres_calc = thres;
/* make the threshold image */
thresh(IMAGE(THRESHOLD), IMAGE(GRAYSCALE), thres);
/* dilation */
dilation(IMAGE(DILATION), IMAGE(THRESHOLD));
/* erosion */
erosion(IMAGE(EROSION), IMAGE(DILATION));
/* do the region labeling stuff */
region_labeling(IMAGE(LABELIMG));
}
/* Drawing FuNCtion for Bounding Boxes; own implementation because Oscar only allows colored boxes; here in Gray value "Color" */
/* should only be used for debugging purposes because we should not drawn into a gray scale image */
OSC_ERR draw_bbox(struct OSC_PICTURE *picIn, struct OSC_VIS_REGIONS *regions, uint8 Color)
{
uint16 i, o;
uint8 *pImg = (uint8*)picIn->data;
const uint16 width = picIn->width;
for(o = 0; o < regions->noOfObjects; o++)//loop over regions
{
/* Draw the horizontal lines. */
for (i = regions->objects[o].bboxLeft; i < regions->objects[o].bboxRight; i += 1)
{
pImg[width * regions->objects[o].bboxTop + i] = Color;
pImg[width * (regions->objects[o].bboxBottom - 1) + i] = Color;
}
/* Draw the vertical lines. */
for (i = regions->objects[o].bboxTop; i < regions->objects[o].bboxBottom-1; i += 1)
{
pImg[width * i + regions->objects[o].bboxLeft] = Color;
pImg[width * i + regions->objects[o].bboxRight] = Color;
}
}
return SUCCESS;
}
static void imhist(uint32_t hist[], const uint8_t* image)
{
uint32_t idx;
/* loop through the whole image; don't care a rats arse whether these
are rows or columns because only the grey value is interesting */
for(idx = 0; idx < SZ; idx++)
{
/* this counts the grey values */
hist[*image] += 1;
/* next pixel */
image++;
}
}
static void erosion(uint8_t* dst, const uint8_t* src)
{
uint32_t r, c;
/* loop through all rows, but skop 1st and last one */
for(r = NC; r < SZ - NC; r+= NC)
{
/* loop through all columns, but skop 1st and last one */
for(c = 1; c < NC - 1; c++)
{
/* shorthand */
const uint8_t* ptr = &src[r + c];
/* this is the actual erosion */
IMAGE(EROSION)[r + c] =
*(ptr - NC - 1u) & *(ptr + NC) & *(ptr - NC + 1u) &
*(ptr - 1) & *ptr & *(ptr + 1) &
*(ptr + NC - 1) & *(ptr + NC) & *(ptr + NC + 1);
}
}
}
static void dilation(uint8_t* dst, const uint8_t* src)
{
uint32_t c, r;
/* loop through all rows, but skop 1st and last one */
for(r = NC; r < SZ - NC; r+= NC)/* we skip the first and last line */
{
/* loop through all columns, but skop 1st and last one */
for(c = 1; c < NC - 1; c++)
{
/* shorthand */
const uint8_t* ptr = &src[r+c];
/* this is the actual dilation */
IMAGE(DILATION)[r+c] =
*(ptr - NC - 1u) | *(ptr - NC) | *(ptr - NC + 1) |
*(ptr - 1) | *ptr | *(ptr + 1) |
*(ptr + NC - 1) | *(ptr + NC) | *(ptr + NC + 1);
}
}
}
static void thresh(uint8_t* dst, const uint8_t* src, uint8_t threshold)
{
uint32_t c, r;
/* loop through all rows, but skop 1st and last one */
for(r = 0; r < SZ; r+= NC)
{
/* loop through all columns, but skop 1st and last one */
for(c = 0; c < NC; c++)
{
/* shorthand */
const uint8_t tmp = src[r + c];
/* check the threshold */
if(threshold < tmp)
{
dst[r + c] = 0u;
}
else
{
dst[r + c] = 255u;
}
}
}
}
static void region_labeling(uint8_t* dst)
{
uint8_t tmp_buf[SZ];
/* input picture info */
struct OSC_PICTURE picin =
{
.data = IMAGE(DILATION),
.width = NC,
.height = OSC_CAM_MAX_IMAGE_HEIGHT / 2u,
.type = OSC_PICTURE_GREYSCALE
};
/* temporary binary image */
struct OSC_PICTURE picout =
{
.data = tmp_buf,
.width = NC,
.height = OSC_CAM_MAX_IMAGE_HEIGHT / 2u,
.type = OSC_PICTURE_BINARY
};
/* region labeling info */
struct OSC_VIS_REGIONS region_info;
/* make a binary image */
OscVisGrey2BW(&picin, &picout, 0x80, false);
/* now do the region labeling */
OscVisLabelBinary(&picout, ®ion_info);
/* feature extraction */
OscVisGetRegionProperties(®ion_info);
/* now copy the grayscale image to the labeling image */
memcpy(dst, IMAGE(GRAYSCALE), SZ);
/* abuse the picin picture info to draw the bounding boxes */
picin.data = dst;
draw_bbox(&picin, ®ion_info, 0x80);
/* set the number of objects in the web gui */
data.ipc.state.objectcount = region_info.noOfObjects;
}
static uint8_t otsu(const uint8_t* img)
{
uint8_t ret;
uint32_t histogram[256];
uint32_t k, g;
uint32_t w0, w1;
uint32_t mu0s, mu1s;
float mu0, mu1;
float sigma_b, sigma_max;
/* initialise the histogram with zero */
memset(histogram, 0, sizeof(histogram));
/* calculate the histogram */
imhist(histogram, img);
sigma_max = 0.0f;
for(k = 0; k < 256; k++)
{
w0 = w1 = 0;
mu0s = mu1s = 0;
for(g = 0; g < 256; g++)
{
if(g <= k)
{
w0 += histogram[g];
mu0s += histogram[g] * g;
}
else
{
w1 += histogram[g];
mu1s += histogram[g] * g;
}
}
mu0 = ((float)mu0s / (float)w0);
mu1 = ((float)mu1s / (float)w1);
sigma_b = ((float)(w0 * w1)) * (mu0 - mu1) * (mu0 - mu1);
if(sigma_b > sigma_max)
{
sigma_max = sigma_b;
ret = (uint8_t)k;
}
}
return ret;
}