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 #pragma warning( disable: 4201 4710 )
47 #include <cvstreams.h>
53 #include "iCalibFilter.h"
54 #include "CalibFilterprop.h"
55 #include "CalibFilter.h"
56 #include "CalibFilteruids.h"
60 #include "Calib3DWindow.h"
64 const AMOVIESETUP_MEDIATYPE sudPinTypes =
66 &MEDIATYPE_Video, // Major type
67 &MEDIASUBTYPE_NULL // Minor type
70 const AMOVIESETUP_PIN psudPins[] =
73 L"Input", // String pin name
74 FALSE, // Is it rendered
75 FALSE, // Is it an output
76 FALSE, // Allowed none
77 FALSE, // Allowed many
78 &CLSID_NULL, // Connects to filter
79 L"Output", // Connects to pin
81 &sudPinTypes }, // The pin details
82 { L"Output", // String pin name
83 FALSE, // Is it rendered
84 TRUE, // Is it an output
85 FALSE, // Allowed none
86 FALSE, // Allowed many
87 &CLSID_NULL, // Connects to filter
88 L"Input", // Connects to pin
90 &sudPinTypes // The pin details
95 const AMOVIESETUP_FILTER sudCCalibFilter =
97 &CLSID_CCalibFilter, // Filter CLSID
98 L"CalibFilter", // Filter name
99 MERIT_DO_NOT_USE, // Its merit
101 psudPins // Pin details
105 // List of class IDs and creator functions for the class factory. This
106 // provides the link between the OLE entry point in the DLL and an object
107 // being created. The class factory will call the static CreateInstance
109 CFactoryTemplate g_Templates[2] = {
112 , &CLSID_CCalibFilter
113 , CCalibFilter::CreateInstance
117 { L"CalibFilter Property Page"
118 , &CLSID_CCalibFilterPropertyPage
119 , CCalibFilterProperties::CreateInstance }
121 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
123 static DWORD WINAPI _3DWindowThreadProc( void* window );
126 CCalibFilter::CCalibFilter(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
127 CTransInPlaceFilter(tszName, punk, CLSID_CCalibFilter,phr),
128 CPersistStream(punk, phr)
130 m_initial_params.etalon_type = CalibEtalon_ChessBoard;
132 m_initial_params.etalon_params[0] = 6;
133 m_initial_params.etalon_params[1] = 8;
134 m_initial_params.etalon_params[2] = 3;
135 m_initial_params.etalon_params_count = 3;
137 m_initial_params.show_feature_points_flag = 1;
138 m_initial_params.frame_interval = 1000;
139 m_initial_params.frames_to_collect = 10;
140 m_initial_params.frames_collected = 0;
141 m_initial_params.frames_passed = 0;
142 m_initial_params.calib_state = CalibState_Initial;
143 m_initial_params.last_frame_time = -1e6f;
145 m_initial_params.enable_undistortion = 0;
146 m_initial_params.show_3d_window = 1;
148 m_params = m_initial_params;
156 m_gray_img = cvCreateImage( cvSize(1,1), IPL_DEPTH_8U, 1 );
157 m_thresh_img = cvCreateImage( cvSize(1,1), IPL_DEPTH_8U, 1 );
158 m_rgb_img = cvCreateImage( cvSize(1,1), IPL_DEPTH_8U, 3 );
159 m_undist_img = cvCreateImage( cvSize(1,1), IPL_DEPTH_8U, 3 );
161 memset( &m_undistort_params, 0, sizeof(m_undistort_params));
162 m_undistort_data = 0;
167 m_thread = CreateThread( 0, 0, _3DWindowThreadProc, &m_window3D, 0, &threadId );
170 CvSize CCalibFilter::GetEtalonSize()
172 return cvSize( cvRound(m_params.etalon_params[0]) - 1,
173 cvRound(m_params.etalon_params[1]) - 1 );
176 /* a whole life of 3D window in the single routine */
177 DWORD WINAPI _3DWindowThreadProc( void* window )
179 CCalib3DWindow* window3D = new CCalib3DWindow;
180 *((CCalib3DWindow**)window) = window3D;
184 // Main message loop:
185 while( GetMessage(&msg, NULL, 0, 0))
187 TranslateMessage(&msg);
188 DispatchMessage(&msg);
191 *((CCalib3DWindow**)window) = 0;
196 CCalibFilter::~CCalibFilter()
198 SendMessage( m_window3D->m_hwnd, WM_CLOSE, 0, 0 );
199 WaitForSingleObject( m_thread, 100 );
200 CloseHandle( m_thread );
205 CUnknown * WINAPI CCalibFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
207 CCalibFilter *pNewObject = new CCalibFilter(NAME("CalibFilter"), punk, phr);
208 if( !pNewObject ) *phr = E_OUTOFMEMORY;
212 /* NonDelegatingQueryInterface */
213 STDMETHODIMP CCalibFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
215 CheckPointer(ppv,E_POINTER);
217 if( riid == IID_ICalibFilter )
218 return GetInterface((ICalibFilter *) this, ppv);
219 else if( riid == IID_ISpecifyPropertyPages )
220 return GetInterface((ISpecifyPropertyPages *) this, ppv);
221 else if( riid == IID_IPersistStream )
222 return GetInterface((IPersistStream *) this, ppv);
224 return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
228 /* CheckReallocBuffers */
229 void CCalibFilter::CheckReallocBuffers( IplImage* rgb_img )
231 CvSize etalon_size = GetEtalonSize();
232 int etalon_points = etalon_size.width*etalon_size.height;
234 if( m_gray_img->imageData == 0 ||
235 m_gray_img->width != rgb_img->width ||
236 m_gray_img->height != rgb_img->height )
238 cvReleaseImageData( m_gray_img );
239 cvInitImageHeader( m_gray_img, cvSize(rgb_img->width, rgb_img->height),
240 IPL_DEPTH_8U, 1, IPL_ORIGIN_TL, 4 );
241 cvCreateImageData( m_gray_img );
243 cvReleaseImageData( m_thresh_img );
244 cvInitImageHeader( m_thresh_img, cvSize(rgb_img->width, rgb_img->height),
245 IPL_DEPTH_8U, 1, IPL_ORIGIN_TL, 4 );
246 cvCreateImageData( m_thresh_img );
248 cvReleaseImageData( m_undist_img );
249 cvInitImageHeader( m_undist_img, cvSize(rgb_img->width, rgb_img->height),
250 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
252 cvCreateImageData( m_undist_img );
255 if( etalon_points * m_params.frames_to_collect > m_max_points )
257 int new_max_points = etalon_points * (m_params.frames_to_collect + 1) + 128;
258 CvPoint2D32f* imagePoints = (CvPoint2D32f*)malloc( new_max_points *
259 sizeof(CvPoint2D32f));
261 memcpy( imagePoints, m_imagePoints, m_max_points * sizeof(CvPoint2D32f));
263 free( m_imagePoints );
264 free( m_objectPoints );
265 free( m_transVects );
268 m_imagePoints = imagePoints;
269 m_objectPoints = (CvPoint3D32f*)malloc( new_max_points * sizeof(CvPoint3D32f) );
270 m_transVects = (CvPoint3D32f*)malloc( new_max_points * sizeof(CvPoint2D32f) );
271 m_rotMatrs = (float*)malloc( new_max_points * 9 * sizeof(float));
272 m_numsPoints = (int*)calloc( m_params.frames_to_collect,sizeof(int));
274 m_max_points = new_max_points;
279 void CCalibFilter::DrawEtalon( IplImage* rgb_img, CvPoint2D32f* corners,
280 int corner_count, CvSize etalon_size,
286 if( corner_count == etalon_size.width * etalon_size.height && draw_ordered )
289 CvPoint prev_pt = { 0, 0};
290 const int line_max = 7;
291 CvScalar line_colors[line_max];
293 line_colors[0] = CV_RGB(255,0,0);
294 line_colors[1] = CV_RGB(255,128,0);
295 line_colors[2] = CV_RGB(200,200,0);
296 line_colors[3] = CV_RGB(0,255,0);
297 line_colors[4] = CV_RGB(0,200,200);
298 line_colors[5] = CV_RGB(0,0,255);
299 line_colors[6] = CV_RGB(255,0,255);
301 for( y = 0, i = 0; y < etalon_size.height; y++ )
303 CvScalar color = line_colors[y % line_max];
304 for( x = 0; x < etalon_size.width; x++, i++ )
307 pt.x = cvRound(corners[i].x);
308 pt.y = cvRound(corners[i].y);
311 cvLine( rgb_img, prev_pt, pt, color, 1, CV_AA, 0 );
313 cvLine( rgb_img, cvPoint( pt.x - r, pt.y - r ),
314 cvPoint( pt.x + r, pt.y + r ), color, 1, CV_AA, 0 );
315 cvLine( rgb_img, cvPoint( pt.x - r, pt.y + r),
316 cvPoint( pt.x + r, pt.y - r), color, 1, CV_AA, 0 );
317 cvCircle( rgb_img, pt, r+1, color, 1, CV_AA, 0 );
324 CvScalar color = CV_RGB(255,0,0);
325 for( i = 0; i < corner_count; i++ )
328 pt.x = cvRound(corners[i].x);
329 pt.y = cvRound(corners[i].y);
330 cvLine( rgb_img, cvPoint( pt.x - r, pt.y - r ),
331 cvPoint( pt.x + r, pt.y + r ), color, 1, CV_AA, 0 );
332 cvLine( rgb_img, cvPoint( pt.x - r, pt.y + r),
333 cvPoint( pt.x + r, pt.y - r), color, 1, CV_AA, 0 );
334 cvCircle( rgb_img, pt, r+1, color, 1, CV_AA, 0 );
340 void CCalibFilter::FillEtalonObjPoints( CvPoint3D32f* obj_points,
346 for( y = 0, i = 0; y < etalon_size.height; y++ )
348 for( x = 0; x < etalon_size.width; x++, i++ )
350 obj_points[i].x = square_size * x;
351 obj_points[i].y = square_size * y;
359 void MirrorPoints( CvPoint2D32f* points, int frames, CvSize etalon_size, CvSize imgSize )
362 for( i = 0; i < frames; i++ )
364 int start = i*etalon_size.width*etalon_size.height;
366 for( j = 0; j < etalon_size.height; j++ )
368 for( k = 0; k < etalon_size.width/2; k++ )
371 CV_SWAP( points[start + j*etalon_size.width + k],
372 points[start + (j+1)*etalon_size.width - k - 1], temp );
375 for( k = 0; k < etalon_size.width; k++ )
377 points[start + j*etalon_size.width + k].y = imgSize.height -
378 points[start + j*etalon_size.width + k].y;
384 void MirrorPoints( CvPoint2D32f*, int, CvSize )
390 void CCalibFilter::ProcessFrame( IplImage* rgb_img, double frame_time )
392 bool find_corners = m_initial_params.show_3d_window ||
393 m_params.calib_state == CalibState_CalibrationProcess;
394 bool chess_found = false;
395 CvSize etalon_size = GetEtalonSize();
396 int etalon_points = etalon_size.width * etalon_size.height;
398 cvGetImageRawData(rgb_img, 0, 0, &size);
399 CheckReallocBuffers( rgb_img );
401 CvPoint2D32f* pt_ptr = m_imagePoints + m_params.frames_collected * etalon_points;
405 /* Begin of find etalon points */
406 int count = etalon_points;// + 10;
408 cvCvtColor( rgb_img, m_gray_img, CV_BGR2GRAY );
410 /*********************************************************/
411 ////////////// FIND CHECKERBOARD CORNERS //////////////
412 ///////////////////////////////////////////////////////////
414 chess_found = cvFindChessBoardCornerGuesses( m_gray_img, m_thresh_img, 0,
415 etalon_size, pt_ptr, &count ) != 0;
419 m_gray_img, pt_ptr, count, cvSize(5,5), cvSize(-1,-1),
420 cvTermCriteria( CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10, 0.01f ));
423 DrawEtalon( rgb_img, pt_ptr, count, etalon_size, chess_found );
426 if( m_params.calib_state == CalibState_Calibrated )
428 /* Calibration finished */
429 if( m_initial_params.show_3d_window && chess_found )
430 {/* We must show 3D etalon and compute extrinsic parameters */
432 //float Jacobian[27];
434 /* Collect object points */
435 FillEtalonObjPoints( m_objectPoints, etalon_size,
436 m_params.etalon_params[2] );
438 MirrorPoints( pt_ptr, 1, etalon_size, size );
440 cvFindExtrinsicCameraParams( etalon_points,
444 m_camera.focalLength,
445 (CvPoint2D32f&)m_camera.principalPoint,
448 m_camera.transVect );
451 CvMat rmat = cvMat( 3, 3, CV_32FC1, m_camera.rotMatr );
452 CvMat rvec = cvMat( 3, 1, CV_32FC1, rotVect );
453 //CvMat jacob = cvMat( 3, 9, CV_32FC1, Jacobian );
455 /* Calc rotation matrix by via Rodrigues Transform */
456 cvRodrigues( &rmat, &rvec, 0, CV_RODRIGUES_V2M );
461 if( m_initial_params.enable_undistortion )
463 /* Apply undistortion */
464 if( memcmp( m_camera.matrix, m_undistort_params.matrix, sizeof(m_camera.matrix)) != 0 ||
465 memcmp( m_camera.distortion, m_undistort_params.distortion, sizeof(m_camera.distortion)) != 0 )
467 memcpy( &m_undistort_params, &m_camera, sizeof(m_camera));
469 if( !m_undistort_data || m_undistort_data->width != rgb_img->width ||
470 m_undistort_data->height != rgb_img->height )
472 cvReleaseImage( &m_undistort_data );
474 m_undistort_data = cvCreateImage( cvSize( rgb_img->width, rgb_img->height ),
479 CvMat a = cvMat( 3, 3, CV_32F, m_undistort_params.matrix );
480 CvMat dist = cvMat( 1, 4, CV_32F, m_undistort_params.distortion );
481 cvUndistort2( rgb_img, m_undist_img, &a, &dist );
483 cvCopyImage(m_undist_img, rgb_img);
485 } /* Check if Calibration not finished and the etalon is recognized */
487 if( m_params.calib_state == CalibState_CalibrationProcess && chess_found &&
488 frame_time >= m_params.last_frame_time + m_params.frame_interval )
490 m_params.last_frame_time = frame_time;
491 m_params.frames_collected++;
493 cvXorS( rgb_img, cvScalarAll( 255 ), rgb_img );
495 if( m_params.frames_collected == m_params.frames_to_collect )
497 /* all frames are collected. Now will calibrate */
498 CalculateCameraParams( size );
499 m_params.calib_state = CalibState_Calibrated;
503 }/* End calibration */
504 } /* Else point accumulation */
509 void CCalibFilter::CalculateCameraParams( CvSize size )
512 CvSize etalon_size = GetEtalonSize();
513 int etalon_points = etalon_size.width * etalon_size.height;
515 FillEtalonObjPoints( m_objectPoints, etalon_size,
516 m_params.etalon_params[2] );
518 for( frame = 1; frame < m_params.frames_collected; frame++ )
520 memcpy( m_objectPoints + etalon_points*frame, m_objectPoints,
521 etalon_points * sizeof(m_objectPoints[0]));
524 /* Set etalon points counters */
525 for( frame = 0; frame < m_params.frames_collected; frame++ )
527 m_numsPoints[frame] = etalon_points;
530 MirrorPoints( m_imagePoints, m_params.frames_collected, etalon_size, size );
532 /* Calirate camera */
533 cvCalibrateCamera( m_params.frames_collected, m_numsPoints,
534 size, m_imagePoints, m_objectPoints,
535 m_camera.distortion, m_camera.matrix,
536 (float*)m_transVects, m_rotMatrs, 0 );
538 /* Copy some camera parameters */
539 m_camera.focalLength[0] = m_camera.matrix[0];
540 m_camera.focalLength[1] = m_camera.matrix[4];
542 m_camera.principalPoint[0] = m_camera.matrix[2];
543 m_camera.principalPoint[1] = m_camera.matrix[5];
547 double CCalibFilter::GetFrameTime( IMediaSample* pSample )
549 double result = GetTickCount();
555 HRESULT CCalibFilter::Transform(IMediaSample *pSample)
557 CalibState state = m_params.calib_state;
561 case CalibState_Initial:
564 CAutoLock cAutoLock(&m_CCalibFilterLock);
565 m_params = m_initial_params;
566 m_params.calib_state = CalibState_NotCalibrated;
568 case CalibState_NotCalibrated:
569 case CalibState_Calibrated:
570 case CalibState_CalibrationProcess:
572 AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
573 VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
576 CvSize size = cvSize( pvi->bmiHeader.biWidth, abs(pvi->bmiHeader.biHeight) );
577 int step = (size.width*3 + 3) & -4;
578 pSample->GetPointer(&rgb_data);
579 assert( pvi->bmiHeader.biBitCount == 24 );
581 cvInitImageHeader( m_rgb_img, size, IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
582 cvSetImageData( m_rgb_img, rgb_data, step );
584 ProcessFrame( m_rgb_img, GetFrameTime( pSample ));
585 ++m_params.frames_passed;
597 HRESULT CCalibFilter::CheckInputType(const CMediaType *mtIn)
599 // Check this is a VIDEOINFO type
600 if( *mtIn->FormatType() != FORMAT_VideoInfo )
605 if( !IsEqualGUID(*mtIn->Subtype(), MEDIASUBTYPE_RGB24 ))
615 HRESULT CCalibFilter::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
618 if (FAILED(hr = CheckInputType(mtIn))) return hr;
620 // format must be a VIDEOINFOHEADER
621 if (*mtOut->FormatType() != FORMAT_VideoInfo) return E_INVALIDARG;
623 // formats must be big enough
624 if (mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
625 mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
628 VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
629 VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
631 if( pInput->bmiHeader.biBitCount != 24 )
636 if (memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0)
643 /* DecideBufferSize */
644 HRESULT CCalibFilter::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
646 if( !m_pInput->IsConnected()) return E_UNEXPECTED;
655 HRESULT CCalibFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
657 if( !m_pInput->IsConnected()) return E_UNEXPECTED;
658 if( iPosition < 0 ) return E_INVALIDARG;
660 /* Do we have more items to offer */
661 if( iPosition > 0 ) return VFW_S_NO_MORE_ITEMS;
663 *pMediaType = m_pInput->CurrentMediaType();
668 /****************************************************************************************\
669 * Interface methods *
670 \****************************************************************************************/
672 STDMETHODIMP CCalibFilter::get_EtalonParams(
673 CalibEtalonType* etalon_type,
674 float* etalon_params,
675 long* etalon_params_count)
677 int params_to_copy = m_initial_params.etalon_params_count;
678 *etalon_type = m_initial_params.etalon_type;
682 if( params_to_copy > *etalon_params_count )
683 params_to_copy = *etalon_params_count;
685 memcpy( etalon_params, m_initial_params.etalon_params,
686 params_to_copy*sizeof(float) );
687 *etalon_params_count = params_to_copy;
694 STDMETHODIMP CCalibFilter::set_EtalonParams(
695 CalibEtalonType etalon_type,
696 float* etalon_params,
697 long etalon_params_count)
699 CAutoLock cAutoLock(&m_CCalibFilterLock);
701 if( etalon_type != CalibEtalon_ChessBoard ||
702 etalon_params_count != 3 ) return E_INVALIDARG;
704 m_initial_params.etalon_type = etalon_type;
705 m_initial_params.etalon_params_count = etalon_params_count;
706 memcpy( m_initial_params.etalon_params, etalon_params,
707 etalon_params_count*sizeof(float) );
714 STDMETHODIMP CCalibFilter::get_FrameInterval( long* count )
716 *count = m_params.frame_interval;
720 STDMETHODIMP CCalibFilter::set_FrameInterval( long count )
722 CAutoLock cAutoLock(&m_CCalibFilterLock);
723 if( count < 1 ) count = 1;
724 m_initial_params.frame_interval = m_params.frame_interval = count;
732 STDMETHODIMP CCalibFilter::get_FramesToCollect(
735 *frames = m_params.frames_to_collect;
739 /************************************/
741 STDMETHODIMP CCalibFilter::get_EnableUndistortion(
744 *enable = m_params.enable_undistortion;
748 STDMETHODIMP CCalibFilter::set_EnableUndistortion(
751 CAutoLock cAutoLock(&m_CCalibFilterLock);
753 m_initial_params.enable_undistortion = m_params.enable_undistortion = enable;
761 STDMETHODIMP CCalibFilter::get_Show3DWindow(
764 *enable = m_params.show_3d_window;
768 STDMETHODIMP CCalibFilter::set_Show3DWindow(
771 CAutoLock cAutoLock(&m_CCalibFilterLock);
773 m_initial_params.show_3d_window = m_params.show_3d_window = enable;
775 m_window3D->Show( enable != 0 );
782 STDMETHODIMP CCalibFilter::SaveCameraParams()
784 if( m_params.calib_state == CalibState_Calibrated)
787 char fileName[MAX_PATH] = "";
789 lpofn.lStructSize = sizeof(OPENFILENAME);
792 lpofn.lpstrFilter = "Camera parameters (*.txt)\0*.txt\0";
793 lpofn.lpstrCustomFilter = 0;
794 lpofn.nMaxCustFilter = 0;
795 lpofn.nFilterIndex = 1;
796 lpofn.lpstrFile = fileName;
797 lpofn.nMaxFile = MAX_PATH;
798 lpofn.lpstrFileTitle = 0;
799 lpofn.nMaxFileTitle = 0;
800 lpofn.lpstrInitialDir = 0;
801 lpofn.lpstrTitle = 0;
802 lpofn.Flags = OFN_OVERWRITEPROMPT;
803 lpofn.nFileOffset = 0;
804 lpofn.nFileExtension = 0;
805 lpofn.lpstrDefExt = "txt";
808 lpofn.lpTemplateName = 0;
810 GetSaveFileName(&lpofn);
811 if( strlen(fileName) != 0)
813 FILE *file = fopen(fileName,"wt");
817 fprintf(file,"Camera Matrix:\n");
818 for( i = 0; i < 3; i++ )
820 for( j = 0; j < 3; j++ )
822 fprintf( file,"M[%d.%d]=%20.7f", i, j, m_camera.matrix[i*3+j]);
827 fprintf(file,"\n\nDistortion:\n");
828 for( i = 0; i < 4; i++ )
829 fprintf(file,"D[%d]=%f\n", i, m_camera.distortion[i]);
835 MessageBox(0,"Can't open file","Save camera parameters",MB_OK|MB_ICONERROR);
841 MessageBox(0,"Camera was not calibrated","Save camera parameters",MB_OK);
847 STDMETHODIMP CCalibFilter::LoadCameraParams()
850 #define BUF_SIZE 10000
851 char buffer[BUF_SIZE + 100];
852 char fileName[MAX_PATH] = "";
854 lpofn.lStructSize = sizeof(OPENFILENAME);
857 lpofn.lpstrFilter = "Camera parameters (*.txt)\0*.txt\0";
858 lpofn.lpstrCustomFilter = 0;
859 lpofn.nMaxCustFilter = 0;
860 lpofn.nFilterIndex = 1;
861 lpofn.lpstrFile = fileName;
862 lpofn.nMaxFile = MAX_PATH;
863 lpofn.lpstrFileTitle = 0;
864 lpofn.nMaxFileTitle = 0;
865 lpofn.lpstrInitialDir = 0;
866 lpofn.lpstrTitle = 0;
867 lpofn.Flags = OFN_FILEMUSTEXIST;
868 lpofn.nFileOffset = 0;
869 lpofn.nFileExtension = 0;
870 lpofn.lpstrDefExt = "txt";
873 lpofn.lpTemplateName = 0;
875 GetOpenFileName(&lpofn);
877 if( strlen(fileName) != 0)
879 FILE *file = fopen(fileName,"rb");
884 float cameraMatrix[9];
887 int sz = fread( buffer, 1, BUF_SIZE, file );
892 for( k = 0; k < 9; k++ )
894 ptr = strstr( ptr, "M[" );
899 if( sscanf( ptr, "%d%*[.,]%d%n", &i, &j, &s ) == 2 && i == k/3 && j == k%3 )
902 ptr = strstr( ptr, "=" );
907 if( sscanf( ptr, "%f%n", cameraMatrix + k, &s ) == 1 )
916 /* else report a bug */
917 MessageBox(0,"Invalid file format","Load camera parameters",MB_OK|MB_ICONERROR);
921 /* read distortion */
922 for( k = 0; k < 4; k++ )
924 ptr = strstr( ptr, "D[" );
929 if( sscanf( ptr, "%d%n", &i, &s ) == 1 && i == k )
932 ptr = strstr( ptr, "=" );
937 if( sscanf( ptr, "%f%n", distortion + k, &s ) == 1 )
946 /* else report a bug */
947 MessageBox(0,"Invalid file format","Load camera parameters",MB_OK|MB_ICONERROR);
951 memcpy( m_camera.matrix, cameraMatrix, sizeof( cameraMatrix ));
952 memcpy( m_camera.distortion, distortion, sizeof( distortion ));
954 m_camera.focalLength[0] = m_camera.matrix[0];
955 m_camera.focalLength[1] = m_camera.matrix[4];
957 m_camera.principalPoint[0] = m_camera.matrix[2];
958 m_camera.principalPoint[1] = m_camera.matrix[5];
960 m_params.calib_state = CalibState_Calibrated;
966 MessageBox(0,"Can't open file","Load camera parameters",MB_OK|MB_ICONERROR);
975 //////////////////////////////////////
976 //////////////////////////////////////
977 //////////////////////////////////////
979 STDMETHODIMP CCalibFilter::set_FramesToCollect(
982 CAutoLock cAutoLock(&m_CCalibFilterLock);
984 m_initial_params.frames_to_collect = m_params.frames_to_collect = frames;
990 STDMETHODIMP CCalibFilter::StartCalibrate()
992 CAutoLock cAutoLock(&m_CCalibFilterLock);
994 m_params = m_initial_params;
995 m_params.calib_state = CalibState_CalibrationProcess;
996 m_params.frames_collected = 0;
1001 STDMETHODIMP CCalibFilter::GetCameraParams( CvCameraParams* camera )
1003 if( m_params.calib_state != CalibState_Calibrated ) return E_PENDING;
1010 STDMETHODIMP CCalibFilter::GetState(
1011 CalibState* calib_state,
1012 long* frames_collected,
1013 long* frames_passed,
1014 double* last_frame_time)
1016 *calib_state = m_params.calib_state;
1017 *frames_collected = m_params.frames_collected;
1018 *frames_passed = m_params.frames_passed;
1019 *last_frame_time = m_params.last_frame_time;
1025 STDMETHODIMP CCalibFilter::GetPages(CAUUID *pPages)
1028 pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
1029 if( !pPages->pElems ) return E_OUTOFMEMORY;
1030 *(pPages->pElems) = CLSID_CCalibFilterPropertyPage;
1034 STDMETHODIMP CCalibFilter::Update3DWindow()
1036 CvSize etalon_size = cvSize( (int)m_params.etalon_params[0],
1037 (int)m_params.etalon_params[1] );
1038 float square_size = m_params.etalon_params[2];
1040 m_window3D->SetParams( &m_camera, etalon_size, square_size );
1045 // IPersistStream implementation
1046 STDMETHODIMP CCalibFilter::GetClassID( CLSID *pClsID )
1048 return CBaseFilter::GetClassID( pClsID );
1052 DWORD CCalibFilter::GetSoftwareVersion()
1057 int CCalibFilter::SizeMax()
1063 #define WRITEOUT(var) hr = pStream->Write(&var, sizeof(var), NULL); \
1064 if (FAILED(hr)) return hr;
1066 #define READIN(var) hr = pStream->Read(&var, sizeof(var), NULL); \
1067 if (FAILED(hr)) return hr;
1069 HRESULT CCalibFilter::ReadFromStream( IStream* pStream )
1072 READIN( m_initial_params );
1074 m_params = m_initial_params;
1076 m_params.calib_state = m_params.calib_state == CalibState_Calibrated ?
1077 CalibState_Calibrated : CalibState_NotCalibrated;
1079 if( m_params.calib_state == CalibState_Calibrated )
1086 HRESULT CCalibFilter::WriteToStream( IStream* pStream )
1089 m_initial_params.calib_state = m_params.calib_state;
1090 WRITEOUT( m_initial_params );
1092 if( m_params.calib_state == CalibState_Calibrated )
1094 WRITEOUT( m_camera );
1097 /*SetDirty(FALSE);*/
1103 STDAPI DllRegisterServer()
1105 return AMovieDllRegisterServer2( TRUE );
1108 STDAPI DllUnregisterServer()
1110 return AMovieDllRegisterServer2( FALSE );