00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkOpenCVVideoSource.h"
00019 #include <iostream>
00020 #include <algorithm>
00021
00022 mitk::OpenCVVideoSource::OpenCVVideoSource()
00023 : m_VideoCapture(0),
00024 m_CurrentImage(0),
00025 m_CurrentVideoTexture(0),
00026 m_PauseImage(0),
00027 m_CapturePaused(false),
00028 m_GrabbingDeviceNumber(-1),
00029 m_RepeatVideo(false),
00030 m_UseCVCAMLib(false),
00031 m_UndistortImage(false)
00032 {
00033 }
00034
00035 mitk::OpenCVVideoSource::~OpenCVVideoSource()
00036 {
00037 this->Reset();
00038 }
00039
00040 void mitk::OpenCVVideoSource::SetVideoFileInput(const char * filename, bool repeatVideo, bool )
00041 {
00042 this->Reset();
00043 m_VideoFileName = filename;
00044
00045 m_VideoCapture = cvCaptureFromFile(filename);
00046 if(!m_VideoCapture)
00047 MITK_WARN << "Error in initializing video file input!";
00048
00049 m_RepeatVideo = repeatVideo;
00050
00051 this->Modified();
00052
00053 }
00054 void mitk::OpenCVVideoSource::SetVideoCameraInput(int cameraindex, bool )
00055 {
00056 this->Reset();
00057
00058 m_GrabbingDeviceNumber = cameraindex;
00059 m_VideoCapture = cvCaptureFromCAM(m_GrabbingDeviceNumber);
00060 if(!m_VideoCapture)
00061 MITK_ERROR << "Error in initializing CVHighGUI video camera!"<< std::endl;
00062
00063 this->Modified();
00064 }
00065
00066 double mitk::OpenCVVideoSource::GetVideoCaptureProperty(int property_id)
00067 {
00068 return cvGetCaptureProperty(m_VideoCapture, property_id);
00069 }
00070
00071 int mitk::OpenCVVideoSource::SetVideoCaptureProperty(int property_id, double value)
00072 {
00073 return cvSetCaptureProperty(m_VideoCapture, property_id, value);
00074 }
00075
00076
00077 unsigned char* mitk::OpenCVVideoSource::GetVideoTexture()
00078 {
00079 FetchFrame();
00080
00081 if (m_RotationEnabled)
00082 {
00083
00084 IplImage * tmpImage = m_CurrentImage;
00085
00086
00087 m_CurrentImage = this->RotateImage(m_CurrentImage);
00088
00089
00090 cvReleaseImage(&tmpImage);
00091 }
00092
00093
00094 this->UpdateVideoTexture();
00095 return this->m_CurrentVideoTexture;
00096 this->Modified();
00097 }
00098
00099
00100
00101
00102
00103 const IplImage * mitk::OpenCVVideoSource::GetImage()
00104 {
00105 return m_CurrentImage;
00106 }
00107
00108 const IplImage * mitk::OpenCVVideoSource::GetCurrentFrame()
00109 {
00110 return m_CurrentImage;
00111 }
00112
00113 void mitk::OpenCVVideoSource::GetCurrentFrameAsOpenCVImage(IplImage * image)
00114 {
00115 if(m_CurrentImage)
00116 {
00117 if(image)
00118 {
00119 image->origin = m_CurrentImage->origin;
00120 memcpy(image->imageData,m_CurrentImage->imageData,m_CurrentImage->width*m_CurrentImage->height*m_CurrentImage->nChannels);
00121 }
00122 }
00123 }
00124
00125 void mitk::OpenCVVideoSource::FetchFrame()
00126 {
00127 if(m_CapturingInProcess)
00128 {
00129 if(m_VideoCapture)
00130 {
00131 if(!m_CapturePaused)
00132 {
00133
00134 m_CurrentImage = cvQueryFrame(m_VideoCapture);
00135
00136 ++m_FrameCount;
00137 }
00138
00139 if(m_CurrentImage == NULL)
00140 {
00141 double framePos = this->GetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO);
00142 MITK_DEBUG << "End of video file found. framePos: " << framePos;
00143 if(m_RepeatVideo && framePos >= 0.99)
00144 {
00145 MITK_DEBUG << "Restarting video file playback.";
00146 this->SetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO, 0);
00147 m_CurrentImage = cvQueryFrame(m_VideoCapture);
00148 }
00149 }
00150 if(m_CaptureWidth == 0 || m_CaptureHeight == 0)
00151 {
00152 MITK_DEBUG << "Trying to set m_CaptureWidth & m_CaptureHeight.";
00153 m_CaptureWidth = m_CurrentImage->width;
00154 m_CaptureHeight = m_CurrentImage->height;
00155 std::cout << "frame width: " << m_CaptureWidth << ", height: " << m_CaptureHeight << std::endl;
00156 m_CurrentImage->origin = 0;
00157 }
00158 }
00159 }
00160 }
00161
00162 void mitk::OpenCVVideoSource::UpdateVideoTexture()
00163 {
00164 if(!m_CurrentImage)
00165 return;
00166
00167 if(m_CurrentVideoTexture == NULL)
00168 m_CurrentVideoTexture = new unsigned char[m_CaptureWidth*m_CaptureHeight*3];
00169
00170
00171 if(m_UndistortImage && !m_CapturePaused)
00172 m_UndistortCameraImage->UndistortImageFast(m_CurrentImage, 0);
00173
00174 int width = m_CurrentImage->width;
00175 int height = m_CurrentImage->height;
00176 int widthStep = m_CurrentImage->widthStep;
00177 int nChannels = m_CurrentImage->nChannels;
00178 unsigned char* tex = m_CurrentVideoTexture;
00179 char* data = m_CurrentImage->imageData;
00180 char* currentData = m_CurrentImage->imageData;
00181
00182 int hIndex=0;
00183 int wIndex=0;
00184 int iout,jout;
00185
00186 for(int i=0;i<width*height*3;i+=3,++wIndex)
00187 {
00188 if(wIndex >= width)
00189 {
00190 wIndex=0;
00191 hIndex++;
00192 }
00193
00194
00195 iout = -hIndex+height-1;
00196 jout = wIndex;
00197
00198 currentData = data + iout*widthStep;
00199
00200 tex[i+2] = currentData[jout*nChannels + 0];
00201 tex[i+1] = currentData[jout*nChannels + 1];
00202 tex[i] = currentData[jout*nChannels + 2];
00203 }
00204
00205 }
00206
00207 void mitk::OpenCVVideoSource::StartCapturing()
00208 {
00209 if(m_VideoCapture != NULL)
00210 m_CapturingInProcess = true;
00211 else
00212 m_CapturingInProcess = false;
00213 }
00214
00215 void mitk::OpenCVVideoSource::StopCapturing()
00216 {
00217 m_CapturingInProcess = false;
00218 }
00219
00220 bool mitk::OpenCVVideoSource::OnlineImageUndistortionEnabled() const
00221 {
00222 return m_UndistortCameraImage;
00223 }
00224
00225 void mitk::OpenCVVideoSource::PauseCapturing()
00226 {
00227 m_CapturePaused = !m_CapturePaused;
00228
00229 if(m_CapturePaused)
00230 {
00231 m_PauseImage = cvCloneImage(m_CurrentImage);
00232
00233
00234 if(m_UndistortImage)
00235 m_UndistortCameraImage->UndistortImageFast(m_PauseImage, 0);
00236
00237 m_CurrentImage = m_PauseImage;
00238 }
00239 else
00240 {
00241 cvReleaseImage( &m_PauseImage );
00242 m_CurrentImage = 0;
00243 m_PauseImage = 0;
00244 }
00245 }
00246
00247 void mitk::OpenCVVideoSource::EnableOnlineImageUndistortion(mitk::Point3D focal, mitk::Point3D principal, mitk::Point4D distortion)
00248 {
00249
00250 m_UndistortImage = true;
00251 float kc[4];
00252 kc[0] = distortion[0]; kc[1] = distortion[1];
00253 kc[2] = distortion[2]; kc[3] = distortion[3];
00254 if(m_CaptureWidth == 0 || m_CaptureHeight == 0)
00255 FetchFrame();
00256
00257 m_UndistortCameraImage = mitk::UndistortCameraImage::New();
00258 m_UndistortCameraImage->SetUndistortImageFastInfo(focal[0], focal[1], principal[0], principal[1], kc, (float)m_CaptureWidth, (float)m_CaptureHeight);
00259 }
00260
00261 void mitk::OpenCVVideoSource::DisableOnlineImageUndistortion()
00262 {
00263 m_UndistortImage = false;
00264 }
00265
00266
00267 void mitk::OpenCVVideoSource::GetCurrentFrameAsItkHSVPixelImage(HSVPixelImageType::Pointer &Image)
00268 {
00269 FetchFrame();
00270
00271
00272 HSVConstIteratorType itImage( Image, Image->GetLargestPossibleRegion());
00273 itImage.Begin();
00274 HSVPixelType pixel;
00275 int rowsize = 3 * m_CaptureWidth;
00276
00277 char* bufferend;
00278 char* picture;
00279 picture = this->m_CurrentImage->imageData;
00280 bufferend = this->m_CurrentImage->imageData + 3*(m_CaptureHeight*m_CaptureWidth);
00281
00282 float r,g,b,h,s,v;
00283 try
00284 {
00285
00286 for(char* datapointer = bufferend - rowsize;datapointer >= picture; datapointer -= rowsize)
00287 {
00288 for(char* current = datapointer; current < datapointer + rowsize; current++)
00289 {
00290
00291 b = *current; current++;
00292 g = *current; current++;
00293 r = *current;
00294 RGBtoHSV(r,g,b,h,s,v);
00295 pixel[0] = h;
00296 pixel[1] = s;
00297 pixel[2] = v;
00298
00299 itImage.Set(pixel);
00300 ++itImage;
00301 }
00302 }
00303 }
00304 catch( ... )
00305 {
00306 std::cout << "Exception raised mitkOpenCVVideoSource: get hsv itk image conversion error." << std::endl;
00307 }
00308
00309 }
00310
00311 void mitk::OpenCVVideoSource::RGBtoHSV(float r, float g, float b, float &h, float &s, float &v)
00312 {
00313 if(r > 1.0)
00314 r = r/255;
00315 if(b > 1.0)
00316 b = b/255;
00317 if(g > 1.0)
00318 g = g/255;
00319
00320 float mn=r,mx=r;
00321 int maxVal=0;
00322
00323 if (g > mx){ mx=g;maxVal=1;}
00324 if (b > mx){ mx=b;maxVal=2;}
00325 if (g < mn) mn=g;
00326 if (b < mn) mn=b;
00327
00328 float delta = mx - mn;
00329
00330 v = mx;
00331 if( mx != 0 )
00332 s = delta / mx;
00333 else
00334 {
00335 s = 0;
00336 h = 0;
00337 return;
00338 }
00339 if (s==0.0f)
00340 {
00341 h=-1;
00342 return;
00343 }
00344 else
00345 {
00346 switch (maxVal)
00347 {
00348 case 0:{h = ( g - b ) / delta;break;}
00349 case 1:{h = 2 + ( b - r ) / delta;break;}
00350 case 2:{h = 4 + ( r - g ) / delta;break;}
00351 }
00352 }
00353
00354 h *= 60;
00355 if( h < 0 ) h += 360;
00356 }
00357
00358
00359
00360
00361
00362 IplImage* mitk::OpenCVVideoSource::RotateImage(IplImage* input)
00363 {
00364 if(input == NULL)
00365 {
00366 std::cout<<"openCVVideoSource: Current video image is null! "<< std::endl;
00367 return input;
00368 }
00369 IplImage* dst = cvCloneImage( input );
00370 double angle = this->GetRotationAngle();
00371 CvPoint2D32f centre;
00372 CvMat *translate = cvCreateMat(2, 3, CV_32FC1);
00373 cvSetZero(translate);
00374 centre.x = m_CaptureWidth/2;
00375 centre.y = m_CaptureHeight/2;
00376 cv2DRotationMatrix(centre, angle, 1.0, translate);
00377 cvWarpAffine(input, dst, translate,CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS , cvScalarAll(0));
00378 cvReleaseMat(&translate);
00379
00380 return dst;
00381 }
00382
00383 void mitk::OpenCVVideoSource::Reset()
00384 {
00385
00386 this->StopCapturing();
00387 if(m_VideoCapture)
00388 cvReleaseCapture(&m_VideoCapture);
00389 m_VideoCapture = 0;
00390 m_CurrentImage = 0;
00391 m_CaptureWidth = 0;
00392 m_CaptureHeight = 0;
00393 delete m_CurrentVideoTexture;
00394 m_CurrentVideoTexture = 0;
00395 if(m_PauseImage)
00396 cvReleaseImage(&m_PauseImage);
00397 m_PauseImage = 0;
00398 m_CapturePaused = false;
00399 m_VideoFileName.clear();
00400 m_GrabbingDeviceNumber = -1;
00401
00402
00403 m_UseCVCAMLib = false;
00404
00405
00406 }