MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkOpenCVVideoSource.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include <iostream>
15#include <algorithm>
16
17#include <opencv2/videoio/videoio_c.h>
18
20: m_VideoCapture(nullptr),
21 m_CurrentImage(nullptr),
22 m_CurrentVideoTexture(nullptr),
23 m_PauseImage(nullptr),
24 m_GrabbingDeviceNumber(-1),
25 m_RepeatVideo(false),
26 m_UseCVCAMLib(false),
27 m_UndistortImage(false),
28 m_FlipXAxisEnabled(false),
29 m_FlipYAxisEnabled(false)
30{
31}
32
37
38void mitk::OpenCVVideoSource::SetVideoFileInput(const char * filename, bool repeatVideo, bool /*useCVCAMLib*/)
39{
40 this->Reset();
41 m_VideoFileName = filename;
42
43 m_VideoCapture = cvCaptureFromFile(filename);
44 if(!m_VideoCapture)
45 MITK_WARN << "Error in initializing video file input!";
46
47 m_RepeatVideo = repeatVideo;
48 //m_CurrentImage = cvCreateImage(cvSize(m_CaptureWidth,m_CaptureHeight),8,3);
49 this->Modified();
50
51}
52void mitk::OpenCVVideoSource::SetVideoCameraInput(int cameraindex, bool /*useCVCAMLib*/)
53{
54 this->Reset();
55
56 m_GrabbingDeviceNumber = cameraindex;
57 m_VideoCapture = cvCaptureFromCAM(m_GrabbingDeviceNumber);
58 if(!m_VideoCapture)
59 MITK_ERROR << "Error in initializing CVHighGUI video camera!"<< std::endl;
60
61 this->Modified();
62}
63
65{
66 return cvGetCaptureProperty(m_VideoCapture, property_id);
67}
68
69int mitk::OpenCVVideoSource::SetVideoCaptureProperty(int property_id, double value)
70{
71 return cvSetCaptureProperty(m_VideoCapture, property_id, value);
72}
73
74//method extended for "static video feature" if enabled
76{ // Fetch Frame and return pointer to opengl texture
77 FetchFrame();
78
79 if (m_FlipXAxisEnabled || m_FlipYAxisEnabled)
80 {
81 //rotate the image to get a static video
82 m_CurrentImage = this->FlipImage(m_CurrentImage);
83
84 }
85
86 //transfer the image to a texture
87 this->UpdateVideoTexture();
88 return this->m_CurrentVideoTexture;
89 this->Modified();
90}
91
93{
94 if(m_CurrentImage)
95 {
96 cv::Mat copy = cv::cvarrToMat( m_CurrentImage, false );
97 return copy.clone();
98 }
99 return cv::Mat();
100}
101
103{
104 return m_CurrentImage;
105}
106
108{ // get last captured frame for processing the image data
109 if(m_CurrentImage)
110 {
111 if(image)
112 {
113 image->origin = m_CurrentImage->origin;
114 memcpy(image->imageData,m_CurrentImage->imageData,m_CurrentImage->width*m_CurrentImage->height*m_CurrentImage->nChannels);
115 }
116 }
117}
118
120{ // main procedure for updating video data
121 if(m_CapturingInProcess)
122 {
123 if(m_VideoCapture) // we use highgui
124 {
125 if(!m_CapturePaused)
126 {
127 // release old image here
128 m_CurrentImage = cvQueryFrame(m_VideoCapture);
129 ++m_FrameCount;
130 }
131
132 if(m_CurrentImage == nullptr) // do we need to repeat the video if it is from video file?
133 {
134 double framePos = this->GetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO);
135 MITK_DEBUG << "End of video file found. framePos: " << framePos;
136 if(m_RepeatVideo && framePos >= 0.99)
137 {
138 MITK_DEBUG << "Restarting video file playback.";
139 this->SetVideoCaptureProperty(CV_CAP_PROP_POS_AVI_RATIO, 0);
140 m_FrameCount = 0;
141 m_CurrentImage = cvQueryFrame(m_VideoCapture);
142 }
143 else
144 {
145 std::ostringstream s;
146 s << "End of video file " << m_VideoFileName;
147 std::logic_error err( s.str() );
148 throw err;
149 }
150 }
151 else
152 {
153 // only undistort if not paused
154 if(m_UndistortImage && m_UndistortCameraImage.IsNotNull())
155 m_UndistortCameraImage->UndistortImageFast(m_CurrentImage, nullptr);
156 }
157
158 if(m_CaptureWidth == 0 || m_CaptureHeight == 0)
159 {
160 MITK_DEBUG << "Trying to set m_CaptureWidth & m_CaptureHeight.";
161 m_CaptureWidth = m_CurrentImage->width;
162 m_CaptureHeight = m_CurrentImage->height;
163 MITK_INFO << "frame width: " << m_CaptureWidth << ", height: " << m_CaptureHeight;
164 m_CurrentImage->origin = 0;
165 }
166 }
167 }
168}
169
171{ //write the grabbed frame into an opengl compatible array, that means flip it and swap channel order
172 if(!m_CurrentImage)
173 return;
174
175 if(m_CurrentVideoTexture == nullptr)
176 m_CurrentVideoTexture = new unsigned char[m_CaptureWidth*m_CaptureHeight*3];
177
178 int width = m_CurrentImage->width;
179 int height = m_CurrentImage->height;
180 int widthStep = m_CurrentImage->widthStep;
181 int nChannels = m_CurrentImage->nChannels;
182 unsigned char* tex = m_CurrentVideoTexture;
183 char* data = m_CurrentImage->imageData;
184 char* currentData = m_CurrentImage->imageData;
185
186 int hIndex=0;
187 int wIndex=0;
188 int iout,jout;
189
190 for(int i=0;i<width*height*3;i+=3,++wIndex)
191 {
192 if(wIndex >= width)
193 {
194 wIndex=0;
195 hIndex++;
196 }
197
198 // vertically flip the image
199 iout = -hIndex+height-1;
200 jout = wIndex;
201
202 currentData = data + iout*widthStep;
203
204 tex[i+2] = currentData[jout*nChannels + 0]; // B
205 tex[i+1] = currentData[jout*nChannels + 1]; // G
206 tex[i] = currentData[jout*nChannels + 2]; // R
207 }
208
209}
210
212{
213 if(m_VideoCapture != nullptr)
214 m_CapturingInProcess = true;
215 else
216 m_CapturingInProcess = false;
217}
218
220{
221 m_CapturePaused = false;
222 m_CapturingInProcess = false;
223}
224
226{
227 return m_UndistortCameraImage;
228}
229
231{
232 m_CapturePaused = !m_CapturePaused;
233
234 if(m_CapturePaused)
235 {
236 m_PauseImage = cvCloneImage(m_CurrentImage);
237
238 // undistort this pause image if necessary
239 if(m_UndistortImage)
240 m_UndistortCameraImage->UndistortImageFast(m_PauseImage, nullptr);
241 m_CurrentImage = m_PauseImage;
242 }
243 else
244 {
245 cvReleaseImage( &m_PauseImage ); // release old pause image if necessary
246 m_CurrentImage = nullptr;
247 m_PauseImage = nullptr;
248 }
249}
250
251void mitk::OpenCVVideoSource::EnableOnlineImageUndistortion(mitk::Point3D focal, mitk::Point3D principal, mitk::Point4D distortion)
252{
253 // Initialize Undistortion
254 m_UndistortImage = true;
255 float kc[4];
256 kc[0] = distortion[0]; kc[1] = distortion[1];
257 kc[2] = distortion[2]; kc[3] = distortion[3];
258 if(m_CaptureWidth == 0 || m_CaptureHeight == 0)
259 FetchFrame();
260
261 m_UndistortCameraImage = mitk::UndistortCameraImage::New();
262 m_UndistortCameraImage->SetUndistortImageFastInfo(focal[0], focal[1], principal[0], principal[1], kc, (float)m_CaptureWidth, (float)m_CaptureHeight);
263}
264
266{
267 m_UndistortImage = false;
268}
269
270// functions for compatibility with ITK segmentation only
272{
273 FetchFrame();
274
275 // Prepare iteration
276 HSVConstIteratorType itImage( Image, Image->GetLargestPossibleRegion());
277 itImage.GoToBegin();
278 HSVPixelType pixel;
279 int rowsize = 3 * m_CaptureWidth;
280
281 char* bufferend;
282 char* picture;
283 picture = this->m_CurrentImage->imageData;
284 bufferend = this->m_CurrentImage->imageData + 3*(m_CaptureHeight*m_CaptureWidth);
285
286 float r,g,b,h,s,v;
287 try
288 {
289 // we have to flip the image
290 for(char* datapointer = bufferend - rowsize;datapointer >= picture; datapointer -= rowsize)
291 {
292 for(char* current = datapointer; current < datapointer + rowsize; current++)
293 {
294 b = *current; current++;
295 g = *current; current++;
296 r = *current;
297 RGBtoHSV(r,g,b,h,s,v);
298 pixel[0] = h;
299 pixel[1] = s;
300 pixel[2] = v;
301
302 itImage.Set(pixel);
303 ++itImage;
304 }
305 }
306 }
307 catch( ... )
308 {
309 std::cout << "Exception raised mitkOpenCVVideoSource: get hsv itk image conversion error." << std::endl;
310 }
311
312}
313
314void mitk::OpenCVVideoSource::RGBtoHSV(float r, float g, float b, float &h, float &s, float &v)
315{
316 if(r > 1.0)
317 r = r/255;
318 if(b > 1.0)
319 b = b/255;
320 if(g > 1.0)
321 g = g/255;
322
323 float mn=r,mx=r;
324 int maxVal=0;
325
326 if (g > mx){ mx=g;maxVal=1;}
327 if (b > mx){ mx=b;maxVal=2;}
328 if (g < mn) mn=g;
329 if (b < mn) mn=b;
330
331 float delta = mx - mn;
332
333 v = mx;
334 if( mx != 0 )
335 s = delta / mx;
336 else
337 {
338 s = 0;
339 h = 0;
340 return;
341 }
342 if (s==0.0f)
343 {
344 h=-1;
345 return;
346 }
347 else
348 {
349 switch (maxVal)
350 {
351 case 0:{h = ( g - b ) / delta;break;} // yel < h < mag
352 case 1:{h = 2 + ( b - r ) / delta;break;} // cyan < h < yel
353 case 2:{h = 4 + ( r - g ) / delta;break;} // mag < h < cyan
354 }
355 }
356
357 h *= 60;
358 if( h < 0 ) h += 360;
359}
360
361/*
362* Rotate input image according to rotation angle around the viewing direction.
363* Angle is supposed to be calculated in QmitkARRotationComponet in the update() method.
364*/
365IplImage* mitk::OpenCVVideoSource::FlipImage(IplImage* input)
366{
367 if(input == nullptr)
368 { //warn the user and quit
369 std::cout<<"openCVVideoSource: Current video image is null! "<< std::endl;
370 return input;
371 }
372
373 if(m_FlipXAxisEnabled && !m_FlipYAxisEnabled)
374 {
375 cvFlip(input,nullptr,0);
376 }
377 if(!m_FlipXAxisEnabled && m_FlipYAxisEnabled)
378 {
379 cvFlip(input,nullptr,1);
380 }
381 if(m_FlipXAxisEnabled && m_FlipYAxisEnabled)
382 {
383 cvFlip(input,nullptr,-1);
384 }
385
386 return input;
387}
388
390{
391 // set capturing to false
392 this->StopCapturing();
393 this->m_FrameCount = 0;
394 if(m_VideoCapture)
395 cvReleaseCapture(&m_VideoCapture);
396 m_VideoCapture = nullptr;
397 m_CurrentImage = nullptr;
398 m_CaptureWidth = 0;
399 m_CaptureHeight = 0;
400 delete m_CurrentVideoTexture;
401 m_CurrentVideoTexture = nullptr;
402 if(m_PauseImage)
403 cvReleaseImage(&m_PauseImage);
404 m_PauseImage = nullptr;
405 m_CapturePaused = false;
406 m_VideoFileName.clear();
407 m_GrabbingDeviceNumber = -1;
408 // do not touch repeat video
409 //m_RepeatVideo = false;
410 m_UseCVCAMLib = false;
411 // do not touch undistort settings
412 // bool m_UndistortImage;
413}
414
416{
417 this->m_FlipXAxisEnabled = enable;
418 this->Modified();
419}
420
422{
423 this->m_FlipXAxisEnabled = enable;
424 this->Modified();
425}
426
void RGBtoHSV(float r, float g, float b, float &h, float &s, float &v)
virtual void GetCurrentFrameAsItkHSVPixelImage(HSVPixelImageType::Pointer &Image)
virtual void SetVideoCameraInput(int cameraindex, bool useCVCAMLib=false)
virtual IplImage * FlipImage(IplImage *input)
itk::ImageRegionIterator< HSVPixelImageType > HSVConstIteratorType
itk::FixedArray< float, 3 > HSVPixelType
unsigned char * GetVideoTexture() override
virtual void SetEnableXAxisFlip(bool enable)
virtual void GetCurrentFrameAsOpenCVImage(IplImage *image)
virtual void SetEnableYAxisFlip(bool enable)
virtual const IplImage * GetCurrentFrame()
virtual void DisableOnlineImageUndistortion()
virtual int SetVideoCaptureProperty(int property_id, double value)
virtual void EnableOnlineImageUndistortion(mitk::Point3D focal, mitk::Point3D principal, mitk::Point4D distortion)
virtual double GetVideoCaptureProperty(int property_id)
virtual void SetVideoFileInput(const char *filename, bool repeatVideo, bool useCVCAMLib=false)
virtual bool OnlineImageUndistortionEnabled() const