bazar  1.3.1
mcv.cpp
Go to the documentation of this file.
1 /*
2 Copyright 2005, 2006 Computer Vision Lab,
3 Ecole Polytechnique Federale de Lausanne (EPFL), Switzerland.
4 All rights reserved.
5 
6 This file is part of BazAR.
7 
8 BazAR is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12 
13 BazAR is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 BazAR; if not, write to the Free Software Foundation, Inc., 51 Franklin
19 Street, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21 #include <iostream>
22 #include <math.h>
23 
24 #include <cv.h>
25 #include <highgui.h>
26 
27 #include "mcv.h"
28 
29 using namespace std;
30 
32 
33 CvSize mcvSize(IplImage * image)
34 {
35  return cvSize(image->width, image->height);
36 }
37 
39 
40 void mcvSmooth(IplImage * image, IplImage * smoothed_image, int smooth_type, int aperture)
41 {
42  if (smooth_type != CV_GAUSSIAN)
43  {
44  cerr << "mcvSmooth: only for CV_GAUSSIAN" << endl;
45  return;
46  }
47 
48  IplImage * image_to_smooth = image;
49  while(aperture > 0)
50  {
51  if (aperture >= 7)
52  {
53  cvSmooth(image_to_smooth, smoothed_image, CV_GAUSSIAN, 7);
54  image_to_smooth = smoothed_image;
55  aperture -= 7;
56  }
57  else if (aperture >= 5)
58  {
59  cvSmooth(image_to_smooth, smoothed_image, CV_GAUSSIAN, 5);
60  image_to_smooth = smoothed_image;
61  aperture -= 5;
62  }
63  else // if (aperture >= 3)
64  {
65  cvSmooth(image_to_smooth, smoothed_image, CV_GAUSSIAN, 3);
66  image_to_smooth = smoothed_image;
67  aperture -= 3;
68  }
69  }
70 }
71 
72 float mcvGaussianDerivative(IplImage * image, int x, int y, int order_x, int order_y, float sigma)
73 {
74  int half_size = int(3 * sqrt(2.) * sigma + 0.5);
75 
76  float result = 0;
77 
78  for(int i = -half_size; i <= +half_size; i++)
79  for(int j = -half_size; j <= +half_size; j++)
80  {
81  float c = 0.;
82  float e = exp(-(i*i+j*j) / (2 * sigma * sigma));
83 
84  if (order_x == 2 && order_y == 0)
85  c = (i * i / (sigma * sigma * sigma * sigma) - 1 / (sigma * sigma)) * e;
86  else if (order_x == 0 && order_y == 2)
87  c = (j * j / (sigma * sigma * sigma * sigma) - 1 / (sigma * sigma)) * e;
88  else if (order_x == 1 && order_y == 1)
89  c = i * j / (sigma * sigma * sigma * sigma) * e;
90  else
91  {
92  c = -1;
93  cerr << "error when calling mcvGaussianDerivative" << endl;
94  }
95 
96  int nx = x + i, ny = y + j;
97  if (nx < 0 || nx >= image->width || ny < 0 || ny >= image->height)
98  result += c * 128;
99  else
100  {
101  if (image->depth == int(IPL_DEPTH_8U))
102  result += c * mcvGet2D(image, nx, ny, unsigned char);
103  else if (image->depth == int(IPL_DEPTH_16S))
104  result += c * mcvGet2D(image, nx, ny, short);
105  else if (image->depth == int(IPL_DEPTH_32F))
106  result += c * mcvGet2D(image, nx, ny, float);
107  else
108  cerr << "mcvGaussianDerivative: wrong image format." << endl;
109  }
110  }
111 
112  return result;
113 }
114 
115 IplImage * mcvGradientNorm2(IplImage * image, int aperture)
116 {
117  IplImage * image_32f = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_32F, 1);
118  cvCvtScale(image, image_32f);
119 
120  IplImage * image_32f_x = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_32F, 1);
121  IplImage * image_32f_y = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_32F, 1);
122 
123  cvSobel(image_32f, image_32f_x, 1, 0, aperture);
124  cvSobel(image_32f, image_32f_y, 1, 0, aperture);
125 
126  IplImage * result_32f = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_32F, 1);
127  cvMul(image_32f_x, image_32f_x, image_32f_x);
128  cvMul(image_32f_y, image_32f_y, image_32f_y);
129  cvAdd(image_32f_x, image_32f_y, result_32f);
130 
131  IplImage * result = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);
132 
133  mcvScaleTo0_255(result_32f, result);
134 
135  cvReleaseImage(&image_32f);
136  cvReleaseImage(&image_32f_x);
137  cvReleaseImage(&image_32f_y);
138  cvReleaseImage(&result_32f);
139 
140  return result;
141 }
142 
143 void mcvSetBorder(IplImage * image, int border, int value)
144 {
145  if (image->depth == int(IPL_DEPTH_16S))
146  {
147  for(int y = 0; y < image->height; y++)
148  for(int x = 0; x < image->width; x++)
149  if (x < border || y < border || x >= image->width - border || y >= image->height - border)
150  mcvGet2D(image, x, y, short) = short(value);
151  }
152  else if (image->depth == int(IPL_DEPTH_32F))
153  {
154  for(int y = 0; y < image->height; y++)
155  for(int x = 0; x < image->width; x++)
156  if (x < border || y < border || x >= image->width - border || y >= image->height - border)
157  mcvGet2D(image, x, y, float) = float(value);
158  }
159  else
160  cerr << "mcvSetBorder: wrong image format." << endl;
161 }
162 
163 void mcvSetBorder(IplImage * image, int border_size)
164 {
165  if (image->depth != IPL_DEPTH_32F)
166  {
167  cerr << "Error when calling mcvAddBorder: image should be 32F" << endl;
168  return;
169  }
170 
171  double sum = 0;
172  unsigned int N = 0;
173  for(int j = border_size + 1; j < image->height - border_size - 1; j++)
174  {
175  float * row = mcvRow(image, j, float);
176  for(int i = border_size + 1; i < image->width - border_size - 1; i++)
177  {
178  sum += double(row[i]);
179  N++;
180  }
181  }
182  float mean = float(sum / double(N));
183  for(int j = 0; j < image->height; j++)
184  {
185  float * row = mcvRow(image, j, float);
186  for(int i = 0; i < image->width; i++)
187  {
188  if (i <= border_size || i >= image->width - border_size - 1 ||
189  j <= border_size || j >= image->height - border_size - 1)
190  row[i] = mean;
191  }
192  }
193 }
194 
196 
197 IplImage * mcvColorToGray(IplImage * colorImage)
198 {
199  IplImage * result = cvCreateImage(cvSize(colorImage->width, colorImage->height), IPL_DEPTH_8U, 1);
200 
201  cvCvtColor(colorImage, result, CV_RGB2GRAY);
202 
203  return result;
204 }
205 
206 IplImage * mcvGrayToColor(IplImage * grayImage)
207 {
208  IplImage * result = cvCreateImage(cvSize(grayImage->width, grayImage->height), IPL_DEPTH_8U, 3);
209 
210  if (grayImage->depth == IPL_DEPTH_32F)
211  {
212  IplImage * tempImage;
213 
214  double min = 255, max = 0;
215  CvPoint Pmin, Pmax;
216  cvMinMaxLoc(grayImage, &min, &max, &Pmin, &Pmax);
217  tempImage = cvCreateImage(cvSize(grayImage->width, grayImage->height), IPL_DEPTH_8U, 1);
218  cvConvertScale(grayImage, tempImage, 255. / (max - min), -min * 255 / (max - min));
219  cvCvtColor(tempImage, result, CV_GRAY2RGB);
220  cvReleaseImage(&tempImage);
221  }
222  else
223  cvCvtColor(grayImage, result, CV_GRAY2RGB);
224 
225  return result;
226 }
227 
228 void mcvHSV2RGB(float H, float S, float V, int & R, int & G, int & B)
229 {
230  if (S == 0) //HSV values = 0..1
231  {
232  R = int( V * 255.f );
233  G = int( V * 255.f );
234  B = int( V * 255.f );
235  }
236  else
237  {
238  float var_h = H * 6;
239  if ( var_h >= 6 ) var_h -= 6; // H must be < 1
240  int var_i = int( var_h );
241  float var_1 = V * ( 1 - S );
242  float var_2 = V * ( 1 - S * ( var_h - var_i ) );
243  float var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );
244 
245  float var_r, var_g, var_b;
246  if ( var_i == 0 ) { var_r = V ; var_g = var_3 ; var_b = var_1; }
247  else if ( var_i == 1 ) { var_r = var_2 ; var_g = V ; var_b = var_1; }
248  else if ( var_i == 2 ) { var_r = var_1 ; var_g = V ; var_b = var_3; }
249  else if ( var_i == 3 ) { var_r = var_1 ; var_g = var_2 ; var_b = V; }
250  else if ( var_i == 4 ) { var_r = var_3 ; var_g = var_1 ; var_b = V; }
251  else { var_r = V ; var_g = var_1 ; var_b = var_2; }
252 
253  R = int( var_r * 255.f ); // RGB results =0..255
254  G = int( var_g * 255.f );
255  B = int( var_b * 255.f );
256  }
257 }
258 
259 IplImage * mcvFloatToHue(IplImage * floatImage, int curve_number)
260 {
261  if (floatImage->depth != IPL_DEPTH_32F)
262  return 0;
263 
264  IplImage * result = cvCreateImage(cvSize(floatImage->width, floatImage->height),
265  IPL_DEPTH_8U, 3);
266  double min = 255, max = 0;
267  CvPoint Pmin, Pmax;
268  cvMinMaxLoc(floatImage, &min, &max, &Pmin, &Pmax);
269 
270  for(int y = 0; y < result->height; y++)
271  {
272  float * row = mcvRow(floatImage, y, float);
273  unsigned char * rowH = mcvRow(result, y, unsigned char);
274  for(int x = 0; x < result->width; x++)
275  {
276  bool use_color = true;
277  if (x < result->width - 1 && y < result->height - 1)
278  {
279  int l1 = int( ((log(row[x]) - log(min)) / (log(max) - log(min))) * curve_number );
280  int l2 = int( ((log(row[x + 1]) - log(min)) / (log(max) - log(min))) * curve_number );
281  int l3 = int( ((log(row[x + floatImage->width]) - log(min)) / (log(max) - log(min))) * curve_number );
282  if (l1 != l2 || l1 != l3)
283  use_color = false;
284  }
285 
286  if (use_color)
287  {
288  int r, g, b;
289  mcvHSV2RGB(float( (row[x] - min) / (max - min) ), 1.f, 1.f, r, g, b);
290  rowH[3 * x] = (unsigned char)(r);
291  rowH[3 * x + 1] = (unsigned char)(g);
292  rowH[3 * x + 2] = (unsigned char)(b);
293  }
294  else
295  {
296  rowH[3 * x] = 0;
297  rowH[3 * x + 1] = 0;
298  rowH[3 * x + 2] = 0;
299  }
300  }
301  }
302 
303  return result;
304 }
305 
306 IplImage * mcvFloatToGray(IplImage * floatImage, int curve_number)
307 {
308  if (floatImage->depth != IPL_DEPTH_32F)
309  return 0;
310 
311  IplImage * result = cvCreateImage(cvSize(floatImage->width, floatImage->height),
312  IPL_DEPTH_8U, 3);
313  double min = 255, max = 0;
314  CvPoint Pmin, Pmax;
315  cvMinMaxLoc(floatImage, &min, &max, &Pmin, &Pmax);
316 
317  for(int y = 0; y < result->height; y++)
318  {
319  float * row = mcvRow(floatImage, y, float);
320  unsigned char * rowH = mcvRow(result, y, unsigned char);
321  for(int x = 0; x < result->width; x++)
322  {
323  bool use_gray = true;
324  if (x < result->width - 1 && y < result->height - 1)
325  {
326  int l1 = int( (row[x] - min) / (max - min) * curve_number );
327  int l2 = int( (row[x + 1] - min) / (max - min) * curve_number );
328  int l3 = int( (row[x + floatImage->width] - min) / (max - min) * curve_number );
329  if (l1 != l2 || l1 != l3)
330  use_gray = false;
331  }
332 
333  if (use_gray)
334  {
335  rowH[3 * x] = (unsigned char)( 255. * (row[x] - min) / (max - min) );
336  rowH[3 * x + 1] = (unsigned char)( 255. * (row[x] - min) / (max - min) );
337  rowH[3 * x + 2] = (unsigned char)( 255. * (row[x] - min) / (max - min) );
338  }
339  else
340  {
341  rowH[3 * x] = 0;
342  rowH[3 * x + 1] = 0;
343  rowH[3 * x + 2] = 255;
344  }
345  }
346  }
347 
348  return result;
349 }
350 
351 IplImage * showLocalMinima(IplImage * image)
352 {
353  IplImage * result = mcvGrayToColor(image);
354 
355  int dy = image->widthStep / sizeof(float);
356 
357  for(int y = 1; y < image->height - 1; y++)
358  {
359  float * row = mcvRow(image, y, float);
360  unsigned char * row_r = mcvRow(result, y, unsigned char);
361  for(int x = 1; x < image->width - 1; x++)
362  {
363  if (row[x] < row[x - 1] && row[x] < row[x + 1] &&
364  row[x] < row[x - dy] && row[x] < row[x + dy] &&
365  row[x] < row[x - dy - 1] && row[x] < row[x + dy - 1] &&
366  row[x] < row[x - dy + 1] && row[x] < row[x + dy + 1])
367  {
368  row_r[3 * x] = 0;
369  row_r[3 * x + 1] = 0;
370  row_r[3 * x + 2] = 255;
371  }
372  }
373  }
374 
375  return result;
376 }
377 
378 IplImage * showLocalMaxima(IplImage * image)
379 {
380  IplImage * result = mcvGrayToColor(image);
381 
382  int dy = image->widthStep / sizeof(float);
383 
384  for(int y = 1; y < image->height - 1; y++)
385  {
386  float * row = mcvRow(image, y, float);
387  unsigned char * row_r = mcvRow(result, y, unsigned char);
388  for(int x = 1; x < image->width - 1; x++)
389  {
390  if (row[x] > row[x - 1] && row[x] > row[x + 1] &&
391  row[x] > row[x - dy] && row[x] > row[x + dy] &&
392  row[x] > row[x - dy - 1] && row[x] > row[x + dy - 1] &&
393  row[x] > row[x - dy + 1] && row[x] > row[x + dy + 1])
394  {
395  row_r[3 * x] = 0;
396  row_r[3 * x + 1] = 0;
397  row_r[3 * x + 2] = 255;
398  }
399  }
400  }
401 
402  return result;
403 }
404 
405 void mcvSwapRandB(IplImage * image)
406 {
407  for(int l = 0; l < image->height; l++)
408  {
409  unsigned char * line = (unsigned char *)image->imageData + l * image->widthStep;
410 
411  for(int c = 0; c < image->nChannels * image->width; c += 3)
412  {
413  char r = line[c];
414  line[c] = line[c + 2];
415  line[c + 2] = r;
416  }
417  }
418 }
419 
420 void mcvScaleTo0_255(IplImage * original, IplImage * scaled)
421 {
422  double min = 255, max = 0;
423  CvPoint Pmin, Pmax;
424 
425  cvMinMaxLoc(original, &min, &max, &Pmin, &Pmax);
426  cvConvertScale(original, scaled, 255. / (max - min), -min * 255 / (max - min));
427 }
428 
430 
431 int mcvSaveImage(const char * filename, IplImage * image, bool verbose)
432 {
433  if (verbose)
434  cout << "(saving " << filename << "..." << flush;
435 
436  int result;
437 
438  if (image->depth == IPL_DEPTH_8U)
439  result = cvSaveImage(filename, image);
440  else
441  {
442  IplImage * tempImage;
443 
444  double min = 255, max = 0;
445  CvPoint Pmin, Pmax;
446  cvMinMaxLoc(image, &min, &max, &Pmin, &Pmax);
447 
448  if (verbose)
449  cout << "[" << min << " : " << max << "] " << flush;
450 
451  tempImage = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);
452  cvConvertScale(image, tempImage, 255. / (max - min), -min * 255 / (max - min));
453 
454  result = cvSaveImage(filename, tempImage);
455 
456  cvReleaseImage(&tempImage);
457  }
458 
459  if (verbose && !result)
460  cout << "ERROR !" << endl;
461 
462  if (verbose && result)
463  cout << "ok)" << endl;
464 
465  return result;
466 }
467 
468 int mcvSaveImage(const char * generic_filename, int index, IplImage * image, bool verbose)
469 {
470  char filename[1000];
471 
472  sprintf(filename, generic_filename, index);
473 
474  return mcvSaveImage(filename, image, verbose);
475 }
476 
478 
479 IplImage * mcvCreateSimilarImage(IplImage * image)
480 {
481  return cvCreateImage(cvSize(image->width, image->height), image->depth, image->nChannels);
482 }
483 
484 IplImage * mcvLoadImage(const char * filename, int code, bool verbose)
485 {
486  if (verbose)
487  cout << "(loading " << filename << "..." << flush;
488 
489  IplImage * result = cvLoadImage(filename, code);
490 
491  if (verbose && !result)
492  cout << "ERROR !" << endl;
493 
494  if (verbose && result)
495  cout << "ok)" << endl;
496 
497  return result;
498 }
499 
500 IplImage * mcvLoadImage(const char * generic_filename, int index, int code, bool verbose)
501 {
502  char filename[1000];
503 
504  sprintf(filename, generic_filename, index);
505 
506  return mcvLoadImage(filename, code, verbose);
507 }
508 
510 
511 void mcvSquare(IplImage * image, int x, int y, int size, CvScalar color, int width)
512 {
513  cvLine(image, cvPoint(x - size / 2, y - size / 2), cvPoint(x + size / 2, y - size / 2), color, width);
514  cvLine(image, cvPoint(x + size / 2, y - size / 2), cvPoint(x + size / 2, y + size / 2), color, width);
515  cvLine(image, cvPoint(x + size / 2, y + size / 2), cvPoint(x - size / 2, y + size / 2), color, width);
516  cvLine(image, cvPoint(x - size / 2, y + size / 2), cvPoint(x - size / 2, y - size / 2), color, width);
517 }
518 
519 void mcvX(IplImage * image, int x, int y, int size, CvScalar color, int width)
520 {
521  cvLine(image, cvPoint(x - size / 2, y - size / 2), cvPoint(x + size / 2, y + size / 2), color, width);
522  cvLine(image, cvPoint(x + size / 2, y - size / 2), cvPoint(x - size / 2, y + size / 2), color, width);
523 }
524 
525 void mcvCross(IplImage * image, int x, int y, int size, CvScalar color, int width)
526 {
527  cvLine(image, cvPoint(x - size / 2, y), cvPoint(x + size / 2, y), color, width);
528  cvLine(image, cvPoint(x, y - size / 2), cvPoint(x, y + size / 2), color, width);
529 }
530 
531 void mcvCircle(IplImage * image, int x, int y, int size, CvScalar color, int thickness)
532 {
533  cvCircle(image, cvPoint(x, y), size / 2, color, thickness);
534 }
535 
536 void mcvVisibleLine(IplImage * image, int x1, int y1, int x2, int y2, int thickness)
537 {
538  cvLine(image, cvPoint(x1, y1), cvPoint(x2, y2), cvScalar(0, 0, 0), thickness + 2);
539  cvLine(image, cvPoint(x1, y1), cvPoint(x2, y2), cvScalar(255, 255, 255), thickness);
540 }
541 
543 
544 IplImage * mcvCreateRandomImage(CvSize size, int depth, int nChannels)
545 {
546  IplImage * result = cvCreateImage(size, depth, nChannels);
547 
548  if (nChannels == 1)
549  for(int l = 0; l < size.height; l++)
550  {
551  unsigned char * line = (unsigned char *)result->imageData + l * result->widthStep;
552  for(int c = 0; c < nChannels * size.width; c++)
553  line[c] = (unsigned char)(rand() % 256);
554  }
555  else
556  for(int l = 0; l < size.height; l++)
557  {
558  unsigned char * line = (unsigned char *)result->imageData + l * result->widthStep;
559  for(int c = 0; c < nChannels * size.width; c += 3)
560  line[c] = line[c + 1] = line[c + 2] = (unsigned char)(rand() % 256);
561  }
562 
563  return result;
564 }
565 
566 void mcvReplace(IplImage * image, int old_value, int new_value)
567 {
568  for(int l = 0; l < image->height; l++)
569  {
570  unsigned char * line = mcvRow(image, l, unsigned char);
571 
572  for(int c = 0; c < image->width; c++)
573  if (int(line[c]) == old_value)
574  line[c] = (unsigned char)new_value;
575  }
576 }
577 
578 void mcvReplaceByNoise(IplImage * image, int value)
579 {
580  for(int l = 0; l < image->height; l++)
581  {
582  unsigned char * line = mcvRow(image, l, unsigned char);
583 
584  for(int c = 0; c < image->width; c++)
585  if (int(line[c]) == value)
586  line[c] = (unsigned char)(rand() % 256);
587  }
588 }
589 
590 void mcvAddWhiteNoise(const IplImage * image, const int minNoise, const int maxNoise)
591 {
592  int deltaNoise = maxNoise - minNoise;
593 
594  for(int y = 0; y < image->height; y++)
595  {
596  unsigned char * line = mcvRow(image, y, unsigned char);
597 
598  for(int x = 0; x < image->width; x++)
599  {
600  int p = line[x];
601  int noise = rand() % (2 * deltaNoise + 1) - deltaNoise;
602 
603  if (noise < 0)
604  noise -= minNoise;
605  else
606  noise += minNoise;
607 
608  p += noise;
609  if (p > 255) p = 255;
610  if (p < 0) p = 0;
611 
612  line[x] = (unsigned char)p;
613  }
614  }
615 }
616 
617 void mcvAddWhiteNoise(const IplImage * image, const int maxNoise)
618 {
619  for(int y = 0; y < image->height; y++)
620  {
621  unsigned char * line = (unsigned char *)(image->imageData + y * image->widthStep);
622 
623  for(int x = 0; x < image->width; x++)
624  {
625  int p = line[x];
626 
627  p += rand() % (2 * maxNoise + 1) - maxNoise;
628 
629  if (p > 255)
630  p = 255;
631  else if (p < 0)
632  p = 0;
633 
634  line[x] = (unsigned char)p;
635  }
636  }
637 }
638 
639 // I -> 255 * (I / 255) ^ gamma
640 void mcvChangeGamma(IplImage * image, float gamma)
641 {
642  for(int y = 0; y < image->height; y++)
643  {
644  unsigned char * line = (unsigned char *)(image->imageData + y * image->widthStep);
645 
646  for(int x = 0; x < image->width; x++)
647  {
648  int I = int(255 * pow(line[x] / 255.0f, gamma));
649  if (I < 0) I = 0;
650  if (I > 256) I = 255;
651  line[x] = (unsigned char)I;
652  }
653  }
654 }
655 
657 
658 void mcvCrop(IplImage * image, int x, int y, IplImage * croppedImage)
659 {
660  IplROI * originalROI = image->roi;
661  int width = croppedImage->width;
662  int height = croppedImage->height;
663 
664  if (x < 0 || y < 0) return;
665  if (x + width >= image->width || y + height >= image->height) return;
666 
667  IplROI roi;
668 
669  roi.xOffset = x;
670  roi.yOffset = y;
671  roi.width = width;
672  roi.height = height;
673  roi.coi = 0;
674 
675  image->roi = &roi;
676  cvCopy(image, croppedImage);
677  image->roi = originalROI;
678 }
679 
680 IplImage * mcvCrop(IplImage * image, int x, int y, int width, int height)
681 {
682  IplImage * result = cvCreateImage(cvSize(width, height), image->depth, image->nChannels);
683 
684  mcvCrop(image, x, y, result);
685 
686  return result;
687 }
688 
690 
691 IplImage * mcvResize(IplImage * original_image, int new_width, int new_height)
692 {
693  if (new_height < 0)
694  new_height = int(float(new_width * original_image->height) / original_image->width);
695  IplImage * result = cvCreateImage(cvSize(new_width, new_height), original_image->depth, original_image->nChannels);
696  cvResize(original_image, result, CV_INTER_LINEAR);
697  return result;
698 }
699 
700 IplImage * mcvZoom(IplImage * source, int xc, int yc, float zoom)
701 {
702  IplImage * temp = cvCreateImage(cvSize(int(source->width * zoom), int(source->height * zoom)), IPL_DEPTH_8U, 1);
703  IplImage * result = cvCreateImage(cvSize(source->width, source->height), IPL_DEPTH_8U, 1);
704 
705  cvResize(source, temp, CV_INTER_LINEAR);
706  CvRect roi;
707  int nxc = int(xc * zoom);
708  int nyc = int(yc * zoom);
709  roi = cvRect(nxc - source->width / 2, nyc - source->height / 2, source->width, source->height);
710  cvSetImageROI(temp, roi);
711  cvCopy(temp, result);
712  cvReleaseImage(&temp);
713 
714  return result;
715 }
716 
717 void mcvPut(IplImage * destImage, IplImage * imageToCopy, int x, int y)
718 {
719  IplROI roi;
720  roi.xOffset = x;
721  roi.yOffset = y;
722  roi.width = imageToCopy->width;
723  roi.height = imageToCopy->height;
724  roi.coi = 0;
725 
726  IplROI * tempRoi = destImage->roi;
727 
728  destImage->roi = &roi;
729 
730  if (imageToCopy->nChannels == 1 && destImage->nChannels == 3)
731  {
732  IplImage * colorImageToCopy = mcvGrayToColor(imageToCopy);
733  cvCopy(colorImageToCopy, destImage);
734  cvReleaseImage(&colorImageToCopy);
735  }
736  else
737  cvCopy(imageToCopy, destImage);
738 
739  destImage->roi = tempRoi;
740 }
741 
742 void mcvDeinterlace(IplImage * image)
743 {
744  unsigned char * line = (unsigned char *)(image->imageData + image->widthStep);
745  int width = image->nChannels * image->width;
746 
747  for(int y = 1; y < image->height; y += 2)
748  {
749  unsigned char * previous = line - image->widthStep;
750  unsigned char * next = line + image->widthStep;
751 
752  for(int x = 0; x < width; x++)
753  line[x] = (unsigned char)((int(previous[x]) + int(next[x])) >> 1);
754 
755  line += 2 * image->widthStep;
756  }
757 }
758 
760 
761 IplImage * mcvGetPatch(IplImage * image, int u, int v, int width, int height)
762 {
763  return mcvCrop(image, u - width / 2, v - height / 2, width, height);
764 }
765 
766 void mcvGetPatch(IplImage * image, IplImage * patch, int u, int v)
767 {
768  mcvCrop(image, u - patch->width / 2, v - patch->height / 2, patch);
769 }
770 
771 void imcvR3z(double Rz[3][3], double angle)
772 {
773  Rz[0][0] = cos(angle); Rz[0][1] = -sin(angle); Rz[0][2] = 0.;
774  Rz[1][0] = sin(angle); Rz[1][1] = cos(angle); Rz[1][2] = 0.;
775  Rz[2][0] = 0.; Rz[2][1] = 0.; Rz[2][2] = 1.;
776 }
777 
778 void imcvDiag3(double D[3][3], double d1, double d2, double d3)
779 {
780  D[0][0] = d1; D[0][1] = 0.; D[0][2] = 0.;
781  D[1][0] = 0.; D[1][1] = d2; D[1][2] = 0.;
782  D[2][0] = 0.; D[2][1] = 0.; D[2][2] = d3;
783 }
784 
785 void imcvTransl3(double T[3][3], double tx, double ty)
786 {
787  T[0][0] = 1.; T[0][1] = 0.; T[0][2] = tx;
788  T[1][0] = 0.; T[1][1] = 1.; T[1][2] = ty;
789  T[2][0] = 0.; T[2][1] = 0.; T[2][2] = 1.;
790 }
791 
792 void imcvMul_MN3(double A[3][3], double B[3][3], double AB[3][3])
793 {
794  double copy[3][3];
795 
796  for(int i = 0; i < 3; i++)
797  for(int j = 0; j < 3; j++)
798  {
799  copy[i][j] = 0.;
800  for(int k = 0; k < 3; k++)
801  copy[i][j] += A[i][k] * B[k][j];
802  }
803  for(int i = 0; i < 3; i++)
804  for(int j = 0; j < 3; j++)
805  AB[i][j] = copy[i][j];
806 }
807 
808 void imcvMul_MNt3(double A[3][3], double B[3][3], double ABt[3][3])
809 {
810  double copy[3][3];
811 
812  for(int i = 0; i < 3; i++)
813  for(int j = 0; j < 3; j++)
814  {
815  copy[i][j] = 0.;
816  for(int k = 0; k < 3; k++)
817  copy[i][j] += A[i][k] * B[j][k];
818  }
819  for(int i = 0; i < 3; i++)
820  for(int j = 0; j < 3; j++)
821  ABt[i][j] = copy[i][j];
822 }
823 
824 void imcvMul_MNMt3(double M[3][3], double N[3][3], double MNMt[3][3])
825 {
826  double NMt[3][3];
827 
828  imcvMul_MNt3(N, M, NMt);
829  imcvMul_MN3(M, NMt, MNMt);
830 }
831 
833 
834 /*
835 cf Multiple view geometry, p. 19
836 A = T(tx, ty) R(theta) R(-phi) D(lambda1, lambda2) R(phi)
837 
838 !!! actually compute the inverse of A to be opencv complient
839 */
840 
841 void mcvComputeAffineTransfo(float * a,
842  int u, int v,
843  float theta, float phi,
844  float lambda1, float lambda2,
845  float tx, float ty)
846 {
847  double K[3][3];
848  double A[3][3];
849 
850  imcvTransl3(A, -tx, -ty);
851  imcvR3z(K, -theta);
852  imcvMul_MN3(K, A, A);
853 
854  imcvR3z(K, phi);
855  imcvMul_MN3(K, A, A);
856 
857  imcvDiag3(K, 1. / lambda1, 1. / lambda2, 1);
858  imcvMul_MN3(K, A, A);
859 
860  imcvR3z(K, -phi);
861  imcvMul_MN3(K, A, A);
862 
863  a[0] = (float)A[0][0];
864  a[1] = (float)A[0][1];
865  a[2] = (float)u + (float)A[0][2];
866  a[3] = (float)A[1][0];
867  a[4] = (float)A[1][1];
868  a[5] = (float)v + (float)A[1][2];
869 }
870 
871 CvScalar mcvRainbowColor(int index, float coeff)
872 {
873  if (index == -1)
874  index = rand() % 6;
875  else
876  index = index % 6;
877 
878  switch(index)
879  {
880  case 0: return CV_RGB(255 * coeff, 0, 0);
881  case 1: return CV_RGB(0, 255 * coeff, 0);
882  case 2: return CV_RGB(0, 0, 255 * coeff);
883 
884  case 3: return CV_RGB(255 * coeff, 255 * coeff, 0);
885  case 4: return CV_RGB(0, 255 * coeff, 255 * coeff);
886  case 5: return CV_RGB(255 * coeff, 0, 255 * coeff);
887 
888  default: return CV_RGB(128, 128, 128);
889  }
890 }
891