source: trunk/MagicSoft/AMC/activemirrorcontrol/activemirrorcontrol/videoframe.cpp@ 4507

Last change on this file since 4507 was 4507, checked in by merck, 20 years ago
MMerck: Added setter to set the corrected reference position. MMerck: We draw both laser reference positions. The stored during MMerck: Roque lamp calibration and the corrected one for infinity MMerck: focus. CVc: Committing in .
File size: 13.5 KB
Line 
1/***************************************************************************
2 videoframe.cpp - description
3 -------------------
4 begin : Fri Nov 22 2002
5 copyright : (C) 2002 by
6 email :
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "amcdefs.h"
19#include "amcframegrabber.h"
20#include "calibratepaneldialog.h"
21#include "linearregression.h"
22#include "threadevent.h"
23#include "videoframe.h"
24#include "videospot.h"
25#include "videospotthread.h"
26#include "videothread.h"
27#include <math.h>
28#include <qframe.h>
29#include <qfile.h>
30#include <qpainter.h>
31#include <qdatetime.h>
32#include <qtextstream.h>
33#include <qtimer.h>
34#include <qimage.h>
35#include <kapp.h>
36
37extern KApplication* g_theApp;
38extern double g_dRefX, g_dRefY;
39
40VideoFrame::VideoFrame( QWidget *parent, const char *name, AMCFrameGrabber* p_pFG )
41 : QFrame( parent, name )
42{
43
44 qDebug("Thread for VideoFrame PID: %d - PPID: %d", getpid(), getppid() );
45
46 qDebug("Creating Image arrays");
47 m_pImage = new QImage( MY_WIDTH, MY_HEIGHT, MY_DEPTH*8 );
48 m_pRawImage = new QImage( MY_WIDTH, MY_HEIGHT, MY_DEPTH*8 );
49 m_pDarkFrame = new QByteArray( BUFSIZE );
50
51 m_iFrame = 0;
52 m_iGoodFrame = 0;
53 m_iDarks = 0;
54 m_iFrameNum = 0;
55
56 m_ix = m_iy = -1;
57 m_dRefX = m_dRefY = -1.;
58 m_dCenterX = m_dCenterY = -1.;
59 m_pCalibDlg = 0;
60 m_qlSpotList.setAutoDelete( true );
61 m_qlSpots.setAutoDelete( true );
62
63 qDebug("Creating VideoThread");
64 m_pVideoThread = new VideoThread( this, p_pFG );
65 m_pVideoThread->init( BUFSIZE );
66 qDebug("Creating SpotThread");
67 m_pSpotThread = new VideoSpotThread( this, m_pRawImage, (uchar*) m_pDarkFrame->data() );
68 qDebug("Starting SpotThread");
69 m_pSpotThread->start();
70 qDebug("Starting VideoThread");
71 m_pVideoThread->start();
72}
73
74VideoFrame::~VideoFrame()
75{
76 // Stop all runing threads
77 halt( true );
78 qDebug("deleting video thread");
79 delete m_pVideoThread;
80 qDebug("deleting spot thread");
81 delete m_pSpotThread;
82
83 qDebug("Deleting image and dark frame buffers");
84 delete m_pDarkFrame;
85 delete m_pImage;
86 delete m_pRawImage;
87}
88
89/** overridden painter for the frame */
90void VideoFrame::drawContents( QPainter* windowPainter )
91{
92// qDebug("In drawContents");
93 // Draw image
94 QRect rect = contentsRect();
95 windowPainter->drawImage( 0,0, *m_pImage );
96
97 // Overlay camera center if it was determined from the LEDs
98 if( m_dCenterX > 0 )
99 {
100 windowPainter->setPen( Qt::white );
101 windowPainter->drawEllipse( m_dCenterX-2., m_dCenterY-2., 5, 5);
102 windowPainter->drawEllipse( m_dCenterX-4., m_dCenterY-4., 9, 9);
103 }
104
105 // Overlay Spots
106 windowPainter->setPen( Qt::red );
107 for( VideoSpot* pActualSpot = m_qlSpots.first();
108 pActualSpot; pActualSpot = m_qlSpots.next() )
109 {
110 if( pActualSpot->isValid() )
111 windowPainter->drawEllipse( pActualSpot->getX()-4, pActualSpot->getY()-4, 9, 9);
112 }
113
114 // Overlay Leds
115 windowPainter->setPen( Qt::yellow );
116 for( VideoSpot* pActualSpot = m_qlLEDs.first();
117 pActualSpot; pActualSpot = m_qlLEDs.next() )
118 {
119 if( pActualSpot->isValid() )
120 windowPainter->drawRect( pActualSpot->getX()-4, pActualSpot->getY()-4, 9, 9);
121 }
122 windowPainter->drawEllipse( LED1_X-4, LED1_Y-4, 9, 9);
123 windowPainter->drawEllipse( LED2_X-4, LED2_Y-4, 9, 9);
124 windowPainter->drawEllipse( LED3_X-4, LED3_Y-4, 9, 9);
125 windowPainter->drawEllipse( LED4_X-4, LED4_Y-4, 9, 9);
126
127 // Draw the calibration points and the regression fits.
128 if( m_pCalibDlg != 0 )
129 {
130 QList<VideoSpot>* pLineList = m_pCalibDlg->getLineList();
131 windowPainter->setPen( Qt::magenta );
132 for( VideoSpot* pActualSpot = pLineList->first();
133 pActualSpot; pActualSpot = pLineList->next() )
134 {
135 if( pActualSpot->isValid() )
136 windowPainter->drawEllipse( pActualSpot->getX()-4, pActualSpot->getY()-4, 9, 9);
137 }
138
139 int iX1, iX2;
140 windowPainter->setPen( Qt::yellow );
141 LinearRegression* pRegression = m_pCalibDlg->getXRegression();
142 if( pRegression->isValid() )
143 {
144 if( ! pRegression->getReversed() ) {
145 iX1 = (int) (( 0. - pRegression->getAxis()) / pRegression->getSlope());
146 iX2 = (int) (( 479. - pRegression->getAxis()) / pRegression->getSlope());
147 windowPainter->drawLine( iX1, 0, iX2, 479 );
148 }
149 else
150 {
151 iX1 = (int) pRegression->getAxis();
152 iX2 = (int) ( pRegression->getAxis() + 479 * pRegression->getSlope() );
153 windowPainter->drawLine( iX1, 0, iX2, 479 );
154 }
155 }
156
157 pRegression = m_pCalibDlg->getYRegression();
158 if( pRegression->isValid() )
159 {
160 if( ! pRegression->getReversed() )
161 {
162 iX1 = (int) (( 0. - pRegression->getAxis()) / pRegression->getSlope());
163 iX2 = (int) (( 479. - pRegression->getAxis()) / pRegression->getSlope());
164 windowPainter->drawLine( iX1, 0, iX2, 479 );
165 }
166 else
167 {
168 iX1 = (int) pRegression->getAxis();
169 iX2 = (int) ( pRegression->getAxis() + 479 * pRegression->getSlope() );
170 windowPainter->drawLine( iX1, 0, iX2, 479 );
171// qDebug( "Drawing line: (%d,%d) - (%d,%d)", iX1, 0, iX2, 479 );
172 }
173 }
174
175 }
176
177 // Draw a blue cross for the global reference point
178 windowPainter->setPen( Qt::blue );
179 windowPainter->drawLine( g_dRefX-4., g_dRefY, g_dRefX+4., g_dRefY);
180 windowPainter->drawLine( g_dRefX, g_dRefY-4., g_dRefX, g_dRefY+4.);
181
182 // Draw a green rectangle showing the reference point for this panel
183 if( m_dRefX > 0)
184 {
185 // Draw a green rectangle showing the reference point for this panel
186 windowPainter->setPen( Qt::green );
187 if( m_dCenterX > 1.0 )
188 {
189 // Adapt spot for shift of camera center.
190 double dDx, dDy;
191 dDx = m_dCenterX - CAMERA_X;
192 dDy = m_dCenterY - CAMERA_Y;
193 windowPainter->drawRect( m_dRefX+dDx-4., m_dRefY+dDy-4., 9., 9. );
194 } else
195 windowPainter->drawRect( m_dRefX-4., m_dRefY-4., 9., 9. );
196 }
197
198 // Draw a cyan rectangle showing the corrected reference point for this panel
199 if( m_dRef1X > 0)
200 {
201 windowPainter->setPen( Qt::cyan );
202 if( m_dCenterX > 1.0 )
203 {
204 // Adapt spot for shift of camera center.
205 double dDx, dDy;
206 dDx = m_dCenterX - CAMERA_X;
207 dDy = m_dCenterY - CAMERA_Y;
208 windowPainter->drawRect( m_dRef1X+dDx-4., m_dRef1Y+dDy-4., 9., 9. );
209 } else
210 windowPainter->drawRect( m_dRef1X-4., m_dRef1Y-4., 9., 9. );
211
212 }
213
214 // Draw a blue rectangle showing the Region Of Interest (ROI)
215 // which is used to find the spot
216 if( ! m_qrROI.isEmpty() )
217 {
218 windowPainter->setPen( Qt::blue );
219 windowPainter->drawRect( m_qrROI );
220 }
221
222}
223
224/** No descriptions */
225void VideoFrame::saveFrame()
226{
227 QString fileName;
228 fileName.sprintf("Frame%02d.png",m_iFrameNum);
229 m_pImage->save( fileName, "PNG");
230
231 fileName.sprintf("Spots%02d.txt",m_iFrameNum++);
232 QFile file( fileName );
233 if( file.open( IO_WriteOnly ) )
234 {
235 QTextStream stream( &file );
236
237 QString str;
238
239 str.sprintf("LEDs\n" );
240 stream << str;
241 for( VideoSpot* pActualSpot = m_qlLEDs.first();
242 pActualSpot; pActualSpot = m_qlLEDs.next() )
243 {
244 if( pActualSpot->isValid() )
245 {
246 str.sprintf("%6.2f %6.2f %d\n", pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel() );
247 stream << str;
248 }
249 }
250
251 str.sprintf("\nSpots\n" );
252 stream << str;
253 for( VideoSpot* pActualSpot = m_qlSpots.first();
254 pActualSpot; pActualSpot = m_qlSpots.next() )
255 {
256 if( pActualSpot->isValid() )
257 {
258 str.sprintf("%6.2f %6.2f %d\n", pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel() );
259 stream << str;
260 }
261 }
262
263 }
264}
265
266/** Save a dark frame */
267void VideoFrame::takeDark()
268{
269 qDebug("Taking dark frame");
270 uchar* pFrame = m_pImage->bits();
271 m_pVideoThread->getLastFrame( pFrame );
272 uchar* pDark = m_pDarkFrame->data();
273
274 for(int ind=0; ind< (MY_HEIGHT * MY_WIDTH * MY_DEPTH); ind++, pDark++, pFrame++ )
275 {
276 int help = *pDark;
277 help = (help * m_iDarks) + (int) *pFrame;
278 *pDark = (uchar) (help / (m_iDarks+1));
279 }
280 m_iDarks++;
281}
282
283/** Clear dark frames */
284void VideoFrame::clearDarks()
285{
286 m_pDarkFrame->fill(0);
287 m_iDarks = 0;
288}
289
290/** No descriptions */
291void VideoFrame::timerDone()
292{
293// qDebug("Frames per second %d %d", m_iFrame, m_iGoodFrame);
294 emit framesGrabbed( m_iFrame );
295 emit framesProcessed( m_iGoodFrame );
296 m_iFrame = 0;
297 m_iGoodFrame=0;
298}
299
300/** No descriptions */
301void VideoFrame::mouseMoveEvent( QMouseEvent* event )
302{
303 if( (event->state() & LeftButton) == 0 )
304 return;
305
306 int x = event->x();
307 int y = event->y();
308 if( x > m_qrROI.left() )
309 m_qrROI.setRight( x );
310 else
311 {
312 if( x == m_qrROI.left() )
313 m_qrROI.setRight( event->x() -1 );
314 else
315 m_qrROI.setLeft( x );
316 }
317 if( y > m_qrROI.top() )
318 m_qrROI.setBottom( y );
319 else
320 {
321 if( y == m_qrROI.bottom() )
322 m_qrROI.setBottom( event->y() -1 );
323 else
324 m_qrROI.setTop( y );
325 }
326 if ( m_qrROI.isValid() );
327 m_pSpotThread->setROI( m_qrROI );
328}
329
330/** No descriptions */
331void VideoFrame::mousePressEvent( QMouseEvent* event )
332{
333 if( event->button() == LeftButton )
334 {
335 m_qrROI.setLeft( event->x() );
336 m_qrROI.setRight( event->x() -1 );
337 m_qrROI.setTop( event->y() );
338 m_qrROI.setBottom( event->y() -1 );
339 m_pSpotThread->setROI( m_qrROI );
340 }
341 if( event->button() == MidButton )
342 {
343 m_qrROI.setLeft( 0 );
344 m_qrROI.setRight( -1 );
345 m_qrROI.setTop( 0 );
346 m_qrROI.setBottom( -1 );
347 m_pSpotThread->setROI( m_qrROI );
348 }
349 if( event->button() == RightButton )
350 {
351 g_dRefX = event->x();
352 g_dRefY = event->y();
353 emit gref( g_dRefX, g_dRefY );
354 }
355}
356
357void VideoFrame::customEvent(QCustomEvent *e)
358{
359 if ( e->type() == THREAD_SPOT_EVENT )
360 {
361 g_theApp->processEvents();
362 m_pSpotThread->getSpotList( &m_qlSpotList );
363 m_pSpotThread->getFrame( m_pImage->bits() );
364 m_iGoodFrame++;
365 repaint( FALSE );
366
367 calcCenter();
368 if( m_qlSpots.count() == 1)
369 {
370 VideoSpot* pSpot = m_qlSpots.first();
371 emit spot( pSpot->getX(), pSpot->getY() );
372 }
373 else
374 emit spot( -1, -1 );
375 g_theApp->processEvents();
376
377 }
378 if ( e->type() == THREAD_FRAME_EVENT )
379 {
380 m_iFrame++;
381 if( ! m_pSpotThread->isActive() )
382 {
383 m_pVideoThread->getLastFrame( m_pRawImage->bits() );
384 m_pSpotThread->wake();
385 }
386//else
387// qDebug("Dropping Frame");
388 g_theApp->processEvents();
389 }
390}
391
392/** No descriptions */
393void VideoFrame::threshold( int p_iValue )
394{
395 m_pSpotThread->setSigmas( p_iValue );
396}
397
398/** No descriptions */
399void VideoFrame::scaleValue( int p_iValue )
400{
401 m_pSpotThread->setScalingMax( p_iValue );
402}
403
404void VideoFrame::halt( bool p_zStop )
405{
406 if ( p_zStop == true )
407 {
408 qDebug("Stoping video thread");
409 m_pVideoThread->stop();
410 m_pVideoThread->wait(); // Wait for video thread to finish
411 qDebug("Stoping videospot thread");
412 m_pSpotThread->stop();
413 m_pSpotThread->wake();
414 m_pSpotThread->wait(); // Wait for spot thread to finish
415 }
416 else
417 {
418 qDebug("Starting video thread");
419 m_pSpotThread->start();
420 qDebug("Starting videospot thread");
421 m_pVideoThread->start();
422 }
423}
424
425/** Calculate the location of the central pixel. We do this by identifiying the
426 position of the camera LEDs and getting the relative offsets. */
427void VideoFrame::calcCenter()
428{
429 double dX = 0.0, dX1 = 0.0, dX2 = 0.0, dX3 = 0.0, dX4 = 0.0;
430 double dY = 0.0, dY1 = 0.0, dY2 = 0.0, dY3 = 0.0, dY4 = 0.0;
431 int iNumLEDs = 0;
432
433 m_dCenterX = m_dCenterY = -1.;
434 m_qlLEDs.clear();
435 m_qlSpots.clear();
436
437 for( VideoSpot* pActualSpot = m_qlSpotList.first();
438 pActualSpot; pActualSpot = m_qlSpotList.next() )
439 {
440 // Check if this spot is compatible with the spot of the
441 // upper left LED
442 if ( pActualSpot->contains2( LED1_X, LED1_Y ) )
443 {
444 dX1 = pActualSpot->getX() + (CAMERA_X - LED1_X);
445 dY1 = pActualSpot->getY() + (CAMERA_Y - LED1_Y);
446 dX += dX1; dY += dY1;
447 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel()) );
448 iNumLEDs++;
449 }
450 // Check if this spot is compatible with the spot of the
451 // upper right LED
452 else if ( pActualSpot->contains2( LED2_X, LED2_Y ) )
453 {
454 dX2 = pActualSpot->getX() + (CAMERA_X - LED2_X);
455 dY2 = pActualSpot->getY() + (CAMERA_Y - LED2_Y);
456 dX += dX2; dY += dY2;
457 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel()) );
458 iNumLEDs++;
459 }
460 // Check if this spot is compatible with the spot of the
461 // lower left LED
462 else if ( pActualSpot->contains2( LED3_X, LED3_Y ) )
463 {
464 dX3 = pActualSpot->getX() + (CAMERA_X - LED3_X);
465 dY3 = pActualSpot->getY() + (CAMERA_Y - LED3_Y);
466 dX += dX3; dY += dY3;
467 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel()) );
468 iNumLEDs++;
469 }
470 // Check if this spot is compatible with the spot of the
471 // lower right LED
472 else if ( pActualSpot->contains2( LED4_X, LED4_Y ) )
473 {
474 dX4 = pActualSpot->getX() + (CAMERA_X - LED4_X);
475 dY4 = pActualSpot->getY() + (CAMERA_Y - LED4_Y);
476 dX += dX4; dY += dY4;
477 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel()) );
478 iNumLEDs++;
479 }
480 else
481 m_qlSpots.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY(), pActualSpot->getNumPixel()) );
482 }
483 if( iNumLEDs != 0)
484 {
485 m_dCenterX = dX / iNumLEDs;
486 m_dCenterY = dY / iNumLEDs;
487// qDebug("Center %d %d", m_iCenterX, m_iCenterY);
488 }
489// qDebug("Center at: %5.1f %5.1f -- with %d LEDs",m_dCenterX, m_dCenterY, iNumLEDs );
490}
Note: See TracBrowser for help on using the repository browser.