bazar  1.3.1
calibmodel.cpp
Go to the documentation of this file.
1 #include "calibmodel.h"
2 
3 CalibModel::CalibModel(const char *modelfile)
4  : modelfile (modelfile)
5 {
6  image=0;
7  win = "BazAR";
8 }
9 
11  if (image) cvReleaseImage(&image);
12 }
13 
15 
16 void CalibModel::onMouse(int event, int x, int y, int flags)
17 {
18  if (event == CV_EVENT_LBUTTONDOWN) {
19  // try to grab something
20  grab = -1;
21  for (int i=0; i<4; i++) {
22  int dx = x-corners[i].x;
23  int dy = y-corners[i].y;
24  if (sqrt((double)(dx*dx+dy*dy)) <10) {
25  grab = i;
26  break;
27  }
28  }
29  }
30 
31  if (grab!=-1) {
32  corners[grab].x = x;
33  corners[grab].y = y;
34  }
35 
36  if (event == CV_EVENT_LBUTTONUP) {
37  grab=-1;
38  }
39 }
40 
41 bool CalibModel::buildCached(int nbcam, CvCapture *capture, bool cache, planar_object_recognizer &detector)
42 {
43 
44  detector.ransac_dist_threshold = 5;
45  detector.max_ransac_iterations = 800;
46  detector.non_linear_refine_threshold = 1.5;
47 
48  // A lower threshold will allow detection in harder conditions, but
49  // might lead to false positives.
50  detector.match_score_threshold=.03f;
51 
52  detector.min_view_rate=.1;
53  detector.views_number = 100;
54 
55  // Should we train or load the classifier ?
56  if(cache && detector.build_with_cache(
57  string(modelfile), // mode image file name
58  500, // maximum number of keypoints on the model
59  32, // patch size in pixels
60  3, // yape radius. Use 3,5 or 7.
61  16, // number of trees for the classifier. Somewhere between 12-50
62  3 // number of levels in the gaussian pyramid
63  ))
64  {
65  // loading worked. Remember the region of interest.
66  corners[0].x = detector.new_images_generator.u_corner1;
67  corners[0].y = detector.new_images_generator.v_corner1;
68  corners[1].x = detector.new_images_generator.u_corner2;
69  corners[1].y = detector.new_images_generator.v_corner2;
70  corners[2].x = detector.new_images_generator.u_corner3;
71  corners[2].y = detector.new_images_generator.v_corner3;
72  corners[3].x = detector.new_images_generator.u_corner4;
73  corners[3].y = detector.new_images_generator.v_corner4;
74  image = cvLoadImage(modelfile, cvQueryFrame(capture)->nChannels == 3);
75  } else {
76  // ask the user the take a shot of the model
77  if (!interactiveSetup(capture)) return false;
78 
79  // train the classifier to detect this model
80  if (!detector.build(image, 400, 32, 3, 16, 3,0, 0))
81  return false;
82 
83  // save the image
84  if (!cvSaveImage(modelfile, image)) return false;
85 
86  // and the region of interest (ROI)
87  string roifn = string(modelfile) + ".roi";
88  ofstream roif(roifn.c_str());
89  if (!roif.good()) return false;
90  for (int i=0;i<4; i++)
91  roif << corners[i].x << " " << corners[i].y << "\n";
92  roif.close();
93 
94  // and the trained classifier
95  detector.save(string(modelfile)+".classifier");
96  }
97 
98  float cn[4][2];
99  for (int i=0; i<4; i++) {
100  cn[i][0] = corners[i].x;
101  cn[i][1] = corners[i].y;
102  }
103 
104  // prepare the light calibration reference
105  return map.init(nbcam, image, cn, 8, 6);
106 }
107 
108 static void putText(IplImage *im, const char *text, CvPoint p, CvFont *f1, CvFont *f2)
109 {
110  cvPutText(im,text,p,f2, cvScalarAll(0));
111  cvPutText(im,text,p,f1, cvScalar(0,255, 255));
112 }
113 
114 
115 IplImage *myRetrieveFrame(CvCapture *capture)
116 {
117  static IplImage *s=0;
118  IplImage *frame =cvRetrieveFrame(capture);
119  if (frame == 0) return 0;
120  IplImage *ret=frame;
121  if (frame->nChannels==1) {
122  if (!s) s=cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
123  cvCvtColor(frame,s,CV_GRAY2BGR);
124  ret = s;
125  }
126  if (ret->origin) {
127  if (!s) s=cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3);
128  cvFlip(ret, s);
129  ret->origin=0;
130  ret = s;
131  }
132  return ret;
133 }
134 IplImage *myQueryFrame(CvCapture *capture)
135 {
136  cvGrabFrame(capture);
137  return myRetrieveFrame(capture);
138 }
139 
140 
141 
142 bool CalibModel::interactiveSetup(CvCapture *capture)
143 {
144 
145  CvFont font, fontbold;
146 
147  cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 1, 1);
148  cvInitFont( &fontbold, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 5);
149 
150  cvNamedWindow(win, CV_WINDOW_AUTOSIZE);
151  grab=-1;
152 
153  objectPtr = this;
154  cvSetMouseCallback(win, onMouseStatic, this);
155 
156  bool pause=false;
157  IplImage *frame = myQueryFrame(capture);
158  IplImage *shot=0, *text=0;
159 
160  state = TAKE_SHOT;
161 
162  bool accepted =false;
163  while (!accepted) {
164 
165  // wait for a key
166  char k = cvWaitKey(10);
167 
168  if (k==27 || k=='q') {
169  if (shot) cvReleaseImage(&shot);
170  if (text) cvReleaseImage(&text);
171  return false;
172  }
173 
174  // clear text or grab the image to display
175  if (!pause || shot==0) {
176  frame = myQueryFrame(capture);
177  if (!text) {
178  text=cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
179  int d = 30;
180  corners[0].x = d;
181  corners[0].y = d;
182  corners[1].x = frame->width-d;
183  corners[1].y = d;
184  corners[2].x = frame->width-d;
185  corners[2].y = frame->height-d;
186  corners[3].x = d;
187  corners[3].y = frame->height-d;
188  }
189  if (frame->nChannels==1)
190  cvCvtColor(frame, text, CV_GRAY2BGR);
191  else
192  cvCopy(frame,text);
193  } else {
194  if (shot->nChannels==1)
195  cvCvtColor(shot, text, CV_GRAY2BGR);
196  else
197  cvCopy(shot, text);
198  }
199 
200  // display text / react to keyboard
201  switch (state) {
202  default:
203  case TAKE_SHOT:
204  if (k==' ') {
205  if (shot) cvCopy(frame,shot);
206  else shot = cvCloneImage(frame);
207  pause = true;
208  state = CORNERS;
209  k=-1;
210  } else {
211  putText(text,"Please take a frontal view", cvPoint(3,20), &font, &fontbold);
212  putText(text,"of a textured planar surface", cvPoint(3,40), &font, &fontbold);
213  putText(text,"and press space", cvPoint(3,60), &font, &fontbold);
214  break;
215  }
216  case CORNERS:
217  putText(text, "Drag corners to match the", cvPoint(3,20), &font, &fontbold);
218  putText(text, "calibration target", cvPoint(3,40), &font, &fontbold);
219  putText(text, "press 'r' to restart", cvPoint(3,60), &font, &fontbold);
220  putText(text, "press space when ready", cvPoint(3,80), &font, &fontbold);
221  if (k=='r') {
222  pause = false;
223  state = TAKE_SHOT;
224  }
225  if (k==' ') {
226  accepted=true;
227  }
228  int four = 4;
229  CvPoint *ptr = corners;
230  cvPolyLine(text, &ptr, &four, 1, 1,
231  cvScalar(0,255,0));
232  break;
233  }
234  cvShowImage(win, text);
235  }
236 
237  cvReleaseImage(&text);
238  image = shot;
239  return true;
240 }
241 
242 void CalibModel::onMouseStatic(int event, int x, int y, int flags, void* param)
243 {
244  if (param)
245  ((CalibModel *)param)->onMouse(event,x,y,flags);
246  if (objectPtr)
247  objectPtr->onMouse(event,x,y,flags);
248  else
249  cerr << "onMouseStatic(): null-pointer.\n";
250 }
251 
252