FlowWidget.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. // FlowWidget.cpp
  2. #include "FlowWidget.h"
  3. #include "../arffHelper/ArffUtil.h"
  4. #include "Unused.h"
  5. #include <iostream>
  6. #include <limits>
  7. #include <cmath>
  8. using namespace std;
  9. // PUBLIC SLOTS:
  10. void FlowWidget::HandleNewTime(int time)
  11. {
  12. SetCurrentTime(time);
  13. }
  14. // PUBLIC:
  15. FlowWidget::FlowWidget(QWidget *parent) : QWidget(parent),
  16. m_pStream(NULL), m_pArff(NULL),
  17. m_horVector(0), m_verVector(0), m_duration(0)
  18. {
  19. SetCurrentTime(0);
  20. SetInterval(100000); // 100ms
  21. }
  22. FlowWidget::~FlowWidget()
  23. {
  24. if (m_pStream!=NULL)
  25. fclose(m_pStream);
  26. }
  27. QSize FlowWidget::minimumSizeHint() const /*override*/
  28. {
  29. return QSize(160,90);
  30. }
  31. void FlowWidget::SetCurrentTime(int currentTime)
  32. {
  33. m_currentTime = currentTime;
  34. CalculateMinMaxGaze();
  35. // update area
  36. update();
  37. }
  38. void FlowWidget::SetDuration(qint64 duration)
  39. {
  40. m_duration = duration;
  41. }
  42. void FlowWidget::SetMedia(QString pathToFile)
  43. {
  44. ReadFlow(pathToFile.toStdString().c_str());
  45. }
  46. void FlowWidget::SetData(Arff &arff)
  47. {
  48. m_pArff = &arff;
  49. int confInd;
  50. bool res = ArffUtil::GetTXYCindex(m_pArff, m_timeInd, m_xInd, m_yInd, confInd);
  51. UNUSED(confInd);
  52. UNUSED(res);
  53. int rows, columns;
  54. m_pArff->Size(rows, columns);
  55. if (rows<2)
  56. return;
  57. m_meanHorGazeVel = 0;
  58. m_meanVerGazeVel = 0;
  59. for (int i=0; i<rows-1; i++){
  60. m_meanHorGazeVel += abs((*m_pArff)[i][m_xInd]-(*m_pArff)[i+1][m_xInd]) / ((*m_pArff)[i+1][m_timeInd]-(*m_pArff)[i][m_timeInd]);
  61. m_meanVerGazeVel += abs((*m_pArff)[i][m_yInd]-(*m_pArff)[i+1][m_yInd]) / ((*m_pArff)[i+1][m_timeInd]-(*m_pArff)[i][m_timeInd]);
  62. }
  63. m_meanHorGazeVel /= (double)(rows-1);
  64. m_meanVerGazeVel /= (double)(rows-1);
  65. }
  66. void FlowWidget::SetInterval(qint64 interval)
  67. {
  68. m_intervalDuration = interval;
  69. }
  70. // PROTECTED:
  71. void FlowWidget::paintEvent(QPaintEvent *) /*override*/
  72. {
  73. QPainter painter(this);
  74. painter.setRenderHint(QPainter::Antialiasing, true);
  75. PaintFlow(&painter);
  76. PaintGazeRect(&painter);
  77. PaintVelocity(&painter);
  78. PaintLegend(&painter);
  79. }
  80. void FlowWidget::resizeEvent(QResizeEvent *event) /*override*/
  81. {
  82. QWidget::resizeEvent(event);
  83. UpdateRectangle();
  84. }
  85. // PRIVATE:
  86. void FlowWidget::PaintFlow(QPainter *painter)
  87. {
  88. if (CalculateFrameNum() != m_currentFrame){
  89. m_currentFrame = CalculateFrameNum();
  90. DrawImage();
  91. }
  92. painter->drawImage(m_targetRect, m_image, QRect(QPoint(0,0), m_image.size()));
  93. }
  94. void FlowWidget::PaintGazeRect(QPainter *painter)
  95. {
  96. double width = (double)(m_maxGazeX-m_minGazeX)*(double)m_targetRect.width()/(double)m_width;
  97. double height = (double)(m_maxGazeY-m_minGazeY)*(double)m_targetRect.height()/(double)m_height;
  98. double startX = m_targetRect.left() + (double)(m_minGazeX)*(double)m_targetRect.width()/(double)m_width;
  99. double startY = m_targetRect.top() + (double)(m_minGazeY)*(double)m_targetRect.height()/(double)m_height;
  100. painter->setPen(QPen(Qt::black, 4.0*m_targetRect.width()/1000.0));
  101. painter->drawRect(startX, startY,width, height);
  102. }
  103. void FlowWidget::PaintVelocity(QPainter *painter)
  104. {
  105. if (m_pStream==NULL)
  106. return;
  107. // update mean velocity
  108. CalculateMeanVelocity();
  109. QPointF center(m_targetRect.left()+m_targetRect.height()/3.5, m_targetRect.top()+m_targetRect.height()/3.5);
  110. double coorLength = m_targetRect.height()/5.0;
  111. // paint coordinates
  112. painter->setPen(QPen(Qt::black, 2.0*m_targetRect.width()/1000.0));
  113. painter->setBrush(Qt::black);
  114. QPointF points[2];
  115. // x axis
  116. points[0] = center - QPoint(coorLength,0);
  117. points[1] = center + QPoint(coorLength,0);
  118. PaintVector(points, painter);
  119. // y axis
  120. points[0] = center - QPoint(0,coorLength);
  121. points[1] = center + QPoint(0,coorLength);
  122. PaintVector(points, painter);
  123. // paint horizontal velocity component
  124. painter->setPen(QPen(Qt::blue, 2.5*m_targetRect.width()/1000.0));
  125. painter->setBrush(Qt::blue);
  126. points[0] = center;
  127. if (m_horVector > 0)
  128. {
  129. // check limits because threshold for max is 0.7
  130. if (m_horVector/m_normMaxU > 1)
  131. points[1] = center + QPoint(coorLength,0);
  132. else
  133. points[1] = center + QPoint(coorLength*m_horVector/m_normMaxU,0);
  134. }
  135. else
  136. {
  137. if (m_horVector/m_normMinU > 1)
  138. points[1] = center - QPoint(coorLength,0);
  139. else
  140. points[1] = center + QPoint(coorLength*(-1)*m_horVector/m_normMinU,0);
  141. }
  142. //PaintVector(points, painter);
  143. // Store for later
  144. QPointF horComp = points[1];
  145. // paint vertical velocity component
  146. painter->setPen(QPen(Qt::yellow, 2.5*m_targetRect.width()/1000.0));
  147. painter->setBrush(Qt::yellow);
  148. points[0] = center;
  149. if (m_verVector > 0)
  150. {
  151. if (m_verVector/m_normMaxV > 1)
  152. points[1] = center + QPoint(0, coorLength);
  153. else
  154. points[1] = center + QPoint(0, coorLength*m_verVector/m_normMaxV);
  155. }
  156. else
  157. {
  158. if (m_verVector/m_normMinV > 1)
  159. points[1] = center - QPoint(0, coorLength);
  160. else
  161. points[1] = center + QPoint(0, coorLength*(-1)*m_verVector/m_normMinV);
  162. }
  163. //PaintVector(points, painter);
  164. // paint velocity component
  165. painter->setPen(QPen(Qt::red, 3*m_targetRect.width()/1000.0));
  166. painter->setBrush(Qt::red);
  167. points[1] += horComp;
  168. points[1] -= center; // added twice
  169. PaintVector(points, painter);
  170. // paint gaze velocity
  171. double normHorVel = m_horGazeVel/(1.0*m_meanHorGazeVel);
  172. double normVerVel = m_verGazeVel/(1.0*m_meanVerGazeVel);
  173. // keep aspect ratio if both are big
  174. if (abs(normHorVel)>1 && abs(normVerVel)>1)
  175. {
  176. if (abs(normHorVel)>abs(normVerVel))
  177. normVerVel /= abs(normHorVel);
  178. else
  179. normHorVel /= abs(normVerVel);
  180. }
  181. if (abs(normHorVel)>1)
  182. normHorVel /= abs(normHorVel);
  183. if (abs(normVerVel)>1)
  184. normVerVel /= abs(normVerVel);
  185. points[1] = center + QPoint(normHorVel*coorLength,normVerVel*coorLength);
  186. painter->setPen(QPen(QColor(0,0,255,255), 2.5*m_targetRect.width()/1000.0));
  187. painter->setBrush(QBrush(QColor(0,0,255,255)));
  188. PaintVector(points, painter);
  189. }
  190. void FlowWidget::PaintVector(QPointF *points, QPainter *painter)
  191. {
  192. QLineF line(points[0], points[1]);
  193. painter->drawLine(line);
  194. // Draw the arrows
  195. double angle = ::acos(line.dx() / line.length());
  196. double Pi = 3.14159265359;
  197. double arrowSize = (double)m_targetRect.height()/30.0;
  198. if (sqrt(pow(points[0].x()-points[1].x(),2) + pow(points[0].y()-points[1].y(),2)) < arrowSize)
  199. arrowSize = sqrt(pow(points[0].x()-points[1].x(),2) + pow(points[0].y()-points[1].y(),2));
  200. if (line.dy() >= 0)
  201. angle = 2*Pi - angle;
  202. QPointF destArrowP1 = points[1] + QPointF(sin(angle - Pi / 3) * arrowSize,
  203. cos(angle - Pi / 3) * arrowSize);
  204. QPointF destArrowP2 = points[1] + QPointF(sin(angle - Pi + Pi / 3) * arrowSize,
  205. cos(angle - Pi + Pi / 3) * arrowSize);
  206. painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
  207. }
  208. void FlowWidget::PaintLegend(QPainter *painter)
  209. {
  210. int legendHeight = m_targetRect.height()/30.0;
  211. int legendWidth = m_targetRect.width()/10;
  212. QFont font = painter->font();
  213. font.setPointSize(legendHeight/1.5);
  214. painter->setFont(font);
  215. painter->setBrush(QBrush(QColor(255,0,0,160)));
  216. painter->setPen(QPen(QColor(255,0,0,160)));
  217. painter->drawRect(QRect(m_targetRect.left(),m_targetRect.top(), legendWidth, legendHeight));
  218. painter->setPen(QPen(Qt::black));
  219. painter->drawText(QRect(m_targetRect.left(),m_targetRect.top(), legendWidth, legendHeight), 0, "video flow");
  220. painter->setBrush(QBrush(QColor(0,0,255,160)));
  221. painter->setPen(QPen(QColor(0,0,255,160)));
  222. painter->drawRect(QRect(m_targetRect.left(),m_targetRect.top()+legendHeight, legendWidth, legendHeight));
  223. painter->setPen(QPen(Qt::black));
  224. painter->drawText(QRect(m_targetRect.left(),m_targetRect.top()+legendHeight, legendWidth*1.5, legendHeight), 0, "gaze velocity");
  225. }
  226. void FlowWidget::ReadFlow(const char *filename, float normLevel /*=0.7*/)
  227. {
  228. // close stream if open
  229. if (m_pStream != NULL)
  230. fclose(m_pStream);
  231. // open new file
  232. m_pStream = fopen(filename, "rb");
  233. // return if not opened
  234. if (m_pStream == NULL)
  235. return;
  236. // read data about flow
  237. size_t res;
  238. res = fread(&m_numOfFrames, sizeof(int), 1, m_pStream);
  239. res = fread(&m_width, sizeof(int), 1, m_pStream);
  240. res = fread(&m_height, sizeof(int), 1, m_pStream);
  241. res = fread(&m_storedWidth, sizeof(int), 1, m_pStream);
  242. res = fread(&m_storedHeight, sizeof(int), 1, m_pStream);
  243. // allocate QImage
  244. m_image = QImage(m_storedWidth, m_storedHeight, QImage::Format_RGB32);
  245. // initialize to fixed color
  246. unsigned char *pImageData = m_image.bits(); // BGRA format
  247. for (int i=0; i<m_storedWidth*m_storedHeight*4; i++)
  248. pImageData[i] = 220;
  249. // update rectangle
  250. UpdateRectangle();
  251. // read max min for each frame
  252. float minU, maxU, minV, maxV;
  253. for (int i=0; i<m_numOfFrames; i++)
  254. {
  255. res = fread(&minU, sizeof(float), 1, m_pStream);
  256. res = fread(&maxU, sizeof(float), 1, m_pStream);
  257. res = fread(&minV, sizeof(float), 1, m_pStream);
  258. res = fread(&maxV, sizeof(float), 1, m_pStream);
  259. m_vMinU.push_back(minU);
  260. m_vMaxU.push_back(maxU);
  261. m_vMinV.push_back(minV);
  262. m_vMaxV.push_back(maxV);
  263. fseek(m_pStream, 2*m_storedWidth*m_storedHeight*sizeof(short int), SEEK_CUR);
  264. }
  265. UNUSED(res);
  266. // reset seek to first frame
  267. fseek(m_pStream, 5*sizeof(int), SEEK_SET);
  268. m_currentFrame = 0;
  269. m_ncols = 0;
  270. // calculate normalization factor as 70% of min-max samples
  271. vector<float> tmpVec;
  272. // check limits
  273. normLevel = normLevel <= 0.0 ? 0.01: normLevel;
  274. normLevel = normLevel > 1.0? 1.0: normLevel;
  275. int threshold = normLevel*(m_vMinU.size()-1);
  276. tmpVec = m_vMinU;
  277. sort(tmpVec.begin(), tmpVec.end(), greater<float>()); // sort negative in descending order
  278. m_normMinU = tmpVec[threshold];
  279. tmpVec = m_vMaxU;
  280. sort(tmpVec.begin(), tmpVec.end());
  281. m_normMaxU = tmpVec[threshold];
  282. tmpVec = m_vMinV;
  283. sort(tmpVec.begin(), tmpVec.end(), greater<float>()); // sort negative in descending order
  284. m_normMinV = tmpVec[threshold];
  285. tmpVec = m_vMaxV;
  286. sort(tmpVec.begin(), tmpVec.end());
  287. m_normMaxV = tmpVec[threshold];
  288. }
  289. int FlowWidget::CalculateFrameNum()
  290. {
  291. int frameNum = (int)((double)m_numOfFrames*(double)m_currentTime/(double)m_duration);
  292. if (frameNum < 0)
  293. return 0;
  294. if (frameNum > m_numOfFrames-1)
  295. return m_numOfFrames-1;
  296. return frameNum;
  297. }
  298. void FlowWidget::DrawImage()
  299. {
  300. if (m_pStream==NULL)
  301. return;
  302. // move file pointer to correct position
  303. long int frameOffset = 5*sizeof(int) + m_currentFrame*(4*sizeof(float) + 2*m_storedWidth*m_storedHeight*sizeof(short int));
  304. fseek(m_pStream, frameOffset, SEEK_SET);
  305. // skip max-min information
  306. fseek(m_pStream, 4*sizeof(float), SEEK_CUR);
  307. short int u,v;
  308. float hor, ver;
  309. int rgb[3];
  310. int pointerImage = 0;
  311. unsigned char *pImageData = m_image.bits(); // BGRA format
  312. size_t res;
  313. for (int y=0; y<m_storedHeight; y++)
  314. {
  315. for (int x=0; x<m_storedWidth; x++)
  316. {
  317. res = fread(&u, sizeof(short int), 1, m_pStream);
  318. res = fread(&v, sizeof(short int), 1, m_pStream);
  319. // without normalization
  320. hor = (float)u*m_vMinU[m_currentFrame]/(float)numeric_limits<short int>::min();
  321. ver = (float)v*m_vMinV[m_currentFrame]/(float)numeric_limits<short int>::min();
  322. ComputeColor(hor, ver, rgb);
  323. pImageData[pointerImage+2] = rgb[0];
  324. pImageData[pointerImage+1] = rgb[1];
  325. pImageData[pointerImage+0] = rgb[2];
  326. pointerImage += 4;
  327. }
  328. }
  329. UNUSED(res);
  330. }
  331. // The code of the folowing 3 function was based on
  332. // http://vision.middlebury.edu/flow/data/flow-code.zip/colorcode.cpp
  333. void FlowWidget::SetCols(int r, int g, int b, int k)
  334. {
  335. m_colorWheel[k][0] = r;
  336. m_colorWheel[k][1] = g;
  337. m_colorWheel[k][2] = b;
  338. }
  339. void FlowWidget::MakeColorWheel()
  340. {
  341. // relative lengths of color transitions:
  342. // these are chosen based on perceptual similarity
  343. // (e.g. one can distinguish more shades between red and yellow
  344. // than between yellow and green)
  345. int RY = 15;
  346. int YG = 6;
  347. int GC = 4;
  348. int CB = 11;
  349. int BM = 13;
  350. int MR = 6;
  351. m_ncols = RY + YG + GC + CB + BM + MR;
  352. if (m_ncols > MAXCOLS)
  353. exit(1);
  354. int i;
  355. int k = 0;
  356. for (i = 0; i < RY; i++) SetCols(255, 255*i/RY, 0, k++);
  357. for (i = 0; i < YG; i++) SetCols(255-255*i/YG, 255, 0, k++);
  358. for (i = 0; i < GC; i++) SetCols(0, 255, 255*i/GC, k++);
  359. for (i = 0; i < CB; i++) SetCols(0, 255-255*i/CB, 255, k++);
  360. for (i = 0; i < BM; i++) SetCols(255*i/BM, 0, 255, k++);
  361. for (i = 0; i < MR; i++) SetCols(255, 0, 255-255*i/MR, k++);
  362. }
  363. void FlowWidget::ComputeColor(float u, float v, int *rgb)
  364. {
  365. if (m_ncols == 0)
  366. MakeColorWheel();
  367. float rad = sqrt(u * u + v * v);
  368. float a = atan2(-v, -u) / M_PI;
  369. float fk = (a + 1.0) / 2.0 * (m_ncols-1);
  370. int k0 = (int)fk;
  371. int k1 = (k0 + 1) % m_ncols;
  372. float f = fk - k0;
  373. //f = 0; // uncomment to see original color wheel
  374. float col0, col;
  375. for (int b = 0; b < 3; b++) {
  376. col0 = m_colorWheel[k0][b] / 255.0;
  377. col = m_colorWheel[k1][b] / 255.0;
  378. col = (1 - f) * col0 + f * col;
  379. if (rad <= 1)
  380. col = 1 - rad * (1 - col); // increase saturation with radius
  381. else
  382. col *= .75; // out of range
  383. rgb[b] = (int)(255.0 * col);
  384. }
  385. }
  386. void FlowWidget::UpdateRectangle()
  387. {
  388. QSize size = m_image.size();
  389. size.scale(this->size(), Qt::KeepAspectRatio);
  390. m_targetRect = QRect(QPoint(0,0), size);
  391. m_targetRect.moveCenter(this->rect().center());
  392. }
  393. void FlowWidget::CalculateMinMaxGaze()
  394. {
  395. if (m_pArff == NULL)
  396. return;
  397. int rows, columns;
  398. m_pArff->Size(rows, columns);
  399. UNUSED(columns);
  400. if (rows == 0)
  401. return;
  402. m_minGazeX = numeric_limits<int>::max();
  403. m_minGazeY = numeric_limits<int>::max();
  404. m_maxGazeX = numeric_limits<int>::min();
  405. m_maxGazeY = numeric_limits<int>::min();
  406. m_horGazeVel = 0.0;
  407. m_verGazeVel = 0.0;
  408. int counter = 0;
  409. for (int i=0; i<rows-1; i++)
  410. {
  411. if ((*m_pArff)[i][m_timeInd]>m_currentTime-m_intervalDuration && (*m_pArff)[i][m_timeInd]<m_currentTime+m_intervalDuration)
  412. {
  413. if ((*m_pArff)[i][m_xInd] < m_minGazeX)
  414. m_minGazeX = (*m_pArff)[i][m_xInd];
  415. if ((*m_pArff)[i][m_xInd] > m_maxGazeX)
  416. m_maxGazeX = (*m_pArff)[i][m_xInd];
  417. if ((*m_pArff)[i][m_yInd] < m_minGazeY)
  418. m_minGazeY = (*m_pArff)[i][m_yInd];
  419. if ((*m_pArff)[i][m_yInd] > m_maxGazeY)
  420. m_maxGazeY = (*m_pArff)[i][m_yInd];
  421. // calculate velocity
  422. m_horGazeVel += ((*m_pArff)[i+1][m_xInd]-(*m_pArff)[i][m_xInd]) / ((*m_pArff)[i+1][m_timeInd]-(*m_pArff)[i][m_timeInd]);
  423. m_verGazeVel += ((*m_pArff)[i+1][m_yInd]-(*m_pArff)[i][m_yInd]) / ((*m_pArff)[i+1][m_timeInd]-(*m_pArff)[i][m_timeInd]);
  424. counter++;
  425. }
  426. }
  427. if (counter > 0)
  428. {
  429. m_horGazeVel /= (double)counter;
  430. m_verGazeVel /= (double)counter;
  431. }
  432. if (m_minGazeX < 0)
  433. m_minGazeX = 0;
  434. if (m_minGazeX >= m_width)
  435. m_minGazeX = m_width-1;
  436. if (m_maxGazeX < 0)
  437. m_maxGazeX = 0;
  438. if (m_maxGazeX >= m_width)
  439. m_maxGazeX = m_width-1;
  440. if (m_minGazeY < 0)
  441. m_minGazeY = 0;
  442. if (m_minGazeY >= m_height)
  443. m_minGazeY = m_height-1;
  444. if (m_maxGazeY < 0)
  445. m_maxGazeY = 0;
  446. if (m_maxGazeY >= m_height)
  447. m_maxGazeY = m_height-1;
  448. }
  449. void FlowWidget::CalculateMeanVelocity()
  450. {
  451. if (m_pStream==NULL)
  452. return;
  453. long int frameOffset = 5*sizeof(int) + m_currentFrame*(4*sizeof(float) + 2*m_storedWidth*m_storedHeight*sizeof(short int));
  454. fseek(m_pStream, frameOffset, SEEK_SET);
  455. // skip max-min information
  456. fseek(m_pStream, 4*sizeof(float), SEEK_CUR);
  457. short int u,v;
  458. int rgb[3];
  459. int pointerImage = 0;
  460. unsigned char *pImageData = m_image.bits(); // BGRA format
  461. int yStart = m_minGazeY*(double)m_storedHeight/(double)m_height;
  462. int yEnd = m_minGazeY*(double)m_storedHeight/(double)m_height;
  463. int xStart = m_minGazeX*(double)m_storedWidth/(double)m_width;
  464. int xEnd = m_maxGazeX*(double)m_storedWidth/(double)m_width;
  465. m_horVector = 0;
  466. m_verVector = 0;
  467. // skip first lines of the image
  468. fseek(m_pStream, 2*m_storedWidth*yStart*sizeof(short int), SEEK_CUR);
  469. size_t res;
  470. for (int y=0; y<yEnd-yStart+1; y++){ //** check +1 for corner cases
  471. for (int x=0; x<m_storedWidth; x++){
  472. res = fread(&u, sizeof(short int), 1, m_pStream);
  473. res = fread(&v, sizeof(short int), 1, m_pStream);
  474. // process data
  475. if (x>=xStart && x<=xEnd)
  476. {
  477. if (u < 0)
  478. m_horVector += (double)u*m_vMinU[m_currentFrame]/(double)numeric_limits<short int>::min();
  479. else
  480. m_horVector += (double)u*m_vMaxU[m_currentFrame]/(double)numeric_limits<short int>::max();
  481. if (v < 0)
  482. m_verVector += (double)v*m_vMinV[m_currentFrame]/(double)numeric_limits<short int>::min();
  483. else
  484. m_verVector += (double)v*m_vMaxV[m_currentFrame]/(double)numeric_limits<short int>::max();
  485. }
  486. pImageData[pointerImage+2] = rgb[0];
  487. pImageData[pointerImage+1] = rgb[1];
  488. pImageData[pointerImage+0] = rgb[2];
  489. pointerImage += 4;
  490. }
  491. }
  492. UNUSED(res);
  493. m_horVector /= (yEnd-yStart+1)*(xEnd-xStart+1);
  494. m_verVector /= (yEnd-yStart+1)*(xEnd-xStart+1);
  495. }