rht_circle.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <cmath>
00027 #include <sys/time.h>
00028 #include "models/shape/rht_circle.h"
00029
00030 using namespace std;
00031 using namespace fawkes;
00032
00033 #define TEST_IF_IS_A_PIXEL(x) ((x)>230)
00034
00035 #define TBY_SQUARED_DIST(x1,y1,x2,y2) \
00036 (((x1)-(x2))*((x1)-(x2))+((y1)-(y2))*((y1)-(y2)))
00037 #define TBY_RADIUS_DIFF(x1, y1, x2, y2, r) \
00038 (sqrt(((x1)-(x2))*((x1)-(x2))+((y1)-(y2))*((y1)-(y2))-(r)*(r)))
00039
00040
00041 const float RhtCircleModel::RHT_MIN_RADIUS = 40.0;
00042 const float RhtCircleModel::RHT_MAX_RADIUS = 500.0;
00043
00044
00045
00046
00047
00048
00049 RhtCircleModel::RhtCircleModel(void)
00050 {
00051 }
00052
00053
00054
00055 RhtCircleModel::~RhtCircleModel(void)
00056 {
00057 m_Circles.clear();
00058 }
00059
00060
00061
00062
00063
00064
00065 int
00066 RhtCircleModel::parseImage( unsigned char* buf,
00067 ROI *roi )
00068 {
00069
00070 unsigned char *buffer = roi->get_roi_buffer_start(buf);
00071
00072 unsigned int x, y;
00073 vector<point_t> pixels;
00074 struct timeval start, end;
00075
00076
00077 accumulator.reset();
00078
00079
00080 m_Circles.clear();
00081
00082
00083 const int RHT_MAX_TIME = 10000;
00084 const int RHT_MAX_ITER = 1000;
00085
00086
00087 const float RHT_MIN_VOTE_RATE = 0.0f;
00088
00089
00090 const int RHT_XY_SCALE = 8;
00091 const int RHT_RADIUS_SCALE= 8;
00092
00093
00094
00095 const float RHT_FITTING_DIST_DIFF = 15.0f;
00096
00097
00098 const float ROI_HOLLOW_RATE = 0.70f;
00099
00100 const unsigned int roi_hollow_top = (int)(roi->height * ((1.0f - ROI_HOLLOW_RATE) / 2));
00101 const unsigned int roi_hollow_bottom = roi->height - roi_hollow_top;
00102 const unsigned int roi_hollow_left = (int)(roi->width * ((1.0f - ROI_HOLLOW_RATE) / 2));
00103 const unsigned int roi_hollow_right = roi->width - roi_hollow_left;
00104
00105
00106
00107
00108 unsigned char *line_start = buffer;
00109
00110 gettimeofday(&start, NULL);
00111 end.tv_usec = start.tv_usec;
00112
00113
00114 for (y = 0; y < roi_hollow_top; ++y) {
00115 for (x = 0; x < roi->width; ++x) {
00116 if (TEST_IF_IS_A_PIXEL(*buffer)) {
00117 point_t pt={x, y};
00118 pixels.push_back(pt);
00119 }
00120
00121 ++buffer;
00122 }
00123 line_start += roi->line_step;
00124 buffer = line_start;
00125 }
00126
00127 for (y = roi_hollow_top; y < roi_hollow_bottom; ++y) {
00128 for (x = 0; x < roi_hollow_left; ++x) {
00129 if (TEST_IF_IS_A_PIXEL(*buffer)) {
00130 point_t pt={x, y};
00131 pixels.push_back(pt);
00132 }
00133
00134 ++buffer;
00135 }
00136 buffer+=(roi_hollow_right - roi_hollow_left);
00137 for (x = roi_hollow_right; x < roi->width; ++x) {
00138 if (TEST_IF_IS_A_PIXEL(*buffer)) {
00139 point_t pt={x, y};
00140 pixels.push_back(pt);
00141 }
00142
00143 ++buffer;
00144 }
00145 line_start += roi->line_step;
00146 buffer = line_start;
00147 }
00148
00149 for (y = roi_hollow_bottom; y < roi->height; ++y) {
00150 for (x = 0; x < roi->width; ++x) {
00151 if (TEST_IF_IS_A_PIXEL(*buffer)) {
00152 point_t pt={x, y};
00153 pixels.push_back(pt);
00154 }
00155
00156 ++buffer;
00157 }
00158 line_start += roi->line_step;
00159 buffer = line_start;
00160 }
00161
00162
00163 point_t p[3];
00164 center_in_roi_t center;
00165 float radius;
00166 vector< point_t >::iterator pos;
00167 int num_iter = 0;
00168 int num_points = (int) pixels.size();
00169 if (num_points == 0) {
00170
00171 return 0;
00172 }
00173
00174 while( (num_iter++ < RHT_MAX_ITER) &&
00175 ( ((end.tv_usec - start.tv_usec) < RHT_MAX_TIME) ||
00176 ((end.tv_usec + 1000000 - start.tv_usec) < RHT_MAX_TIME) )
00177
00178 ) {
00179
00180
00181 for (int i=0; i < 3; ++i) {
00182 int ri = rand() % num_points;
00183 pos = pixels.begin() + ri;
00184 p[i] = *pos;
00185 }
00186
00187
00188
00189 calcCircle(p[0], p[1], p[2], center, radius);
00190
00191
00192 if (radius > RHT_MIN_RADIUS && radius < RHT_MAX_RADIUS) {
00193 accumulator.accumulate((int)(center.x / RHT_XY_SCALE),
00194 (int)(center.y / RHT_XY_SCALE),
00195 (int)(radius / RHT_RADIUS_SCALE));
00196 }
00197
00198 gettimeofday(&end, NULL);
00199 }
00200
00201
00202 int max, x_max, y_max, r_max;
00203 max = accumulator.getMax(x_max, y_max, r_max);
00204
00205 cout << "Max vote is with " << max << " of the " << num_iter << " ones." << endl;
00206
00207
00208 if (max > num_iter * RHT_MIN_VOTE_RATE)
00209 {
00210 center_in_roi_t center;
00211 center.x = (float)(x_max * RHT_XY_SCALE + RHT_XY_SCALE/2);
00212 center.y = (float)(y_max * RHT_XY_SCALE + RHT_XY_SCALE/2);
00213 float c_r = (float)(r_max * RHT_RADIUS_SCALE + RHT_RADIUS_SCALE/2);
00214
00215
00216 for(vector< point_t >::iterator pos = pixels.begin(); pos != pixels.end(); )
00217 {
00218 if (TBY_RADIUS_DIFF(pos->x, pos->y, center.x, center.y, c_r)
00219 > RHT_FITTING_DIST_DIFF)
00220 {
00221 pixels.erase(pos);
00222 }
00223 else
00224 {
00225 pos++;
00226 }
00227 }
00228
00229 Circle c;
00230 c.fitCircle(pixels);
00231 c.count = max;
00232 m_Circles.push_back(c);
00233
00234
00235
00236
00237
00238
00239 return 0;
00240 }
00241
00242
00243
00244
00245 return 1;
00246 }
00247
00248
00249 int
00250 RhtCircleModel::getShapeCount(void) const
00251 {
00252 return m_Circles.size();
00253 }
00254
00255 Circle *
00256 RhtCircleModel::getShape(int id) const
00257 {
00258 if (id < 0 || (unsigned int)id >= m_Circles.size()) {
00259 return NULL;
00260 } else {
00261 return const_cast<Circle*>(&m_Circles[id]);
00262 }
00263 }
00264
00265
00266 Circle *
00267 RhtCircleModel::getMostLikelyShape(void) const
00268 {
00269 if (m_Circles.size() == 0) {
00270 return NULL;
00271 } else if (m_Circles.size() == 1) {
00272 return const_cast<Circle*>(&m_Circles[0]);
00273 } else {
00274 int cur=0;
00275 for (unsigned int i=1; i < m_Circles.size(); ++i) {
00276 if (m_Circles[i].count > m_Circles[cur].count) {
00277 cur = i;
00278 }
00279 }
00280 return const_cast<Circle*>(&m_Circles[cur]);
00281 }
00282 }
00283
00284
00285 void
00286 RhtCircleModel::calcCircle(
00287 const point_t& p1,
00288 const point_t& p2,
00289 const point_t& p3,
00290 center_in_roi_t& center,
00291 float& radius)
00292
00293
00294
00295 {
00296 const int &x1=p1.x, &y1=p1.y, &x2=p2.x, &y2=p2.y, &x3=p3.x, &y3=p3.y;
00297 float dx, dy;
00298 int div = 2*((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1));
00299
00300 if (div == 0)
00301 {
00302
00303 radius = -1.0;
00304 return;
00305 }
00306 center.x = ((float)((x2*x2+y2*y2-x1*x1-y1*y1)*(y3-y1)
00307 -(x3*x3+y3*y3-x1*x1-y1*y1)*(y2-y1))
00308 /div);
00309 center.y = ((float)((x2-x1)*(x3*x3+y3*y3-x1*x1-y1*y1)
00310 -(x3-x1)*(x2*x2+y2*y2-x1*x1-y1*y1))
00311 /div);
00312 dx = center.x - x1;
00313 dy = center.y - y1;
00314 radius = (float)sqrt(dx*dx+dy*dy);
00315 }
00316
00317