bazar  1.3.1
lightcollector.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <math.h>
3 #include "lightcollector.h"
4 #include <geometry/homography.h>
5 
7  vertices=0;
8  transformed=0;
9  triangles=0;
10  nbTri=0;
11  avg=0;
12  nx=ny=0;
13  avgChannels=0;
14  worldRT=0;
15 }
16 
18 {
19  if (lc.vertices) vertices = cvCloneMat(lc.vertices);
20  else vertices=0;
21  if (lc.transformed) transformed = cvCloneMat(lc.transformed);
22  else transformed=0;
23  nbTri = lc.nbTri;
24  nx = lc.nx;
25  ny = lc.ny;
26  if (lc.triangles) {
27  triangles = new int[nbTri*3];
28  memcpy(triangles, lc.triangles, sizeof(int)*nbTri*3);
29  } else triangles=0;
31  avg=0;
32  if (lc.worldRT) cvIncRefData(lc.worldRT);
33  worldRT = lc.worldRT;
34  //assert(lc.avg==0);
35 }
36 
38 {
39  vertices=0;
40  transformed=0;
41  triangles=0;
42  nbTri = lc.nbTri;
43  nx = lc.nx;
44  ny = lc.ny;
46  avg = lc.avg;
47  lc.avg=0;
48  if (lc.worldRT) cvIncRefData(lc.worldRT);
49  if (worldRT) cvDecRefData(worldRT);
50  worldRT = lc.worldRT;
51  return *this;
52 }
53 
55 {
56  if (lc.vertices) vertices = cvCloneMat(lc.vertices);
57  else vertices=0;
58  if (lc.transformed) transformed = cvCloneMat(lc.transformed);
59  else transformed=0;
60  nbTri = lc.nbTri;
61  nx = lc.nx;
62  ny = lc.ny;
64  if (lc.triangles) {
65  triangles = new int[nbTri*3];
66  memcpy(triangles, lc.triangles, sizeof(int)*nbTri*3);
67  } else
68  triangles=0;
69  if (lc.avg) {
70  avg = new float[avgChannels*nbTri];
71  memcpy(avg, lc.avg, sizeof(float)*avgChannels*nbTri);
72  } else
73  avg=0;
74  if (lc.worldRT) worldRT=cvCloneMat(lc.worldRT);
75  else worldRT = 0;
76 }
77 
79  if (avg) delete[] avg;
80  if (vertices) cvReleaseMat(&vertices);
81  if (transformed) cvReleaseMat(&transformed);
82  if (worldRT) cvDecRefData(&worldRT);
83 }
84 
85 // from tri.cpp
86 int stat_triangle(IplImage *im, int pts[3][2], float avg[3]);
87 
91 void LightCollector::averageImage(IplImage *im, CvMat *_homography)
92 {
93  if (avgChannels != im->nChannels) {
94  if (avgChannels < im->nChannels) {
95  delete[] avg;
96  avg = 0;
97  }
98  avgChannels = im->nChannels;
99  }
100  if (!avg) avg = new float[avgChannels*nbTri];
101 
102  // apply the homography to every mesh vertex
103  if (_homography)
104  cvMatMul(_homography, vertices, transformed);
105  else
106  cvCopy(vertices, transformed);
107  CvMat r1,r2,r3;
108  cvGetRow(transformed, &r1, 0);
109  cvGetRow(transformed, &r2, 1);
110  cvGetRow(transformed, &r3, 2);
111  cvDiv(&r1,&r3,&r1);
112  cvDiv(&r2,&r3,&r2);
113 
114  nbPix=0;
115  for (int t=0; t<nbTri;t++) {
116  int pts[3][2];
117  for (int i=0; i<3; i++) {
118  assert(triangles[t*3+i] < transformed->cols);
119  pts[i][0] = cvRound(CV_MAT_ELEM(*transformed, float, 0, triangles[t*3+i]));
120  pts[i][1] = cvRound(CV_MAT_ELEM(*transformed, float, 1, triangles[t*3+i]));
121  }
122  nbPix+=stat_triangle(im, pts, avg+t*avgChannels);
123  }
124 }
125 
126 bool LightCollector::genGrid(float corners[4][2], int nx, int ny)
127 {
128  if (nx<1 || ny<1) return false;
129  if (avg) delete[] avg; avg=0;
130  if (vertices) cvReleaseMat(&vertices);
131  if (transformed) cvReleaseMat(&transformed);
132 
133  // generate vertices
134  vertices = cvCreateMat(3, (nx+1)*(ny+1), CV_32FC1);
135  transformed = cvCreateMat(3, vertices->cols, CV_32FC1);
136  for (int y=0; y<(ny+1); ++y)
137  for (int x=0; x<(nx+1); ++x) {
138  CV_MAT_ELEM(*vertices, float, 0, y*(nx+1)+x) = float(x)/float(nx);
139  CV_MAT_ELEM(*vertices, float, 1, y*(nx+1)+x) = float(y)/float(ny);
140  CV_MAT_ELEM(*vertices, float, 2, y*(nx+1)+x) = 1;
141  }
142 
143  // generate triangles
144  nbTri = nx*ny*2;
145  triangles = new int[nbTri*3];
146  int *tri = triangles;
147  for (int y=0; y<ny; ++y)
148  for (int x=0; x<nx; ++x) {
149  tri[0] = y*(nx+1)+x;
150  tri[1] = y*(nx+1)+x+1;
151  tri[2] = (y+1)*(nx+1)+x;
152  tri+=3;
153  tri[0] = y*(nx+1)+x+1;
154  tri[1] = (y+1)*(nx+1)+x+1;
155  tri[2] = (y+1)*(nx+1)+x;
156  tri+=3;
157  }
158 
159  homography H;
160  if (!H.estimate(0, 0, corners[0][0], corners[0][1],
161  1, 0, corners[1][0], corners[1][1],
162  1, 1, corners[2][0], corners[2][1],
163  0, 1, corners[3][0], corners[3][1]))
164  return false;
165 
166  cvMatMul(&H, vertices, transformed);
167  CvMat r1,r2,r3, d1, d2;
168  cvGetRow(transformed, &r1, 0);
169  cvGetRow(transformed, &r2, 1);
170  cvGetRow(transformed, &r3, 2);
171  cvGetRow(vertices, &d1, 0);
172  cvGetRow(vertices, &d2, 1);
173  cvDiv(&r1,&r3,&d1);
174  cvDiv(&r2,&r3,&d2);
175  return true;
176 }
177 
178 void LightCollector::drawGrid(IplImage *im, CvMat *_homography)
179 {
180  // apply the homography to every mesh vertex
181  cvMatMul(_homography, vertices, transformed);
182  CvMat r1,r2,r3;
183  cvGetRow(transformed, &r1, 0);
184  cvGetRow(transformed, &r2, 1);
185  cvGetRow(transformed, &r3, 2);
186  cvDiv(&r1,&r3,&r1);
187  cvDiv(&r2,&r3,&r2);
188 
189  for (int t=0; t<nbTri;t++) {
190  int pts[3][2];
191  for (int i=0; i<3; i++) {
192  pts[i][0] = cvRound(CV_MAT_ELEM(*transformed, float, 0, triangles[t*3+i]));
193  pts[i][1] = cvRound(CV_MAT_ELEM(*transformed, float, 1, triangles[t*3+i]));
194  }
195  cvLine(im, cvPoint(pts[0][0], pts[0][1]), cvPoint(pts[1][0], pts[1][1]), cvScalarAll(255), 1,4,0);
196  cvLine(im, cvPoint(pts[1][0], pts[1][1]), cvPoint(pts[2][0], pts[2][1]), cvScalarAll(255), 1,4,0);
197  cvLine(im, cvPoint(pts[2][0], pts[2][1]), cvPoint(pts[0][0], pts[0][1]), cvScalarAll(255), 1,4,0);
198  }
199 }
200 
201 void LightCollector::drawAvg(IplImage *im)
202 {
203  for (int t=0; t<nbTri;t++) {
204  CvPoint pts[3];
205  for (int i=0; i<3; i++) {
206  pts[i].x = cvRound(CV_MAT_ELEM(*transformed, float, 0, triangles[t*3+i]));
207  pts[i].y = cvRound(CV_MAT_ELEM(*transformed, float, 1, triangles[t*3+i]));
208  }
209  CvScalar col;
210  if (avgChannels >1) {
211  float *c = avg + avgChannels*t;
212  col = CV_RGB(c[0], c[1], c[2]);
213  } else {
214  col = cvScalarAll(avg[t]);
215  }
216  cvFillConvexPoly(im, pts, 3, col);
217  }
218 }
219 
220 struct Hdr {
222 };
224 {
225  return sizeof(Hdr)+nbTri*avgChannels*sizeof(float);
226 }
227 
228 void LightCollector::serialize(char *buffer)
229 {
230  Hdr *hdr = (Hdr *) buffer;
231  hdr->nx = nx;
232  hdr->ny = ny;
233  hdr->nbTri = nbTri;
234  hdr->avgChannels = avgChannels;
235  hdr->nbPix = nbPix;
236  assert(nbTri!=0 && avgChannels!=0);
237  memcpy(buffer + sizeof(Hdr), avg, nbTri*avgChannels*sizeof(float));
238 }
239 
240 void LightCollector::load(const char *buffer, int size)
241 {
242  const Hdr *hdr = (const Hdr *) buffer;
243  //assert(nx == hdr->nx);
244  //assert(ny == hdr->ny);
245  nx = hdr->nx;
246  ny = hdr->ny;
247  nbTri = hdr->nbTri;
248  if (avg && avgChannels < hdr->avgChannels) {
249  delete[] avg;
250  avg=0;
251  }
252  avgChannels = hdr->avgChannels;
253  if (!avg) avg = new float[avgChannels*nbTri];
254  if (size != serializeSize()) {
255  printf("problem!\n");
256  }
257  assert(size == serializeSize());
258  memcpy(avg, buffer + sizeof(Hdr), nbTri*avgChannels*sizeof(float));
259 }
260 
262 {
263  if (avg) {
264  delete[] avg;
265  avg = 0;
266  }
267 }
268 
269 bool LightCollector::cmpWithRef(const LightCollector &ref, float *val, const float *_scale, const float *_shift)
270 {
271  if (avg==0) return false;
272  assert(avgChannels==ref.avgChannels);
273 
274  const float ones[3] = {1,1,1};
275  const float zeroes[3] = {0,0,0};
276  const float *scale = (_scale ? _scale : ones);
277  const float *shift = (_shift ? _shift : zeroes);
278  vector<float> values[3];
279 
280  values[0].reserve(nbTri);
281  values[1].reserve(nbTri);
282  values[2].reserve(nbTri);
283 
284  for (int i=0; i<nbTri; i++) {
285  for (int c=0; c<avgChannels; c++) {
286  float v = avg[i*avgChannels+c];
287  float rv = ref.avg[i*avgChannels+c];
288  if (v>= 5 && v<=250 && rv >= 5 && rv <= 250) {
289  values[c].push_back((scale[c]*v+shift[c])/rv);
290  }
291  }
292  }
293  for (int i=0; i<avgChannels; i++) {
294  if (values[i].size()>0) {
295  val[i] = values[i][values[i].size()/2];
296  } else {
297  return false;
298  }
299  }
300  return true;
301 }
302