Visual Servoing Platform version 3.5.0
vpImageFilter.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Various image tools, convolution, ...
33 *
34 * Authors:
35 * Eric Marchand
36 *
37 *****************************************************************************/
38
39#include <visp3/core/vpImageConvert.h>
40#include <visp3/core/vpImageFilter.h>
41#include <visp3/core/vpRGBa.h>
42#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020408)
43#include <opencv2/imgproc/imgproc.hpp>
44#elif defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020101)
45#include <opencv2/imgproc/imgproc_c.h>
46#elif defined(VISP_HAVE_OPENCV)
47#include <cv.h>
48#endif
49
77void vpImageFilter::filter(const vpImage<unsigned char> &I, vpImage<double> &If, const vpMatrix &M, bool convolve)
78{
79 unsigned int size_y = M.getRows(), size_x = M.getCols();
80 unsigned int half_size_y = size_y / 2, half_size_x = size_x / 2;
81
82 If.resize(I.getHeight(), I.getWidth(), 0.0);
83
84 if (convolve) {
85 for (unsigned int i = half_size_y; i < I.getHeight() - half_size_y; i++) {
86 for (unsigned int j = half_size_x; j < I.getWidth() - half_size_x; j++) {
87 double conv = 0;
88
89 for (unsigned int a = 0; a < size_y; a++) {
90 for (unsigned int b = 0; b < size_x; b++) {
91 double val = I[i + half_size_y - a][j + half_size_x - b]; // Convolution
92 conv += M[a][b] * val;
93 }
94 }
95 If[i][j] = conv;
96 }
97 }
98 } else {
99 for (unsigned int i = half_size_y; i < I.getHeight() - half_size_y; i++) {
100 for (unsigned int j = half_size_x; j < I.getWidth() - half_size_x; j++) {
101 double corr = 0;
102
103 for (unsigned int a = 0; a < size_y; a++) {
104 for (unsigned int b = 0; b < size_x; b++) {
105 double val = I[i - half_size_y + a][j - half_size_x + b]; // Correlation
106 corr += M[a][b] * val;
107 }
108 }
109 If[i][j] = corr;
110 }
111 }
112 }
113}
114
128 bool convolve)
129{
130 unsigned int size = M.getRows();
131 unsigned int half_size = size / 2;
132
133 Iu.resize(I.getHeight(), I.getWidth(), 0.0);
134 Iv.resize(I.getHeight(), I.getWidth(), 0.0);
135
136 if (convolve) {
137 for (unsigned int v = half_size; v < I.getHeight() - half_size; v++) {
138 for (unsigned int u = half_size; u < I.getWidth() - half_size; u++) {
139 double conv_u = 0;
140 double conv_v = 0;
141
142 for (unsigned int a = 0; a < size; a++) {
143 for (unsigned int b = 0; b < size; b++) {
144 double val = I[v + half_size - a][u + half_size - b]; // Convolution
145 conv_u += M[a][b] * val;
146 conv_v += M[b][a] * val;
147 }
148 }
149 Iu[v][u] = conv_u;
150 Iv[v][u] = conv_v;
151 }
152 }
153 } else {
154 for (unsigned int v = half_size; v < I.getHeight() - half_size; v++) {
155 for (unsigned int u = half_size; u < I.getWidth() - half_size; u++) {
156 double conv_u = 0;
157 double conv_v = 0;
158
159 for (unsigned int a = 0; a < size; a++) {
160 for (unsigned int b = 0; b < size; b++) {
161 double val = I[v - half_size + a][u - half_size + b]; // Correlation
162 conv_u += M[a][b] * val;
163 conv_v += M[b][a] * val;
164 }
165 }
166 Iu[v][u] = conv_u;
167 Iv[v][u] = conv_v;
168 }
169 }
170 }
171}
172
226 const vpColVector &kernelV)
227{
228 unsigned int size = kernelH.size();
229 unsigned int half_size = size / 2;
230
231 If.resize(I.getHeight(), I.getWidth(), 0.0);
232 vpImage<double> I_filter(I.getHeight(), I.getWidth(), 0.0);
233
234 for (unsigned int i = 0; i < I.getHeight(); i++) {
235 for (unsigned int j = half_size; j < I.getWidth() - half_size; j++) {
236 double conv = 0.0;
237 for (unsigned int a = 0; a < kernelH.size(); a++) {
238 conv += kernelH[a] * I[i][j + half_size - a];
239 }
240
241 I_filter[i][j] = conv;
242 }
243 }
244
245 for (unsigned int i = half_size; i < I.getHeight() - half_size; i++) {
246 for (unsigned int j = 0; j < I.getWidth(); j++) {
247 double conv = 0.0;
248 for (unsigned int a = 0; a < kernelV.size(); a++) {
249 conv += kernelV[a] * I_filter[i + half_size - a][j];
250 }
251
252 If[i][j] = conv;
253 }
254 }
255}
256
257#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)
299 unsigned int gaussianFilterSize, double thresholdCanny,
300 unsigned int apertureSobel)
301{
302#if (VISP_HAVE_OPENCV_VERSION < 0x020408)
303 IplImage *img_ipl = NULL;
304 vpImageConvert::convert(Isrc, img_ipl);
305 IplImage *edges_ipl;
306 edges_ipl = cvCreateImage(cvSize(img_ipl->width, img_ipl->height), img_ipl->depth, img_ipl->nChannels);
307
308 cvSmooth(img_ipl, img_ipl, CV_GAUSSIAN, (int)gaussianFilterSize, (int)gaussianFilterSize, 0, 0);
309 cvCanny(img_ipl, edges_ipl, thresholdCanny, thresholdCanny, (int)apertureSobel);
310
311 vpImageConvert::convert(edges_ipl, Ires);
312 cvReleaseImage(&img_ipl);
313 cvReleaseImage(&edges_ipl);
314#else
315 cv::Mat img_cvmat, edges_cvmat;
316 vpImageConvert::convert(Isrc, img_cvmat);
317 cv::GaussianBlur(img_cvmat, img_cvmat, cv::Size((int)gaussianFilterSize, (int)gaussianFilterSize), 0, 0);
318 cv::Canny(img_cvmat, edges_cvmat, thresholdCanny, thresholdCanny, (int)apertureSobel);
319 vpImageConvert::convert(edges_cvmat, Ires);
320#endif
321}
322#endif
323
327void vpImageFilter::filter(const vpImage<unsigned char> &I, vpImage<double> &GI, const double *filter,
328 unsigned int size)
329{
330 vpImage<double> GIx;
331 filterX(I, GIx, filter, size);
332 filterY(GIx, GI, filter, size);
333 GIx.destroy();
334}
335
339void vpImageFilter::filter(const vpImage<double> &I, vpImage<double> &GI, const double *filter, unsigned int size)
340{
341 vpImage<double> GIx;
342 filterX(I, GIx, filter, size);
343 filterY(GIx, GI, filter, size);
344 GIx.destroy();
345}
346
347void vpImageFilter::filterX(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *filter,
348 unsigned int size)
349{
350 dIx.resize(I.getHeight(), I.getWidth());
351 for (unsigned int i = 0; i < I.getHeight(); i++) {
352 for (unsigned int j = 0; j < (size - 1) / 2; j++) {
353 dIx[i][j] = vpImageFilter::filterXLeftBorder(I, i, j, filter, size);
354 // dIx[i][j]=0;
355 }
356 for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
357 dIx[i][j] = vpImageFilter::filterX(I, i, j, filter, size);
358 }
359 for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
360 dIx[i][j] = vpImageFilter::filterXRightBorder(I, i, j, filter, size);
361 // dIx[i][j]=0;
362 }
363 }
364}
365void vpImageFilter::filterX(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter,
366 unsigned int size)
367{
368 dIx.resize(I.getHeight(), I.getWidth());
369 for (unsigned int i = 0; i < I.getHeight(); i++) {
370 for (unsigned int j = 0; j < (size - 1) / 2; j++) {
371 dIx[i][j].R = static_cast<unsigned char>(vpImageFilter::filterXLeftBorderR(I, i, j, filter, size));
372 dIx[i][j].G = static_cast<unsigned char>(vpImageFilter::filterXLeftBorderG(I, i, j, filter, size));
373 dIx[i][j].B = static_cast<unsigned char>(vpImageFilter::filterXLeftBorderB(I, i, j, filter, size));
374 }
375 for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
376 dIx[i][j].R = static_cast<unsigned char>(vpImageFilter::filterXR(I, i, j, filter, size));
377 dIx[i][j].G = static_cast<unsigned char>(vpImageFilter::filterXG(I, i, j, filter, size));
378 dIx[i][j].B = static_cast<unsigned char>(vpImageFilter::filterXB(I, i, j, filter, size));
379 }
380 for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
381 dIx[i][j].R = static_cast<unsigned char>(vpImageFilter::filterXRightBorderR(I, i, j, filter, size));
382 dIx[i][j].G = static_cast<unsigned char>(vpImageFilter::filterXRightBorderG(I, i, j, filter, size));
383 dIx[i][j].B = static_cast<unsigned char>(vpImageFilter::filterXRightBorderB(I, i, j, filter, size));
384 }
385 }
386}
387void vpImageFilter::filterX(const vpImage<double> &I, vpImage<double> &dIx, const double *filter, unsigned int size)
388{
389 dIx.resize(I.getHeight(), I.getWidth());
390 for (unsigned int i = 0; i < I.getHeight(); i++) {
391 for (unsigned int j = 0; j < (size - 1) / 2; j++) {
392 dIx[i][j] = vpImageFilter::filterXLeftBorder(I, i, j, filter, size);
393 // dIx[i][j]=0;
394 }
395 for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
396 dIx[i][j] = vpImageFilter::filterX(I, i, j, filter, size);
397 }
398 for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
399 dIx[i][j] = vpImageFilter::filterXRightBorder(I, i, j, filter, size);
400 // dIx[i][j]=0;
401 }
402 }
403}
404void vpImageFilter::filterY(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *filter,
405 unsigned int size)
406{
407 dIy.resize(I.getHeight(), I.getWidth());
408 for (unsigned int i = 0; i < (size - 1) / 2; i++) {
409 for (unsigned int j = 0; j < I.getWidth(); j++) {
410 dIy[i][j] = vpImageFilter::filterYTopBorder(I, i, j, filter, size);
411 }
412 }
413 for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
414 for (unsigned int j = 0; j < I.getWidth(); j++) {
415 dIy[i][j] = vpImageFilter::filterY(I, i, j, filter, size);
416 }
417 }
418 for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
419 for (unsigned int j = 0; j < I.getWidth(); j++) {
420 dIy[i][j] = vpImageFilter::filterYBottomBorder(I, i, j, filter, size);
421 }
422 }
423}
424void vpImageFilter::filterY(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIy, const double *filter,
425 unsigned int size)
426{
427 dIy.resize(I.getHeight(), I.getWidth());
428 for (unsigned int i = 0; i < (size - 1) / 2; i++) {
429 for (unsigned int j = 0; j < I.getWidth(); j++) {
430 dIy[i][j].R = static_cast<unsigned char>(vpImageFilter::filterYTopBorderR(I, i, j, filter, size));
431 dIy[i][j].G = static_cast<unsigned char>(vpImageFilter::filterYTopBorderG(I, i, j, filter, size));
432 dIy[i][j].B = static_cast<unsigned char>(vpImageFilter::filterYTopBorderB(I, i, j, filter, size));
433 }
434 }
435 for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
436 for (unsigned int j = 0; j < I.getWidth(); j++) {
437 dIy[i][j].R = static_cast<unsigned char>(vpImageFilter::filterYR(I, i, j, filter, size));
438 dIy[i][j].G = static_cast<unsigned char>(vpImageFilter::filterYG(I, i, j, filter, size));
439 dIy[i][j].B = static_cast<unsigned char>(vpImageFilter::filterYB(I, i, j, filter, size));
440 }
441 }
442 for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
443 for (unsigned int j = 0; j < I.getWidth(); j++) {
444 dIy[i][j].R = static_cast<unsigned char>(vpImageFilter::filterYBottomBorderR(I, i, j, filter, size));
445 dIy[i][j].G = static_cast<unsigned char>(vpImageFilter::filterYBottomBorderG(I, i, j, filter, size));
446 dIy[i][j].B = static_cast<unsigned char>(vpImageFilter::filterYBottomBorderB(I, i, j, filter, size));
447 }
448 }
449}
450void vpImageFilter::filterY(const vpImage<double> &I, vpImage<double> &dIy, const double *filter, unsigned int size)
451{
452 dIy.resize(I.getHeight(), I.getWidth());
453 for (unsigned int i = 0; i < (size - 1) / 2; i++) {
454 for (unsigned int j = 0; j < I.getWidth(); j++) {
455 dIy[i][j] = vpImageFilter::filterYTopBorder(I, i, j, filter, size);
456 }
457 }
458 for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
459 for (unsigned int j = 0; j < I.getWidth(); j++) {
460 dIy[i][j] = vpImageFilter::filterY(I, i, j, filter, size);
461 }
462 }
463 for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
464 for (unsigned int j = 0; j < I.getWidth(); j++) {
465 dIy[i][j] = vpImageFilter::filterYBottomBorder(I, i, j, filter, size);
466 }
467 }
468}
469
482void vpImageFilter::gaussianBlur(const vpImage<unsigned char> &I, vpImage<double> &GI, unsigned int size, double sigma,
483 bool normalize)
484{
485 double *fg = new double[(size + 1) / 2];
486 vpImageFilter::getGaussianKernel(fg, size, sigma, normalize);
487 vpImage<double> GIx;
488 vpImageFilter::filterX(I, GIx, fg, size);
489 vpImageFilter::filterY(GIx, GI, fg, size);
490 GIx.destroy();
491 delete[] fg;
492}
493
505void vpImageFilter::gaussianBlur(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &GI, unsigned int size, double sigma,
506 bool normalize)
507{
508 double *fg = new double[(size + 1) / 2];
509 vpImageFilter::getGaussianKernel(fg, size, sigma, normalize);
510 vpImage<vpRGBa> GIx;
511 vpImageFilter::filterX(I, GIx, fg, size);
512 vpImageFilter::filterY(GIx, GI, fg, size);
513 GIx.destroy();
514 delete[] fg;
515}
516
528void vpImageFilter::gaussianBlur(const vpImage<double> &I, vpImage<double> &GI, unsigned int size, double sigma,
529 bool normalize)
530{
531 double *fg = new double[(size + 1) / 2];
532 vpImageFilter::getGaussianKernel(fg, size, sigma, normalize);
533 vpImage<double> GIx;
534 vpImageFilter::filterX(I, GIx, fg, size);
535 vpImageFilter::filterY(GIx, GI, fg, size);
536 GIx.destroy();
537 delete[] fg;
538}
539
555void vpImageFilter::getGaussianKernel(double *filter, unsigned int size, double sigma, bool normalize)
556{
557 if (size % 2 != 1)
558 throw(vpImageException(vpImageException::incorrectInitializationError, "Bad Gaussian filter size"));
559
560 if (sigma <= 0)
561 sigma = (size - 1) / 6.0;
562
563 int middle = (int)(size - 1) / 2;
564 double sigma2 = vpMath::sqr(sigma);
565 for (int i = 0; i <= middle; i++) {
566 filter[i] = (1. / (sigma * sqrt(2. * M_PI))) * exp(-(i * i) / (2. * sigma2));
567 }
568 if (normalize) {
569 // renormalization
570 double sum = 0;
571 for (int i = 1; i <= middle; i++) {
572 sum += 2 * filter[i];
573 }
574 sum += filter[0];
575
576 for (int i = 0; i <= middle; i++) {
577 filter[i] = filter[i] / sum;
578 }
579 }
580}
581
595void vpImageFilter::getGaussianDerivativeKernel(double *filter, unsigned int size, double sigma, bool normalize)
596{
597 if (size % 2 != 1)
598 throw(vpImageException(vpImageException::incorrectInitializationError, "Bad Gaussian filter size"));
599
600 if (sigma <= 0)
601 sigma = (size - 1) / 6.0;
602
603 int middle = (int)(size - 1) / 2;
604 double sigma2 = vpMath::sqr(sigma);
605 filter[0] = 0.;
606 for (int i = 1; i <= middle; i++) {
607 filter[i] = -(1. / (sigma * sqrt(2. * M_PI))) *
608 (exp(-((i + 1) * (i + 1)) / (2. * sigma2)) - exp(-((i - 1) * (i - 1)) / (2. * sigma2))) / 2.;
609 }
610
611 if (normalize) {
612 double sum = 0;
613 for (int i = 1; i <= middle; i++) {
614 sum += 2. * (1. / (sigma * sqrt(2. * M_PI))) * exp(-(i * i) / (2. * sigma2));
615 }
616 sum += (1. / (sigma * sqrt(2. * M_PI)));
617
618 for (int i = 1; i <= middle; i++) {
619 filter[i] = filter[i] / sum;
620 }
621 }
622}
623
625{
626 dIx.resize(I.getHeight(), I.getWidth());
627 // dIx=0;
628 for (unsigned int i = 0; i < I.getHeight(); i++) {
629 for (unsigned int j = 0; j < 3; j++) {
630 dIx[i][j] = 0;
631 }
632 for (unsigned int j = 3; j < I.getWidth() - 3; j++) {
633 dIx[i][j] = vpImageFilter::derivativeFilterX(I, i, j);
634 }
635 for (unsigned int j = I.getWidth() - 3; j < I.getWidth(); j++) {
636 dIx[i][j] = 0;
637 }
638 }
639}
640
642{
643 dIy.resize(I.getHeight(), I.getWidth());
644 // dIy=0;
645 for (unsigned int i = 0; i < 3; i++) {
646 for (unsigned int j = 0; j < I.getWidth(); j++) {
647 dIy[i][j] = 0;
648 }
649 }
650 for (unsigned int i = 3; i < I.getHeight() - 3; i++) {
651 for (unsigned int j = 0; j < I.getWidth(); j++) {
652 dIy[i][j] = vpImageFilter::derivativeFilterY(I, i, j);
653 }
654 }
655 for (unsigned int i = I.getHeight() - 3; i < I.getHeight(); i++) {
656 for (unsigned int j = 0; j < I.getWidth(); j++) {
657 dIy[i][j] = 0;
658 }
659 }
660}
661
662void vpImageFilter::getGradX(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *filter,
663 unsigned int size)
664{
665 dIx.resize(I.getHeight(), I.getWidth());
666 //#pragma omp parallel for
667 for (unsigned int i = 0; i < I.getHeight(); i++) {
668 for (unsigned int j = 0; j < (size - 1) / 2; j++) {
669 dIx[i][j] = 0;
670 }
671 for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
672 dIx[i][j] = vpImageFilter::derivativeFilterX(I, i, j, filter, size);
673 }
674 for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
675 dIx[i][j] = 0;
676 }
677 }
678}
679void vpImageFilter::getGradX(const vpImage<double> &I, vpImage<double> &dIx, const double *filter, unsigned int size)
680{
681 dIx.resize(I.getHeight(), I.getWidth());
682 // dIx=0;
683 for (unsigned int i = 0; i < I.getHeight(); i++) {
684 for (unsigned int j = 0; j < (size - 1) / 2; j++) {
685 dIx[i][j] = 0;
686 }
687 for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
688 dIx[i][j] = vpImageFilter::derivativeFilterX(I, i, j, filter, size);
689 }
690 for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
691 dIx[i][j] = 0;
692 }
693 }
694}
695
696void vpImageFilter::getGradY(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *filter,
697 unsigned int size)
698{
699 dIy.resize(I.getHeight(), I.getWidth());
700 //#pragma omp parallel for
701 for (unsigned int i = 0; i < (size - 1) / 2; i++) {
702 for (unsigned int j = 0; j < I.getWidth(); j++) {
703 dIy[i][j] = 0;
704 }
705 }
706 //#pragma omp parallel for
707 for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
708 for (unsigned int j = 0; j < I.getWidth(); j++) {
709 dIy[i][j] = vpImageFilter::derivativeFilterY(I, i, j, filter, size);
710 }
711 }
712 //#pragma omp parallel for
713 for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
714 for (unsigned int j = 0; j < I.getWidth(); j++) {
715 dIy[i][j] = 0;
716 }
717 }
718}
719
720void vpImageFilter::getGradY(const vpImage<double> &I, vpImage<double> &dIy, const double *filter, unsigned int size)
721{
722 dIy.resize(I.getHeight(), I.getWidth());
723 // dIy=0;
724 for (unsigned int i = 0; i < (size - 1) / 2; i++) {
725 for (unsigned int j = 0; j < I.getWidth(); j++) {
726 dIy[i][j] = 0;
727 }
728 }
729 for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
730 for (unsigned int j = 0; j < I.getWidth(); j++) {
731 dIy[i][j] = vpImageFilter::derivativeFilterY(I, i, j, filter, size);
732 }
733 }
734 for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
735 for (unsigned int j = 0; j < I.getWidth(); j++) {
736 dIy[i][j] = 0;
737 }
738 }
739}
740
750void vpImageFilter::getGradXGauss2D(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *gaussianKernel,
751 const double *gaussianDerivativeKernel, unsigned int size)
752{
753 vpImage<double> GIy;
754 vpImageFilter::filterY(I, GIy, gaussianKernel, size);
755 vpImageFilter::getGradX(GIy, dIx, gaussianDerivativeKernel, size);
756}
757
767void vpImageFilter::getGradYGauss2D(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *gaussianKernel,
768 const double *gaussianDerivativeKernel, unsigned int size)
769{
770 vpImage<double> GIx;
771 vpImageFilter::filterX(I, GIx, gaussianKernel, size);
772 vpImageFilter::getGradY(GIx, dIy, gaussianDerivativeKernel, size);
773}
774
775// operation pour pyramide gaussienne
777{
779#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x030000)
780 cv::Mat imgsrc, imgdest;
781 vpImageConvert::convert(I, imgsrc);
782 cv::pyrDown(imgsrc, imgdest, cv::Size((int)I.getWidth() / 2, (int)I.getHeight() / 2));
783 vpImageConvert::convert(imgdest, GI);
784#elif defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020408)
785 cv::Mat imgsrc, imgdest;
786 vpImageConvert::convert(I, imgsrc);
787 cv::pyrDown(imgsrc, imgdest, cvSize((int)I.getWidth() / 2, (int)I.getHeight() / 2));
788 vpImageConvert::convert(imgdest, GI);
789#elif defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)
790 IplImage *imgsrc = NULL; // cvCreateImage(cvGetSize(imgign), IPL_DEPTH_8U, 1);
791 IplImage *imgdest = NULL; // cvCreateImage(cvGetSize(imgign), IPL_DEPTH_8U, 1);
792 imgsrc = cvCreateImage(cvSize((int)I.getWidth(), (int)I.getHeight()), IPL_DEPTH_8U, 1);
793 imgdest = cvCreateImage(cvSize((int)I.getWidth() / 2, (int)I.getHeight() / 2), IPL_DEPTH_8U, 1);
794 vpImageConvert::convert(I, imgsrc);
795 cvPyrDown(imgsrc, imgdest);
796 vpImageConvert::convert(imgdest, GI);
797
798 cvReleaseImage(&imgsrc);
799 cvReleaseImage(&imgdest);
800// vpImage<unsigned char> sGI;sGI=GI;
801
802#else
805#endif
806}
807
809{
810#if 0
811 GI.resize(I.getHeight(),(int)((I.getWidth()+1.)/2.)) ;
812 for (unsigned int i=0 ; i < I.getHeight() ; i++)
813 {
814 GI[i][0]=I[i][0];
815 for (unsigned int j=1 ; j < ((I.getWidth()+1.)/2.)-1 ; j++)
816 {
817 GI[i][j]=vpImageFilter::filterGaussXPyramidal(I,i,2*j);
818 }
819 GI[i][(int)((I.getWidth()+1.)/2.)-1]=I[i][2*((int)((I.getWidth()+1.)/2.)-1)];
820 }
821#else
822 unsigned int w = I.getWidth() / 2;
823
824 GI.resize(I.getHeight(), w);
825 for (unsigned int i = 0; i < I.getHeight(); i++) {
826 GI[i][0] = I[i][0];
827 for (unsigned int j = 1; j < w - 1; j++) {
828 GI[i][j] = vpImageFilter::filterGaussXPyramidal(I, i, 2 * j);
829 }
830 GI[i][w - 1] = I[i][2 * w - 1];
831 }
832
833#endif
834}
836{
837
838#ifdef ORIG
839 GI.resize((int)((I.getHeight() + 1.) / 2.), I.getWidth());
840 for (unsigned int j = 0; j < I.getWidth(); j++) {
841 GI[0][j] = I[0][j];
842 for (unsigned int i = 1; i < ((I.getHeight() + 1.) / 2.) - 1; i++) {
843 GI[i][j] = vpImageFilter::filterGaussYPyramidal(I, 2 * i, j);
844 }
845 GI[(int)((I.getHeight() + 1.) / 2.) - 1][j] = I[2 * ((int)((I.getHeight() + 1.) / 2.) - 1)][j];
846 }
847
848#else
849 unsigned int h = I.getHeight() / 2;
850
851 GI.resize(h, I.getWidth());
852 for (unsigned int j = 0; j < I.getWidth(); j++) {
853 GI[0][j] = I[0][j];
854 for (unsigned int i = 1; i < h - 1; i++) {
855 GI[i][j] = vpImageFilter::filterGaussYPyramidal(I, 2 * i, j);
856 }
857 GI[h - 1][j] = I[2 * h - 1][j];
858 }
859#endif
860}
861
869double vpImageFilter::getSobelKernelX(double *filter, unsigned int size)
870{
871 if (size == 0)
872 throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size 0!");
873 if (size > 20)
874 throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size > 20!");
875
876 vpMatrix SobelY(size*2+1, size*2+1);
877 double norm = getSobelKernelY(SobelY.data, size);
878 memcpy(filter, SobelY.t().data, SobelY.getRows()*SobelY.getCols()*sizeof(double));
879 return norm;
880}
881
889double vpImageFilter::getSobelKernelY(double *filter, unsigned int size)
890{
891 //Sobel kernel pre-computed for the usual size
892 static const double SobelY3x3[9] = {-1.0, -2.0, -1.0,
893 0.0, 0.0, 0.0,
894 1.0, 2.0, 1.0};
895 static const double SobelY5x5[25] = {-1.0, -4.0, -6.0, -4.0, -1.0,
896 -2.0, -8.0, -12.0, -8.0, -2.0,
897 0.0, 0.0, 0.0, 0.0, 0.0,
898 2.0, 8.0, 12.0, 8.0, 2.0,
899 1.0, 4.0, 6.0, 4.0, 1.0};
900 static const double SobelY7x7[49] = {-1, -6, -15, -20, -15, -6, -1,
901 -4, -24, -60, -80, -60, -24, -4,
902 -5, -30, -75, -100, -75, -30, -5,
903 0, 0, 0, 0, 0, 0, 0,
904 5, 30, 75, 100, 75, 30, 5,
905 4, 24, 60, 80, 60, 24, 4,
906 1, 6, 15, 20, 15, 6, 1};
907 static const vpMatrix smoothingKernel(3,3);
908 smoothingKernel[0][0] = 1.0; smoothingKernel[0][1] = 2.0; smoothingKernel[0][2] = 1.0;
909 smoothingKernel[1][0] = 2.0; smoothingKernel[1][1] = 4.0; smoothingKernel[1][2] = 2.0;
910 smoothingKernel[2][0] = 1.0; smoothingKernel[2][1] = 2.0; smoothingKernel[2][2] = 1.0;
911
912 if (size == 0)
913 throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size 0!");
914 if (size > 20)
915 throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size > 20!");
916
917 const unsigned int kernel_size = size*2+1;
918 if (kernel_size == 3) {
919 memcpy(filter, SobelY3x3, kernel_size*kernel_size*sizeof(double));
920 return 1/8.0;
921 }
922 if (kernel_size == 5) {
923 memcpy(filter, SobelY5x5, kernel_size*kernel_size*sizeof(double));
924 return 1/16.0;
925 }
926 if (kernel_size == 7) {
927 memcpy(filter, SobelY7x7, kernel_size*kernel_size*sizeof(double));
928 return 1/16.0;
929 }
930
931 vpMatrix sobelY(7,7);
932 memcpy(sobelY.data, SobelY7x7, sobelY.getRows()*sobelY.getCols()*sizeof(double));
933 for (unsigned int i = 4; i <= size; i++) {
934 sobelY = vpMatrix::conv2(sobelY, smoothingKernel, "full");
935 }
936
937 memcpy(filter, sobelY.data, sobelY.getRows()*sobelY.getCols()*sizeof(double));
938
939 return 1/16.0;
940}
unsigned int getCols() const
Definition: vpArray2D.h:279
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:145
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:291
unsigned int getRows() const
Definition: vpArray2D.h:289
Implementation of column vector and the associated operations.
Definition: vpColVector.h:131
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ dimensionError
Bad dimension.
Definition: vpException.h:95
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emited by the vpImage class and its derivates.
static unsigned char filterGaussXPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static void filter(const vpImage< double > &I, vpImage< double > &Iu, vpImage< double > &Iv, const vpMatrix &M, bool convolve=false)
static double derivativeFilterY(const vpImage< T > &I, unsigned int r, unsigned int c)
Definition: vpImageFilter.h:96
static double filterYTopBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterYB(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static double filterXLeftBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterY(const vpImage< unsigned char > &I, vpImage< double > &dIx, const double *filter, unsigned int size)
static double filterYBottomBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGradXGauss2D(const vpImage< unsigned char > &I, vpImage< double > &dIx, const double *gaussianKernel, const double *gaussianDerivativeKernel, unsigned int size)
static double filterYTopBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGaussianDerivativeKernel(double *filter, unsigned int size, double sigma=0., bool normalize=true)
static void getGradX(const vpImage< unsigned char > &I, vpImage< double > &dIx)
static double filterXRightBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterYBottomBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterYTopBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterXB(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void filterX(const vpImage< unsigned char > &I, vpImage< double > &dIx, const double *filter, unsigned int size)
static void gaussianBlur(const vpImage< unsigned char > &I, vpImage< double > &GI, unsigned int size=7, double sigma=0., bool normalize=true)
static double filterXLeftBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterYR(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void sepFilter(const vpImage< unsigned char > &I, vpImage< double > &If, const vpColVector &kernelH, const vpColVector &kernelV)
static double getSobelKernelX(double *filter, unsigned int size)
static double filterXRightBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterYBottomBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double derivativeFilterX(const vpImage< T > &I, unsigned int r, unsigned int c)
Definition: vpImageFilter.h:82
static double filterXLeftBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGaussianKernel(double *filter, unsigned int size, double sigma=0., bool normalize=true)
static double getSobelKernelY(double *filter, unsigned int size)
static double filterXLeftBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterXRightBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGradYGauss2D(const vpImage< unsigned char > &I, vpImage< double > &dIy, const double *gaussianKernel, const double *gaussianDerivativeKernel, unsigned int size)
static void filterXR(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void getGaussXPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
static void canny(const vpImage< unsigned char > &I, vpImage< unsigned char > &Ic, unsigned int gaussianFilterSize, double thresholdCanny, unsigned int apertureSobel)
static double filterYTopBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterYG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void getGaussYPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
static double filterXRightBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterXG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void getGradY(const vpImage< unsigned char > &I, vpImage< double > &dIy)
static double filterYBottomBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static unsigned char filterGaussYPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static void getGaussPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:829
unsigned int getWidth() const
Definition: vpImage.h:246
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
unsigned int getHeight() const
Definition: vpImage.h:188
static double sqr(double x)
Definition: vpMath.h:116
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:154
static vpMatrix conv2(const vpMatrix &M, const vpMatrix &kernel, const std::string &mode="full")
Definition: vpMatrix.cpp:6810
vpMatrix t() const
Definition: vpMatrix.cpp:464