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

Last change on this file since 3401 was 3401, checked in by merck, 21 years ago
nitial checkin of AMC project
File size: 11.1 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
36#define HEADERSIZE 15
37
38extern int g_iRefX, g_iRefY;
39
40
41VideoFrame::VideoFrame( QWidget *parent, const char *name, AMCFrameGrabber* p_pFG )
42 : QFrame( parent, name )
43{
44
45 qDebug("Thread for VideoFrame PID: %d - PPID: %d", getpid(), getppid() );
46
47 qDebug("Creating Image arrays");
48 m_pImage = new QImage( MY_WIDTH, MY_HEIGHT, MY_DEPTH*8 );
49 m_darkFrame = 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_iRefX = m_iRefY = -1;
58 m_iCenterX = m_iCenterY = 1;
59 m_pCalibDlg = 0;
60// m_qlSpots.setAutoDelete( true );
61
62 qDebug("Creating VideoThread");
63 m_pVideoThread = new VideoThread( this, p_pFG );
64 m_pVideoThread->init( BUFSIZE );
65 qDebug("Creating SpotThread");
66 m_pSpotThread = new VideoSpotThread( this, m_pImage, (uchar*) m_darkFrame->data() );
67 qDebug("Starting VideoThread");
68 qDebug("Thread for VideoFrame when starting VideoThread PID: %d - PPID: %d", getpid(), getppid() );
69 m_pVideoThread->start();
70}
71
72VideoFrame::~VideoFrame()
73{
74 qDebug("Stoping video thread");
75 m_pVideoThread->stop();
76 m_pVideoThread->wait( );
77 qDebug("deleting video thread");
78 delete m_pVideoThread;
79 qDebug("Stoping spot thread");
80 m_pSpotThread->wait();
81 qDebug("deleting spot thread");
82 delete m_pSpotThread;
83 delete m_darkFrame;
84 delete m_pImage;
85 m_qlSpots.clear();
86}
87
88/** overridden painter for the frame */
89void VideoFrame::drawContents( QPainter* windowPainter )
90{
91// qDebug("In drawContents");
92 // Draw image
93 QRect rect = contentsRect();
94 windowPainter->drawImage( 0,0, *m_pImage );
95
96 // Overlay camera center if it was determined from the LEDs
97 if( m_iCenterX != -1 )
98 windowPainter->setPen( Qt::white );
99 windowPainter->drawEllipse( m_iCenterX-2, m_iCenterY-2, 5, 5);
100 windowPainter->drawEllipse( m_iCenterX-4, m_iCenterY-4, 9, 9);
101
102 // Overlay Spots
103 windowPainter->setPen( Qt::red );
104 for( VideoSpot* pActualSpot = m_qlSpots.first();
105 pActualSpot; pActualSpot = m_qlSpots.next() )
106 {
107 if( pActualSpot->isValid() )
108 windowPainter->drawEllipse( pActualSpot->getX()-4, pActualSpot->getY()-4, 9, 9);
109 }
110
111 if( m_pCalibDlg != 0 )
112 {
113 QList<VideoSpot>* pLineList = m_pCalibDlg->getLineList();
114 windowPainter->setPen( Qt::magenta );
115 for( VideoSpot* pActualSpot = pLineList->first();
116 pActualSpot; pActualSpot = pLineList->next() )
117 {
118 if( pActualSpot->isValid() )
119 windowPainter->drawEllipse( pActualSpot->getX()-4, pActualSpot->getY()-4, 9, 9);
120 }
121
122 int iX1, iX2;
123 windowPainter->setPen( Qt::yellow );
124 LinearRegression* pRegression = m_pCalibDlg->getXRegression();
125 if( pRegression->isValid() )
126 {
127 iX1 = (int) (( 0. - pRegression->getAxis()) / pRegression->getSlope());
128 iX2 = (int) (( 479. - pRegression->getAxis()) / pRegression->getSlope());
129 windowPainter->drawLine( iX1, 0, iX2, 479 );
130 }
131
132 pRegression = m_pCalibDlg->getYRegression();
133 if( pRegression->isValid() )
134 {
135 iX1 = (int) (( 0. - pRegression->getAxis() ) / pRegression->getSlope());
136 iX2 = (int) (( 479. - pRegression->getAxis() ) / pRegression->getSlope());
137 windowPainter->drawLine( iX1, 0, iX2, 479 );
138 }
139
140 }
141
142 // Draw a blue cross for the global reference point
143 windowPainter->setPen( Qt::blue );
144 windowPainter->drawLine( g_iRefX-4, g_iRefY, g_iRefX+4, g_iRefY);
145 windowPainter->drawLine( g_iRefX, g_iRefY-4, g_iRefX, g_iRefY+4);
146
147 // Draw a green rectangle showing the reference point for this panel
148 if( m_iRefX > 0)
149 {
150 windowPainter->setPen( Qt::green );
151 windowPainter->drawRect( m_iRefX-4, m_iRefY-4, 9, 9 );
152 }
153
154 // Draw a blue rectangle showing the Region Of Interest (ROI)
155 // which is used to find the spot
156 if( ! m_qrROI.isEmpty() )
157 {
158 windowPainter->setPen( Qt::blue );
159 windowPainter->drawRect( m_qrROI );
160 }
161
162}
163
164/** No descriptions */
165void VideoFrame::saveFrame()
166{
167 QString fileName;
168 fileName.sprintf("Frame%02d.png",m_iFrameNum);
169 m_pImage->save( fileName, "PNG");
170
171 fileName.sprintf("Spots%02d.txt",m_iFrameNum++);
172 QFile file( fileName );
173 if( file.open( IO_WriteOnly ) )
174 {
175 QTextStream stream( &file );
176
177 QString str;
178
179 str.sprintf("LEDs\n" );
180 stream << str;
181 for( VideoSpot* pActualSpot = m_qlLEDs.first();
182 pActualSpot; pActualSpot = m_qlLEDs.next() )
183 {
184 if( pActualSpot->isValid() )
185 {
186 str.sprintf("%d %d\n", pActualSpot->getX(), pActualSpot->getY() );
187 stream << str;
188 }
189 }
190
191 str.sprintf("\nSpots\n" );
192 stream << str;
193 for( VideoSpot* pActualSpot = m_qlSpots.first();
194 pActualSpot; pActualSpot = m_qlSpots.next() )
195 {
196 if( pActualSpot->isValid() )
197 {
198 str.sprintf("%d %d\n", pActualSpot->getX(), pActualSpot->getY() );
199 stream << str;
200 }
201 }
202
203 }
204}
205
206/** Save a dark frame */
207void VideoFrame::takeDark()
208{
209 qDebug("Taking dark frame");
210 uchar* pFrame = m_pImage->bits();
211 m_pVideoThread->getLastFrame( pFrame );
212 uchar* pDark = m_darkFrame->data();
213
214 for(int ind=0; ind< (MY_HEIGHT * MY_WIDTH * MY_DEPTH); ind++, pDark++, pFrame++ )
215 {
216 int help = *pDark;
217 help = (help * m_iDarks) + (int) *pFrame;
218 *pDark = (uchar) (help / (m_iDarks+1));
219 }
220 m_iDarks++;
221}
222
223/** Clear dark frames */
224void VideoFrame::clearDarks()
225{
226 m_darkFrame->fill(0);
227 m_iDarks = 0;
228}
229
230/** No descriptions */
231void VideoFrame::timerDone()
232{
233// qDebug("Frames per second %d %d", m_iFrame, m_iGoodFrame);
234 emit framesGrabbed( m_iFrame );
235 emit framesProcessed( m_iGoodFrame );
236 m_iFrame = 0;
237 m_iGoodFrame=0;
238}
239
240/** No descriptions */
241void VideoFrame::mouseMoveEvent( QMouseEvent* event )
242{
243 if( (event->state() & LeftButton) == 0 )
244 return;
245
246 int x = event->x();
247 int y = event->y();
248 if( x > m_qrROI.left() )
249 m_qrROI.setRight( x );
250 else
251 {
252 if( x == m_qrROI.left() )
253 m_qrROI.setRight( event->x() -1 );
254 else
255 m_qrROI.setLeft( x );
256 }
257 if( y > m_qrROI.top() )
258 m_qrROI.setBottom( y );
259 else
260 {
261 if( y == m_qrROI.bottom() )
262 m_qrROI.setBottom( event->y() -1 );
263 else
264 m_qrROI.setTop( y );
265 }
266 if ( m_qrROI.isValid() );
267 m_pSpotThread->setROI( m_qrROI );
268}
269
270/** No descriptions */
271void VideoFrame::mousePressEvent( QMouseEvent* event )
272{
273 if( event->button() == LeftButton )
274 {
275 m_qrROI.setLeft( event->x() );
276 m_qrROI.setRight( event->x() -1 );
277 m_qrROI.setTop( event->y() );
278 m_qrROI.setBottom( event->y() -1 );
279 m_pSpotThread->setROI( m_qrROI );
280 }
281 if( event->button() == MidButton )
282 {
283 m_qrROI.setLeft( 0 );
284 m_qrROI.setRight( -1 );
285 m_qrROI.setTop( 0 );
286 m_qrROI.setBottom( -1 );
287 m_pSpotThread->setROI( m_qrROI );
288 }
289 if( event->button() == RightButton )
290 {
291 g_iRefX = event->x();
292 g_iRefY = event->y();
293 emit gref( g_iRefX, g_iRefY );
294 }
295}
296
297void VideoFrame::customEvent(QCustomEvent *e)
298{
299 if ( e->type() == THREAD_END_EVENT )
300 {
301 repaint( FALSE );
302 calcCenter();
303 if( m_qlSpots.count() == 1)
304 {
305 VideoSpot* pSpot = m_qlSpots.first();
306 emit spot( pSpot->getX(), pSpot->getY() );
307 }
308 else
309 emit spot( -1, -1 );
310 }
311 if ( e->type() == THREAD_FRAME_EVENT )
312 {
313 m_iFrame++;
314 if( ! m_pSpotThread->running() )
315 {
316 m_iGoodFrame++;
317 m_pVideoThread->getLastFrame( m_pImage->bits() );
318 m_pSpotThread->start();
319 }
320// else
321// qDebug("Dropping Frame");
322 }
323}
324
325/** No descriptions */
326void VideoFrame::threshold( int p_iValue )
327{
328 m_pSpotThread->setSigmas( p_iValue );
329}
330
331/** No descriptions */
332void VideoFrame::scaleValue( int p_iValue )
333{
334 m_pSpotThread->setScalingMax( p_iValue );
335}
336
337void VideoFrame::halt( bool p_zStop )
338{
339 if ( p_zStop == true )
340 {
341 m_pVideoThread->stop();
342 m_pVideoThread->wait(); // Wait for video thread to finish
343 m_pSpotThread->wait(); // Wait for spot thread to finish
344 }
345 else
346 m_pVideoThread->start();
347}
348
349/** Calculate the location of the central pixel. We do this by identifiying the
350 position of the camera LEDs and getting the relative offsets. */
351void VideoFrame::calcCenter()
352{
353 double dX = 0.0, dX1 = 0.0, dX2 = 0.0, dX3 = 0.0, dX4 = 0.0;
354 double dY = 0.0, dY1 = 0.0, dY2 = 0.0, dY3 = 0.0, dY4 = 0.0;
355 int iNumLEDs = 0;
356
357 m_iCenterX = m_iCenterY = 1;
358 m_qlLEDs.clear();
359 m_qlSpots.clear();
360
361 QList<VideoSpot>& qlSpotList = m_pSpotThread->getSpotList();
362 for( VideoSpot* pActualSpot = qlSpotList.first();
363 pActualSpot; pActualSpot = qlSpotList.next() )
364 {
365 // Check if this spot is compatible with the spot of the
366 // upper left LED
367 if ( pActualSpot->contains( LED1_X, LED1_Y ) )
368 {
369 dX1 = pActualSpot->getX() + (CAMERA_X - LED1_X);
370 dY1 = pActualSpot->getY() + (CAMERA_Y - LED1_Y);
371 dX += dX1; dY += dY1;
372 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY()) );
373 iNumLEDs++;
374 }
375 // Check if this spot is compatible with the spot of the
376 // upper right LED
377 else if ( pActualSpot->contains( LED2_X, LED2_Y ) )
378 {
379 dX2 = pActualSpot->getX() + (CAMERA_X - LED2_X);
380 dY2 = pActualSpot->getY() + (CAMERA_Y - LED2_Y);
381 dX += dX2; dY += dY2;
382 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY()) );
383 iNumLEDs++;
384 }
385 // Check if this spot is compatible with the spot of the
386 // lower left LED
387 else if ( pActualSpot->contains( LED3_X, LED3_Y ) )
388 {
389 dX3 = pActualSpot->getX() + (CAMERA_X - LED3_X);
390 dY3 = pActualSpot->getY() + (CAMERA_Y - LED3_Y);
391 dX += dX3; dY += dY3;
392 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY()) );
393 iNumLEDs++;
394 }
395 // Check if this spot is compatible with the spot of the
396 // lower right LED
397 else if ( pActualSpot->contains( LED4_X, LED4_Y ) )
398 {
399 dX4 = pActualSpot->getX() + (CAMERA_X - LED4_X);
400 dY4 = pActualSpot->getY() + (CAMERA_Y - LED4_Y);
401 dX += dX4; dY += dY4;
402 m_qlLEDs.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY()) );
403 iNumLEDs++;
404 }
405 else
406 m_qlSpots.append( new VideoSpot( pActualSpot->getX(), pActualSpot->getY()) );
407 }
408 if( iNumLEDs != 0)
409 {
410 m_iCenterX = (int) rint(dX / iNumLEDs);
411 m_iCenterY = (int) rint(dY / iNumLEDs);
412// qDebug("Center %d %d", m_iCenterX, m_iCenterY);
413 }
414 qDebug("Center at: %d %d -- with %d LEDs",m_iCenterX, m_iCenterY, iNumLEDs );
415}
Note: See TracBrowser for help on using the repository browser.