1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 #include "precomp.hpp"
47 CvCalibFilter::CvCalibFilter()
50 etalonType = CV_CALIB_ETALON_USER;
59 memset( points, 0, sizeof(points));
60 memset( undistMap, 0, sizeof(undistMap));
62 memset( latestCounts, 0, sizeof(latestCounts));
63 memset( latestPoints, 0, sizeof(latestPoints));
64 memset( &stereo, 0, sizeof(stereo) );
70 imgSize = cvSize(0,0);
75 memset( rectMap, 0, sizeof(rectMap));
79 CvCalibFilter::~CvCalibFilter()
82 cvFree( &etalonParams );
83 cvFree( &etalonPoints );
84 cvReleaseMat( &grayImg );
85 cvReleaseMat( &tempImg );
86 cvReleaseMat( &undistImg );
87 cvReleaseMemStorage( &storage );
91 bool CvCalibFilter::SetEtalon( CvCalibEtalonType type, double* params,
92 int pointCount, CvPoint2D32f* _points )
98 if (latestPoints != NULL)
100 for( i = 0; i < MAX_CAMERAS; i++ )
101 cvFree( latestPoints + i );
104 if( type == CV_CALIB_ETALON_USER || type != etalonType )
106 if (etalonParams != NULL)
108 cvFree( &etalonParams );
116 case CV_CALIB_ETALON_CHESSBOARD:
117 etalonParamCount = 3;
118 if( !params || cvRound(params[0]) != params[0] || params[0] < 3 ||
119 cvRound(params[1]) != params[1] || params[1] < 3 || params[2] <= 0 )
125 pointCount = cvRound((params[0] - 1)*(params[1] - 1));
128 case CV_CALIB_ETALON_USER:
129 etalonParamCount = 0;
131 if( !_points || pointCount < 4 )
143 if( etalonParamCount > 0 )
145 arrSize = etalonParamCount * sizeof(etalonParams[0]);
146 etalonParams = (double*)cvAlloc( arrSize );
149 arrSize = pointCount * sizeof(etalonPoints[0]);
151 if( etalonPointCount != pointCount )
153 if (etalonPoints != NULL)
155 cvFree( &etalonPoints );
157 etalonPointCount = pointCount;
158 etalonPoints = (CvPoint2D32f*)cvAlloc( arrSize );
163 case CV_CALIB_ETALON_CHESSBOARD:
165 int etalonWidth = cvRound( params[0] ) - 1;
166 int etalonHeight = cvRound( params[1] ) - 1;
169 etalonParams[0] = etalonWidth;
170 etalonParams[1] = etalonHeight;
171 etalonParams[2] = params[2];
173 for( y = 0; y < etalonHeight; y++ )
174 for( x = 0; x < etalonWidth; x++ )
176 etalonPoints[k++] = cvPoint2D32f( (etalonWidth - 1 - x)*params[2],
182 case CV_CALIB_ETALON_USER:
185 memcpy( etalonParams, params, arrSize );
189 memcpy( etalonPoints, _points, arrSize );
203 CvCalibFilter::GetEtalon( int* paramCount, const double** params,
204 int* pointCount, const CvPoint2D32f** _points ) const
207 *paramCount = etalonParamCount;
210 *params = etalonParams;
213 *pointCount = etalonPointCount;
216 *_points = etalonPoints;
222 void CvCalibFilter::SetCameraCount( int count )
226 if( count != cameraCount )
228 for( int i = 0; i < cameraCount; i++ )
230 cvFree( points + i );
231 cvFree( latestPoints + i );
232 cvReleaseMat( &undistMap[i][0] );
233 cvReleaseMat( &undistMap[i][1] );
234 cvReleaseMat( &rectMap[i][0] );
235 cvReleaseMat( &rectMap[i][1] );
238 memset( latestCounts, 0, sizeof(latestCounts) );
245 bool CvCalibFilter::SetFrames( int frames )
253 framesTotal = frames;
258 void CvCalibFilter::Stop( bool calibrate )
261 isCalibrated = false;
263 // deallocate undistortion maps
264 for( i = 0; i < cameraCount; i++ )
266 cvReleaseMat( &undistMap[i][0] );
267 cvReleaseMat( &undistMap[i][1] );
268 cvReleaseMat( &rectMap[i][0] );
269 cvReleaseMat( &rectMap[i][1] );
272 if( calibrate && framesAccepted > 0 )
274 int n = framesAccepted;
275 CvPoint3D32f* buffer =
276 (CvPoint3D32f*)cvAlloc( n * etalonPointCount * sizeof(buffer[0]));
278 float* rotMatr = (float*)cvAlloc( n * 9 * sizeof(rotMatr[0]));
279 float* transVect = (float*)cvAlloc( n * 3 * sizeof(transVect[0]));
280 int* counts = (int*)cvAlloc( n * sizeof(counts[0]));
282 cvInitMatHeader( &mat, 1, sizeof(CvCamera)/sizeof(float), CV_32FC1, 0 );
283 memset( cameraParams, 0, cameraCount * sizeof(cameraParams[0]));
285 for( i = 0; i < framesAccepted; i++ )
287 counts[i] = etalonPointCount;
288 for( j = 0; j < etalonPointCount; j++ )
289 buffer[i * etalonPointCount + j] = cvPoint3D32f( etalonPoints[j].x,
290 etalonPoints[j].y, 0 );
293 for( i = 0; i < cameraCount; i++ )
295 cvCalibrateCamera( framesAccepted, counts,
296 imgSize, points[i], buffer,
297 cameraParams[i].distortion,
298 cameraParams[i].matrix,
299 transVect, rotMatr, 0 );
301 cameraParams[i].imgSize[0] = (float)imgSize.width;
302 cameraParams[i].imgSize[1] = (float)imgSize.height;
304 // cameraParams[i].focalLength[0] = cameraParams[i].matrix[0];
305 // cameraParams[i].focalLength[1] = cameraParams[i].matrix[4];
307 // cameraParams[i].principalPoint[0] = cameraParams[i].matrix[2];
308 // cameraParams[i].principalPoint[1] = cameraParams[i].matrix[5];
310 memcpy( cameraParams[i].rotMatr, rotMatr, 9 * sizeof(rotMatr[0]));
311 memcpy( cameraParams[i].transVect, transVect, 3 * sizeof(transVect[0]));
313 mat.data.ptr = (uchar*)(cameraParams + i);
315 /* check resultant camera parameters: if there are some INF's or NAN's,
316 stop and reset results */
317 if( !cvCheckArr( &mat, CV_CHECK_RANGE | CV_CHECK_QUIET, -10000, 10000 ))
323 isCalibrated = i == cameraCount;
325 {/* calibrate stereo cameras */
326 if( cameraCount == 2 )
328 stereo.camera[0] = &cameraParams[0];
329 stereo.camera[1] = &cameraParams[1];
331 icvStereoCalibration( framesAccepted, counts,
343 cvFree( &transVect );
350 bool CvCalibFilter::FindEtalon( IplImage** imgs )
352 return FindEtalon( (CvMat**)imgs );
356 bool CvCalibFilter::FindEtalon( CvMat** mats )
360 if( !mats || etalonPointCount == 0 )
368 int i, tempPointCount0 = etalonPointCount*2;
370 for( i = 0; i < cameraCount; i++ )
372 if( !latestPoints[i] )
373 latestPoints[i] = (CvPoint2D32f*)
374 cvAlloc( tempPointCount0*2*sizeof(latestPoints[0]));
377 for( i = 0; i < cameraCount; i++ )
380 int tempPointCount = tempPointCount0;
383 if( !CV_IS_MAT(mats[i]) && !CV_IS_IMAGE(mats[i]))
389 size = cvGetSize(mats[i]);
391 if( size.width != imgSize.width || size.height != imgSize.height )
396 if( !grayImg || grayImg->width != imgSize.width ||
397 grayImg->height != imgSize.height )
399 cvReleaseMat( &grayImg );
400 cvReleaseMat( &tempImg );
401 grayImg = cvCreateMat( imgSize.height, imgSize.width, CV_8UC1 );
402 tempImg = cvCreateMat( imgSize.height, imgSize.width, CV_8UC1 );
406 storage = cvCreateMemStorage();
410 case CV_CALIB_ETALON_CHESSBOARD:
411 if( CV_MAT_CN(cvGetElemType(mats[i])) == 1 )
412 cvCopy( mats[i], grayImg );
414 cvCvtColor( mats[i], grayImg, CV_BGR2GRAY );
415 found = cvFindChessBoardCornerGuesses( grayImg, tempImg, storage,
416 cvSize( cvRound(etalonParams[0]),
417 cvRound(etalonParams[1])),
418 latestPoints[i], &tempPointCount ) != 0;
420 cvFindCornerSubPix( grayImg, latestPoints[i], tempPointCount,
421 cvSize(5,5), cvSize(-1,-1),
422 cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,10,0.1));
430 latestCounts[i] = found ? tempPointCount : -tempPointCount;
431 result = result && found;
436 cvClearMemStorage( storage );
442 bool CvCalibFilter::Push( const CvPoint2D32f** pts )
445 int i, newMaxPoints = etalonPointCount*(MAX(framesAccepted,framesTotal) + 1);
447 isCalibrated = false;
451 for( i = 0; i < cameraCount; i++ )
452 if( latestCounts[i] <= 0 )
454 pts = (const CvPoint2D32f**)latestPoints;
457 for( i = 0; i < cameraCount; i++ )
465 if( maxPoints < newMaxPoints )
467 CvPoint2D32f* prev = points[i];
468 cvFree( points + i );
469 points[i] = (CvPoint2D32f*)cvAlloc( newMaxPoints * sizeof(prev[0]));
470 memcpy( points[i], prev, maxPoints * sizeof(prev[0]));
473 memcpy( points[i] + framesAccepted*etalonPointCount, pts[i],
474 etalonPointCount*sizeof(points[0][0]));
477 if( maxPoints < newMaxPoints )
478 maxPoints = newMaxPoints;
480 result = i == cameraCount;
482 if( ++framesAccepted >= framesTotal )
488 bool CvCalibFilter::GetLatestPoints( int idx, CvPoint2D32f** pts,
489 int* count, bool* found )
493 if( (unsigned)idx >= (unsigned)cameraCount ||
494 !pts || !count || !found )
500 n = latestCounts[idx];
504 *pts = latestPoints[idx];
510 void CvCalibFilter::DrawPoints( IplImage** dst )
512 DrawPoints( (CvMat**)dst );
516 void CvCalibFilter::DrawPoints( CvMat** dstarr )
528 for( i = 0; i < cameraCount; i++ )
530 if( dstarr[i] && latestCounts[i] )
532 CvMat dst_stub, *dst;
535 CvPoint2D32f* pts = 0;
537 GetLatestPoints( i, &pts, &count, &found );
539 dst = cvGetMat( dstarr[i], &dst_stub );
541 static const CvScalar line_colors[] =
552 const int colorCount = sizeof(line_colors)/sizeof(line_colors[0]);
554 CvScalar color = line_colors[0];
557 for( j = 0; j < count; j++ )
560 pt.x = cvRound(pts[j].x);
561 pt.y = cvRound(pts[j].y);
565 if( etalonType == CV_CALIB_ETALON_CHESSBOARD )
566 color = line_colors[(j/cvRound(etalonParams[0]))%colorCount];
568 color = CV_RGB(0,255,0);
571 cvLine( dst, prev_pt, pt, color, 1, CV_AA );
574 cvLine( dst, cvPoint( pt.x - r, pt.y - r ),
575 cvPoint( pt.x + r, pt.y + r ), color, 1, CV_AA );
577 cvLine( dst, cvPoint( pt.x - r, pt.y + r),
578 cvPoint( pt.x + r, pt.y - r), color, 1, CV_AA );
580 cvCircle( dst, pt, r+1, color, 1, CV_AA );
590 /* Get total number of frames and already accepted pair of frames */
591 int CvCalibFilter::GetFrameCount( int* total ) const
594 *total = framesTotal;
596 return framesAccepted;
600 /* Get camera parameters for specified camera. If camera is not calibrated
601 the function returns 0 */
602 const CvCamera* CvCalibFilter::GetCameraParams( int idx ) const
604 if( (unsigned)idx >= (unsigned)cameraCount )
610 return isCalibrated ? cameraParams + idx : 0;
614 /* Get camera parameters for specified camera. If camera is not calibrated
615 the function returns 0 */
616 const CvStereoCamera* CvCalibFilter::GetStereoParams() const
618 if( !(isCalibrated && cameraCount == 2) )
628 /* Sets camera parameters for all cameras */
629 bool CvCalibFilter::SetCameraParams( CvCamera* params )
642 arrSize = cameraCount * sizeof(params[0]);
644 cvInitMatHeader( &mat, 1, cameraCount * (arrSize/sizeof(float)),
646 cvCheckArr( &mat, CV_CHECK_RANGE, -10000, 10000 );
648 memcpy( cameraParams, params, arrSize );
655 bool CvCalibFilter::SaveCameraParams( const char* filename )
661 FILE* f = fopen( filename, "w" );
663 if( !f ) return false;
665 fprintf( f, "%d\n\n", cameraCount );
667 for( i = 0; i < cameraCount; i++ )
669 for( j = 0; j < (int)(sizeof(cameraParams[i])/sizeof(float)); j++ )
671 fprintf( f, "%15.10f ", ((float*)(cameraParams + i))[j] );
673 fprintf( f, "\n\n" );
676 /* Save stereo params */
679 for( i = 0; i < 2; i++ )
681 for( j = 0; j < 4; j++ )
683 fprintf(f, "%15.10f ", stereo.quad[i][j].x );
684 fprintf(f, "%15.10f ", stereo.quad[i][j].y );
690 for( i = 0; i < 2; i++ )
692 for( j = 0; j < 9; j++ )
694 fprintf(f, "%15.10lf ", stereo.coeffs[i][j/3][j%3] );
708 bool CvCalibFilter::LoadCameraParams( const char* filename )
712 FILE* f = fopen( filename, "r" );
714 isCalibrated = false;
716 if( !f ) return false;
718 if( fscanf( f, "%d", &d ) != 1 || d <= 0 || d > 10 )
723 for( i = 0; i < cameraCount; i++ )
725 for( j = 0; j < (int)(sizeof(cameraParams[i])/sizeof(float)); j++ )
727 int values_read = fscanf( f, "%f", &((float*)(cameraParams + i))[j] );
728 CV_Assert(values_read == 1);
733 /* Load stereo params */
736 for( i = 0; i < 2; i++ )
738 for( j = 0; j < 4; j++ )
740 int values_read = fscanf(f, "%f ", &(stereo.quad[i][j].x) );
741 CV_Assert(values_read == 1);
742 values_read = fscanf(f, "%f ", &(stereo.quad[i][j].y) );
743 CV_Assert(values_read == 1);
748 for( i = 0; i < 2; i++ )
750 for( j = 0; j < 9; j++ )
752 int values_read = fscanf(f, "%lf ", &(stereo.coeffs[i][j/3][j%3]) );
753 CV_Assert(values_read == 1);
762 stereo.warpSize = cvSize( cvRound(cameraParams[0].imgSize[0]), cvRound(cameraParams[0].imgSize[1]));
770 bool CvCalibFilter::Rectify( IplImage** srcarr, IplImage** dstarr )
772 return Rectify( (CvMat**)srcarr, (CvMat**)dstarr );
775 bool CvCalibFilter::Rectify( CvMat** srcarr, CvMat** dstarr )
779 if( !srcarr || !dstarr )
785 if( isCalibrated && cameraCount == 2 )
787 for( i = 0; i < cameraCount; i++ )
789 if( srcarr[i] && dstarr[i] )
791 IplImage src_stub, *src;
792 IplImage dst_stub, *dst;
794 src = cvGetImage( srcarr[i], &src_stub );
795 dst = cvGetImage( dstarr[i], &dst_stub );
797 if( src->imageData == dst->imageData )
800 undistImg->width != src->width ||
801 undistImg->height != src->height ||
802 CV_MAT_CN(undistImg->type) != src->nChannels )
804 cvReleaseMat( &undistImg );
805 undistImg = cvCreateMat( src->height, src->width,
806 CV_8U + (src->nChannels-1)*8 );
808 cvCopy( src, undistImg );
809 src = cvGetImage( undistImg, &src_stub );
814 if( !rectMap[i][0] || rectMap[i][0]->width != src->width ||
815 rectMap[i][0]->height != src->height )
817 cvReleaseMat( &rectMap[i][0] );
818 cvReleaseMat( &rectMap[i][1] );
819 rectMap[i][0] = cvCreateMat(stereo.warpSize.height,stereo.warpSize.width,CV_32FC1);
820 rectMap[i][1] = cvCreateMat(stereo.warpSize.height,stereo.warpSize.width,CV_32FC1);
821 cvComputePerspectiveMap(stereo.coeffs[i], rectMap[i][0], rectMap[i][1]);
823 cvRemap( src, dst, rectMap[i][0], rectMap[i][1] );
829 for( i = 0; i < cameraCount; i++ )
831 if( srcarr[i] != dstarr[i] )
832 cvCopy( srcarr[i], dstarr[i] );
839 bool CvCalibFilter::Undistort( IplImage** srcarr, IplImage** dstarr )
841 return Undistort( (CvMat**)srcarr, (CvMat**)dstarr );
845 bool CvCalibFilter::Undistort( CvMat** srcarr, CvMat** dstarr )
849 if( !srcarr || !dstarr )
857 for( i = 0; i < cameraCount; i++ )
859 if( srcarr[i] && dstarr[i] )
861 CvMat src_stub, *src;
862 CvMat dst_stub, *dst;
864 src = cvGetMat( srcarr[i], &src_stub );
865 dst = cvGetMat( dstarr[i], &dst_stub );
867 if( src->data.ptr == dst->data.ptr )
869 if( !undistImg || undistImg->width != src->width ||
870 undistImg->height != src->height ||
871 CV_ARE_TYPES_EQ( undistImg, src ))
873 cvReleaseMat( &undistImg );
874 undistImg = cvCreateMat( src->height, src->width, src->type );
877 cvCopy( src, undistImg );
883 CvMat A = cvMat( 3, 3, CV_32FC1, cameraParams[i].matrix );
884 CvMat k = cvMat( 1, 4, CV_32FC1, cameraParams[i].distortion );
886 if( !undistMap[i][0] || undistMap[i][0]->width != src->width ||
887 undistMap[i][0]->height != src->height )
889 cvReleaseMat( &undistMap[i][0] );
890 cvReleaseMat( &undistMap[i][1] );
891 undistMap[i][0] = cvCreateMat( src->height, src->width, CV_32FC1 );
892 undistMap[i][1] = cvCreateMat( src->height, src->width, CV_32FC1 );
893 cvInitUndistortMap( &A, &k, undistMap[i][0], undistMap[i][1] );
896 cvRemap( src, dst, undistMap[i][0], undistMap[i][1] );
898 cvUndistort2( src, dst, &A, &k );
906 for( i = 0; i < cameraCount; i++ )
908 if( srcarr[i] != dstarr[i] )
909 cvCopy( srcarr[i], dstarr[i] );