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