25 #include <fvmodels/shape/rcd_circle.h>
34 namespace firevision {
38 # define TEST_IF_IS_A_PIXEL(x) ((x) > 230)
40 # define TEST_IF_IS_A_PIXEL(x) ((x) == 0)
43 #define TBY_SQUARED_DIST(x1, y1, x2, y2) \
44 (((x1) - (x2)) * ((x1) - (x2)) + ((y1) - (y2)) * ((y1) - (y2)))
45 #define TBY_RADIUS_DIFF(x1, y1, x2, y2, r) \
46 (((x1) - (x2)) * ((x1) - (x2)) + ((y1) - (y2)) * ((y1) - (y2)) - (r) * (r))
63 RcdCircleModel::RcdCircleModel(
unsigned int max_failures,
64 unsigned int min_pixels,
65 unsigned int min_interpix_dist,
66 unsigned int max_dist_p4,
67 unsigned int max_dist_a,
72 RCD_MAX_FAILURES = max_failures;
73 RCD_MIN_PIXELS = min_pixels;
74 RCD_MIN_INTERPIX_DIST = min_interpix_dist;
75 RCD_MAX_DIST_P4 = max_dist_p4;
76 RCD_MAX_DIST_A = max_dist_a;
77 RCD_HW_RATIO = hw_ratio;
78 RCD_MAX_TIME = max_time;
79 RCD_ROI_HOLLOW_RATE = hollow_rate;
83 RcdCircleModel::~RcdCircleModel(
void)
89 RcdCircleModel::parseImage(
unsigned char *buf,
ROI *roi)
92 unsigned char *line_start = buffer;
95 vector<upoint_t> pixels, remove_list;
99 struct timeval start, now;
104 const unsigned int roi_hollow_top = (int)(roi->
height * ((1.0f - RCD_ROI_HOLLOW_RATE) / 2));
105 const unsigned int roi_hollow_bottom = roi->
height - roi_hollow_top;
106 const unsigned int roi_hollow_left = (int)(roi->
width * ((1.0f - RCD_ROI_HOLLOW_RATE) / 2));
107 const unsigned int roi_hollow_right = roi->
width - roi_hollow_left;
117 unsigned int boundary_right = 0;
118 unsigned int boundary_bottom = 0;
120 gettimeofday(&start, NULL);
125 for (y = 0; y < roi_hollow_top; ++y) {
126 for (x = 0; x < roi->
width; ++x) {
127 if (TEST_IF_IS_A_PIXEL(*buffer)) {
129 pixels.push_back(pt);
130 if (x > boundary_right)
141 for (y = roi_hollow_top; y < roi_hollow_bottom; ++y) {
142 for (x = 0; x < roi_hollow_left; ++x) {
143 if (TEST_IF_IS_A_PIXEL(*buffer)) {
145 pixels.push_back(pt);
146 if (x > boundary_right)
153 buffer += (roi_hollow_right - roi_hollow_left);
154 for (x = roi_hollow_right; x < roi->
width; ++x) {
155 if (TEST_IF_IS_A_PIXEL(*buffer)) {
157 pixels.push_back(pt);
158 if (x > boundary_right)
169 for (y = roi_hollow_bottom; y < roi->
height; ++y) {
170 for (x = 0; x < roi->
width; ++x) {
171 if (TEST_IF_IS_A_PIXEL(*buffer)) {
173 pixels.push_back(pt);
186 vector<upoint_t>::iterator pos;
188 if (pixels.size() < RCD_MIN_PIXELS) {
194 for (
int i = 0; i < 4; ++i) {
195 int ri = rand() % ((int)pixels.size());
196 pos = pixels.begin() + ri;
199 remove_list.push_back(p[i]);
202 if (TBY_SQUARED_DIST(p[1].x, p[1].y, p[2].x, p[2].y) < RCD_MIN_INTERPIX_DIST
203 || TBY_SQUARED_DIST(p[2].x, p[2].y, p[0].x, p[0].y) < RCD_MIN_INTERPIX_DIST
204 || TBY_SQUARED_DIST(p[0].x, p[0].y, p[1].x, p[1].y) < RCD_MIN_INTERPIX_DIST) {
210 pixels.push_back(p[0]);
211 pixels.push_back(p[1]);
212 pixels.push_back(p[2]);
213 pixels.push_back(p[3]);
217 gettimeofday(&now, NULL);
223 calcCircle(p[0], p[1], p[2], center, radius);
226 int r = (int)sqrt(TBY_SQUARED_DIST(center.
x, center.
y, pixels[3].x, pixels[3].y));
227 int dist = (int)(r - radius);
228 dist = (dist >= 0) ? dist : -dist;
229 if (radius <= 0 || (
unsigned int)dist > RCD_MAX_DIST_P4) {
233 pixels.push_back(p[0]);
234 pixels.push_back(p[1]);
235 pixels.push_back(p[2]);
236 pixels.push_back(p[3]);
240 gettimeofday(&now, NULL);
246 for (
unsigned int i = 0; i < pixels.size(); ++i) {
247 int r = (int)sqrt(TBY_SQUARED_DIST(center.
x, center.
y, pixels[i].x, pixels[i].y));
248 int dist = (int)(r - radius);
249 dist = (dist >= 0) ? dist : -dist;
250 if ((
unsigned int)dist <= RCD_MAX_DIST_A) {
251 pos = pixels.begin() + i;
254 remove_list.push_back(pixels[i]);
262 > (boundary_right > boundary_bottom ? boundary_right : boundary_bottom) * RCD_HW_RATIO) {
264 if (radius > TBY_CIRCLE_RADIUS_MIN && radius < TBY_CIRCLE_RADIUS_MAX) {
273 m_Circles.push_back(c);
281 while (!remove_list.empty()) {
282 pixels.push_back(remove_list.back());
283 remove_list.pop_back();
285 gettimeofday(&now, NULL);
289 gettimeofday(&now, NULL);
291 diff_sec = now.tv_sec - start.tv_sec;
292 diff_usec = now.tv_usec - start.tv_usec;
295 diff_usec += 1000000;
298 f_diff_sec = diff_sec + diff_usec / 1000000.f;
300 }
while ((f < RCD_MAX_FAILURES) && (pixels.size() > RCD_MIN_PIXELS)
301 && (f_diff_sec < RCD_MAX_TIME));
307 RcdCircleModel::getShapeCount(
void)
const
309 return m_Circles.size();
313 RcdCircleModel::getShape(
int id)
const
315 if (
id < 0 || (
unsigned int)
id >= m_Circles.size()) {
318 return const_cast<Circle *
>(&m_Circles[id]);
323 RcdCircleModel::getMostLikelyShape(
void)
const
326 switch (m_Circles.size()) {
328 case 1:
return const_cast<Circle *
>(&m_Circles[0]);
330 for (
unsigned int i = 1; i < m_Circles.size(); ++i)
331 if (m_Circles[i].radius > m_Circles[cur].radius)
333 return const_cast<Circle *
>(&m_Circles[cur]);
338 RcdCircleModel::calcCircle(
const upoint_t & p1,
347 const int &x1 = p1.
x, &y1 = p1.
y, &x2 = p2.
x, &y2 = p2.
y, &x3 = p3.
x, &y3 = p3.
y;
349 int div = 2 * ((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1));
356 center.
x = ((float)((x2 * x2 + y2 * y2 - x1 * x1 - y1 * y1) * (y3 - y1)
357 - (x3 * x3 + y3 * y3 - x1 * x1 - y1 * y1) * (y2 - y1))
359 center.
y = ((float)((x2 - x1) * (x3 * x3 + y3 * y3 - x1 * x1 - y1 * y1)
360 - (x3 - x1) * (x2 * x2 + y2 * y2 - x1 * x1 - y1 * y1))
364 radius = (float)sqrt(dx * dx + dy * dy);
void fitCircle(std::vector< fawkes::upoint_t > &points)
Fit circle.
int count
Number of pixels.
unsigned int height
ROI height.
unsigned char * get_roi_buffer_start(unsigned char *buffer) const
Get ROI buffer start.
unsigned int line_step
line step
unsigned int width
ROI width.
Fawkes library namespace.
Point with cartesian coordinates as unsigned integers.
unsigned int x
x coordinate
unsigned int y
y coordinate