BitmapToolkit Scol plugin
Prerequisites.h
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
25#ifndef __BTK_PREREQUISITES_H__
26#define __BTK_PREREQUISITES_H__
27
28#include <scolPlugin.h>
29#include <scolMemoryHelper.hpp>
30
31#ifdef _WIN32
32#include <tchar.h>
33#endif
34
35#include <opencv2/opencv.hpp>
36#include <math.h>
37#include <list>
38#include <vector>
39#include <string>
40#include <boost/filesystem/operations.hpp>
41
42// We can safely disable this warning that occurs in aruco library.
43#pragma warning(disable : 4290)
44
45// MlToolKit variables
46#define SCOL_ML_TRAINING_FINISHED_CB 0
48
49#define SCOL_ML_DETECTION_CB 1
50extern int WM_ML_DETECTION;
51
52#ifdef _DEBUG
53//#define _SCOL_DEBUG_
54#endif
55
56// ToolKit loading functions
57int LoadMathToolkit(mmachine m);
58int LoadBitmapToolKit(mmachine m);
59int LoadCaptureToolkit(mmachine m);
60int LoadArToolkit(mmachine m);
61int LoadMlToolkit(mmachine m);
62int LoadMediaPlayerToolkit(mmachine m);
65
66// disable warning for aruco
67#pragma warning(disable : 4290)
68
69int Random(int mi, int mx);
70
72// Vector of 2 float components
74{
75public:
77 {
78 x = 0.0f;
79 y = 0.0f;
80 }
81
82 Vector2(float xx, float yy)
83 {
84 x = xx;
85 y = yy;
86 }
87
88 //-----------------------------------------------------------------------
89 // Utility
91 {
92 return sqrtf(x*x + y * y);
93 }
94
96 {
97 float magnitude = GetMagnitude();
98 if (magnitude == 0.0f)
99 return Vector2(0.0f, 0.0f);
100 return Vector2(x / magnitude, y / magnitude);
101 }
102
103 float DotProduct(Vector2 other)
104 {
105 return x * other.x + y * other.y;
106 }
107
108 //-----------------------------------------------------------------------
109 // Unary operators
111 {
112 return Vector2(-x, -y);
113 }
114
116 {
117 return Vector2(x + other.x, y + other.y);
118 }
119
121 {
122 return Vector2(x - other.x, y - other.y);
123 }
124
125 Vector2 operator*=(float scalar)
126 {
127 return Vector2(x * scalar, y * scalar);
128 }
129
130 Vector2 operator/=(float scalar)
131 {
132 return Vector2(x / scalar, y / scalar);
133 }
134
135protected:
136private:
137
138public:
139 float x;
140 float y;
141protected:
142private:
143};
144
145//-----------------------------------------------------------------------
146// Vector2 binary operators
148{
149 return Vector2(u.x + v.x, u.y + v.y);
150}
151
153{
154 return u + (-v);
155}
156inline Vector2 operator*(Vector2 u, float scalar)
157{
158 Vector2 result = u;
159 result *= scalar;
160 return result;
161}
162inline Vector2 operator*(float scalar, Vector2 u)
163{
164 return u * scalar;
165}
166inline Vector2 operator/(Vector2 u, float scalar)
167{
168 Vector2 result = u;
169 result /= scalar;
170 return result;
171}
173
175// Vector with 3 float components
177{
178public:
180 {
181 x = 0.0f;
182 y = 0.0f;
183 z = 0.0f;
184 }
185
186 Vector3(float xx, float yy, float zz)
187 {
188 x = xx;
189 y = yy;
190 z = zz;
191 }
192
193 //-----------------------------------------------------------------------
194 // Utility
196 {
197 return sqrtf(x*x + y * y + z * z);
198 }
199
201 {
202 float magnitude = GetMagnitude();
203 if (magnitude == 0.0f)
204 return Vector3(0.0f, 0.0f, 0.0f);
205 return Vector3(x / magnitude, y / magnitude, z / magnitude);
206 }
207
208 float DotProduct(Vector3 other)
209 {
210 return x * other.x + y * other.y + z * other.z;
211 }
212
214 {
215 return Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x);
216 }
217
218 //-----------------------------------------------------------------------
219 // Unary operators
221 {
222 return Vector3(-x, -y, -z);
223 }
224
226 {
227 return Vector3(x + other.x, y + other.y, z + other.z);
228 }
229
231 {
232 return Vector3(x - other.x, y - other.y, z - other.z);
233 }
234
235 Vector3 operator*=(float scalar)
236 {
237 return Vector3(x * scalar, y * scalar, z * scalar);
238 }
239
240 Vector3 operator/=(float scalar)
241 {
242 return Vector3(x / scalar, y / scalar, z / scalar);
243 }
244
245protected:
246private:
247
248public:
249 float x;
250 float y;
251 float z;
252protected:
253private:
254};
255
256//-----------------------------------------------------------------------
257// Vector3 binary operators
259{
260 return Vector3(u.x + v.x, u.y + v.y, u.z + v.z);
261}
262
264{
265 return u + (-v);
266}
267inline Vector3 operator*(Vector3 u, float scalar)
268{
269 return Vector3(u.x * scalar, u.y * scalar, u.z * scalar);
270}
271inline Vector3 operator*(float scalar, Vector3 u)
272{
273 return Vector3(u.x * scalar, u.y * scalar, u.z * scalar);
274}
275inline Vector3 operator/(Vector3 u, float scalar)
276{
277 return Vector3(u.x / scalar, u.y / scalar, u.z / scalar);
278}
280
282// BtQuaternion
284{
285public:
287 {
288 w = 1.0f;
289 x = 0.0f;
290 y = 0.0f;
291 z = 0.0f;
292 }
293
294 BtQuaternion(float ww, float xx, float yy, float zz)
295 {
296 w = ww;
297 x = xx;
298 y = yy;
299 z = zz;
300 }
301
302 BtQuaternion(float quat[4])
303 {
304 w = quat[0];
305 x = quat[1];
306 y = quat[2];
307 z = quat[3];
308 }
309
310 BtQuaternion(double quat[4])
311 {
312 w = (float)quat[0];
313 x = (float)quat[1];
314 y = (float)quat[2];
315 z = (float)quat[3];
316 }
317
318 static const BtQuaternion IDENTITY;
319
320 //-----------------------------------------------------------------------
321 inline bool operator== (const BtQuaternion& rhs) const
322 {
323 return (rhs.x == x) && (rhs.y == y) &&
324 (rhs.z == z) && (rhs.w == w);
325 }
326 //-----------------------------------------------------------------------
327 inline bool operator!= (const BtQuaternion& rhs) const
328 {
329 return !operator==(rhs);
330 }
331 //-----------------------------------------------------------------------
333 {
334 return BtQuaternion(w + rkQ.w, x + rkQ.x, y + rkQ.y, z + rkQ.z);
335 }
336 //-----------------------------------------------------------------------
338 {
339 return BtQuaternion(w - rkQ.w, x - rkQ.x, y - rkQ.y, z - rkQ.z);
340 }
341 //-----------------------------------------------------------------------
342 BtQuaternion operator-() const { return BtQuaternion(-w, -x, -y, -z); }
343 //-----------------------------------------------------------------------
345 {
346 // NOTE: Multiplication is not generally commutative, so in most
347 // cases p*q != q*p.
348
349 return BtQuaternion
350 (
351 w * rkQ.w - x * rkQ.x - y * rkQ.y - z * rkQ.z,
352 w * rkQ.x + x * rkQ.w + y * rkQ.z - z * rkQ.y,
353 w * rkQ.y + y * rkQ.w + z * rkQ.x - x * rkQ.z,
354 w * rkQ.z + z * rkQ.w + x * rkQ.y - y * rkQ.x
355 );
356 }
357 //-----------------------------------------------------------------------
358 BtQuaternion operator*(float s) const
359 {
360 return BtQuaternion(s * w, s * x, s * y, s * z);
361 }
362 //-----------------------------------------------------------------------
363 friend BtQuaternion operator*(float s, const BtQuaternion& q)
364 {
365 return q * s;
366 }
367 //-----------------------------------------------------------------------
369 {
370 float fNorm = w * w + x * x + y * y + z * z;
371 if (fNorm > 0.0)
372 {
373 float fInvNorm = 1.0f / fNorm;
374 return BtQuaternion(w*fInvNorm, -x * fInvNorm, -y * fInvNorm, -z * fInvNorm);
375 }
376 else
377 {
378 // return an invalid result to flag the error
379 return BtQuaternion();
380 }
381 }
382 //-----------------------------------------------------------------------
383 Vector3 operator* (const Vector3& v) const
384 {
385 // nVidia SDK implementation
386 Vector3 uv, uuv;
387 Vector3 qvec(x, y, z);
388 uv = qvec.CrossProduct(v);
389 uuv = qvec.CrossProduct(uv);
390 uv *= (2.0f * w);
391 uuv *= 2.0f;
392
393 return v + uv + uuv;
394 }
395 //-----------------------------------------------------------------------
396 static BtQuaternion FromRotationMatrix(double rotMatrix[16], bool reverseX = false, bool reverseY = true)
397 {
398 // Origin is double numbers, target is float. Convert from double to float as late as possible, so do not write "f" suffix belong to floating numbers!
399 BtQuaternion mQuat;
400
401 //revert Y axis
402 double kRot[3][3];
403 kRot[0][0] = rotMatrix[0];
404 kRot[0][1] = rotMatrix[4];
405 kRot[0][2] = rotMatrix[8];
406
407 if (reverseY)
408 {
409 kRot[1][0] = -rotMatrix[1];
410 kRot[1][1] = -rotMatrix[5];
411 kRot[1][2] = -rotMatrix[9];
412 }
413 else
414 {
415 kRot[1][0] = rotMatrix[1];
416 kRot[1][1] = rotMatrix[5];
417 kRot[1][2] = rotMatrix[9];
418 }
419
420 kRot[2][0] = rotMatrix[2];
421 kRot[2][1] = rotMatrix[6];
422 kRot[2][2] = rotMatrix[10];
423
424 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
425 // article "BtQuaternion Calculus and Fast Animation".
426 double fTrace = kRot[0][0] + kRot[1][1] + kRot[2][2];
427 double fRoot;
428
429 if (fTrace > 0.0)
430 {
431 // |w| > 1/2, may as well choose w > 1/2
432 fRoot = sqrt(fTrace + 1.0); // 2w
433 mQuat.w = static_cast<float>(0.5*fRoot);
434 fRoot = 0.5 / fRoot; // 1/(4w)
435 mQuat.x = static_cast<float>((kRot[2][1] - kRot[1][2])*fRoot);
436 mQuat.y = static_cast<float>((kRot[0][2] - kRot[2][0])*fRoot);
437 mQuat.z = static_cast<float>((kRot[1][0] - kRot[0][1])*fRoot);
438 }
439 else
440 {
441 // |w| <= 1/2
442 static size_t s_iNext[3] = { 1, 2, 0 };
443 size_t i = 0;
444 if (kRot[1][1] > kRot[0][0])
445 i = 1;
446 if (kRot[2][2] > kRot[i][i])
447 i = 2;
448
449 size_t j = s_iNext[i];
450 size_t k = s_iNext[j];
451
452 fRoot = sqrt(kRot[i][i] - kRot[j][j] - kRot[k][k] + 1.0);
453 float* apkQuat[3] = { &mQuat.x, &mQuat.y, &mQuat.z };
454 *apkQuat[i] = static_cast<float>(0.5*fRoot);
455 fRoot = 0.5 / fRoot;
456 mQuat.w = static_cast<float>((kRot[k][j] - kRot[j][k])*fRoot);
457 *apkQuat[j] = static_cast<float>((kRot[j][i] + kRot[i][j])*fRoot);
458 *apkQuat[k] = static_cast<float>((kRot[k][i] + kRot[i][k])*fRoot);
459 }
460
461 if (reverseX)
462 {
463 mQuat.x = -mQuat.x;
464 mQuat.w = -mQuat.w;
465 }
466
467 //normalize
468 float len = mQuat.w*mQuat.w + mQuat.x*mQuat.x + mQuat.y*mQuat.y + mQuat.z*mQuat.z;
469 float factor = 1.0f / sqrt(len);
470 mQuat.w *= factor;
471 mQuat.x *= factor;
472 mQuat.y *= factor;
473 mQuat.z *= factor;
474
475 return mQuat;
476 }
477 //-----------------------------------------------------------------------
478 float Dot(const BtQuaternion& rkQ) const
479 {
480 return w * rkQ.w + x * rkQ.x + y * rkQ.y + z * rkQ.z;
481 }
482 //-----------------------------------------------------------------------
483 float Norm() const { return sqrt(w * w + x * x + y * y + z * z); }
484 //-----------------------------------------------------------------------
485 float normalise(void)
486 {
487 float len = Norm();
488 *this = 1.0f / len * *this;
489 return len;
490 }
491 //-----------------------------------------------------------------------
492 static BtQuaternion Slerp(float fT, const BtQuaternion& rkP,
493 const BtQuaternion& rkQ, bool shortestPath)
494 {
495 float fCos = rkP.Dot(rkQ);
496 BtQuaternion rkT;
497
498 // Do we need to invert rotation?
499 if (fCos < 0.0f && shortestPath)
500 {
501 fCos = -fCos;
502 rkT = -rkQ;
503 }
504 else
505 {
506 rkT = rkQ;
507 }
508
509 if (fabs(fCos) < 1 - 1e-03)
510 {
511 // Standard case (slerp)
512 float fSin = sqrt(1 - (fCos * fCos));
513 float fAngle = std::atan2(fSin, fCos);
514 float fInvSin = 1.0f / fSin;
515 float fCoeff0 = std::sin((1.0f - fT) * fAngle) * fInvSin;
516 float fCoeff1 = std::sin(fT * fAngle) * fInvSin;
517 return fCoeff0 * rkP + fCoeff1 * rkT;
518 }
519 else
520 {
521 // There are two situations:
522 // 1. "rkP" and "rkQ" are very close (fCos ~= +1), so we can do a linear
523 // interpolation safely.
524 // 2. "rkP" and "rkQ" are almost inverse of each other (fCos ~= -1), there
525 // are an infinite number of possibilities interpolation. but we haven't
526 // have method to fix this case, so just use linear interpolation here.
527 BtQuaternion t = (1.0f - fT) * rkP + fT * rkT;
528 // taking the complement requires renormalisation
529 t.normalise();
530 return t;
531 }
532 }
533protected:
534private:
535
536public:
537 float x;
538 float y;
539 float z;
540 float w;
541protected:
542private:
543};
544
545
547
549{
550private:
551 std::vector<cv::Point2f> m_filteredPoints;
552 std::vector<cv::Point2f> m_prevPoints;
553 std::vector<cv::Point2f> m_prevfilteredPoints;
554 std::vector<cv::Point2f> m_pointsTrend;
555 float m_fSmoothing;
556 float m_fCorrection;
557 float m_fPrediction;
558 float m_fJitterRadius;
559 float m_fMaxDeviationRadius;
560 int m_dwFrameCount;
561
562public:
565
566 void Init(float fSmoothing = 0.25f, float fCorrection = 0.25f, float fPrediction = 0.25f, float fJitterRadius = 0.03f, float fMaxDeviationRadius = 0.05f)
567 {
568 m_fMaxDeviationRadius = fMaxDeviationRadius; // Size of the max prediction radius Can snap back to noisy data when too high
569 m_fSmoothing = fSmoothing; // How much smothing will occur. Will lag when too high
570 m_fCorrection = fCorrection; // How much to correct back from prediction. Can make things springy
571 m_fPrediction = fPrediction; // Amount of prediction into the future to use. Can over shoot when too high
572 m_fJitterRadius = fJitterRadius; // Size of the radius where jitter is removed. Can do too much smoothing when too high
573
574 Reset();
575 }
576
577 void Shutdown()
578 {
579 }
580
581 void Reset()
582 {
583 m_dwFrameCount = 0;
584 m_filteredPoints.clear();
585 m_prevPoints.clear();
586 m_prevfilteredPoints.clear();
587 m_pointsTrend.clear();
588 for (unsigned int k = 0; k < 4; ++k)
589 {
590 m_filteredPoints.push_back(cv::Point2f(0.0f, 0.0f));
591 m_prevPoints.push_back(cv::Point2f(0.0f, 0.0f));
592 m_prevfilteredPoints.push_back(cv::Point2f(0.0f, 0.0f));
593 m_pointsTrend.push_back(cv::Point2f(0.0f, 0.0f));
594 }
595 }
596
597 void Update(std::vector<cv::Point2f> points)
598 {
599 cv::Point2f diffPoints;
600 std::vector<cv::Point2f> trendPoints;
601 float fDiff;
602
603 for (unsigned int k = 0; k < 4; ++k)
604 {
605 trendPoints.push_back(cv::Point2f(0.0f, 0.0f));
606 }
607
608 // Initial start values
609 if (m_dwFrameCount == 0)
610 {
611 for (unsigned int i = 0; i < 4; i++)
612 {
613 m_filteredPoints[i] = points[i];
614 }
615 m_dwFrameCount++;
616 }
617 else if (m_dwFrameCount == 1)
618 {
619 for (unsigned int i = 0; i < 4; i++)
620 {
621 m_filteredPoints[i] = points[i] + m_prevPoints[i];
622 m_filteredPoints[i].x *= 0.5f;
623 m_filteredPoints[i].y *= 0.5f;
624
625 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
626
627 cv::Point2f cdiff = diffPoints;
628 cdiff.x *= m_fCorrection;
629 cdiff.y *= m_fCorrection;
630
631 cv::Point2f pdiff = m_pointsTrend[i];
632 pdiff.x *= 1.0f - m_fCorrection;
633 pdiff.y *= 1.0f - m_fCorrection;
634 trendPoints[i] = cdiff + pdiff;
635 }
636
637 m_dwFrameCount++;
638 }
639 else
640 {
641 for (unsigned int i = 0; i < 4; i++)
642 {
643 diffPoints = points[i] - m_prevfilteredPoints[i];
644
645 fDiff = fabs(sqrt(diffPoints.x * diffPoints.x + diffPoints.y * diffPoints.y));
646 if (fDiff <= m_fJitterRadius)
647 {
648 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
649
650 cv::Point2f cVal = points[i];
651 cVal.x *= fDiff / m_fJitterRadius;
652 cVal.y *= fDiff / m_fJitterRadius;
653
654 cv::Point2f pVal = m_prevfilteredPoints[i];
655 pVal.x *= 1.0f - fDiff / m_fJitterRadius;
656 pVal.y *= 1.0f - fDiff / m_fJitterRadius;
657 m_filteredPoints[i] = cVal + pVal;
658 }
659 else
660 {
661 m_filteredPoints[i] = points[i];
662 }
663
664 // Now the double exponential smoothing filter
665 cv::Point2f cVal = m_filteredPoints[i];
666 cVal.x *= 1.0f - m_fSmoothing;
667 cVal.y *= 1.0f - m_fSmoothing;
668
669 cv::Point2f pVal = m_prevfilteredPoints[i] + m_pointsTrend[i];
670 pVal.x *= m_fSmoothing;
671 pVal.y *= m_fSmoothing;
672 m_filteredPoints[i] = cVal + pVal;
673
674 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
675
676 cVal = diffPoints;
677 cVal.x *= m_fCorrection;
678 cVal.y *= m_fCorrection;
679
680 pVal = m_pointsTrend[i];
681 pVal.x *= 1.0f - m_fCorrection;
682 pVal.y *= 1.0f - m_fCorrection;
683
684 trendPoints[i] = cVal + pVal;
685
686 // Predict into the future to reduce latency
687 cVal = trendPoints[i];
688 cVal.x *= m_fPrediction;
689 cVal.y *= m_fPrediction;
690
691 cv::Point2f predictedPoint = m_filteredPoints[i] + cVal;
692
693 // Check that we are not too far away from raw data
694 diffPoints = predictedPoint - points[i];
695 fDiff = fabs(sqrt(diffPoints.x * diffPoints.x + diffPoints.y * diffPoints.y));
696
697 if (fDiff > m_fMaxDeviationRadius)
698 {
699 cVal = predictedPoint;
700 cVal.x *= m_fMaxDeviationRadius / fDiff;
701 cVal.y *= m_fMaxDeviationRadius / fDiff;
702
703 pVal = points[i];
704 pVal.x *= 1.0f - m_fMaxDeviationRadius / fDiff;
705 pVal.y *= 1.0f - m_fMaxDeviationRadius / fDiff;
706
707 predictedPoint = cVal + pVal;
708 }
709
710 m_filteredPoints[i] = predictedPoint;
711 }
712 }
713
714 for (unsigned int i = 0; i < 4; i++)
715 {
716 m_prevfilteredPoints[i] = m_filteredPoints[i];
717 m_prevPoints[i] = points[i];
718 m_pointsTrend[i] = trendPoints[i];
719 }
720 }
721
722 std::vector<cv::Point2f> GetFilteredPoints()
723 {
724 return m_filteredPoints;
725 }
726};
727
728
730{
731private:
732 std::vector<double> m_filteredPoints;
733 std::vector<double> m_prevPoints;
734 std::vector<double> m_prevfilteredPoints;
735 std::vector<double> m_pointsTrend;
736 float m_fSmoothing;
737 float m_fCorrection;
738 float m_fPrediction;
739 float m_fJitterRadius;
740 float m_fMaxDeviationRadius;
741 int m_dwFrameCount;
742
743public:
746
747 void Init(float fSmoothing = 0.25f, float fCorrection = 0.25f, float fPrediction = 0.25f, float fJitterRadius = 0.03f, float fMaxDeviationRadius = 0.05f)
748 {
749 m_fMaxDeviationRadius = fMaxDeviationRadius; // Size of the max prediction radius Can snap back to noisy data when too high
750 m_fSmoothing = fSmoothing; // How much smothing will occur. Will lag when too high
751 m_fCorrection = fCorrection; // How much to correct back from prediction. Can make things springy
752 m_fPrediction = fPrediction; // Amount of prediction into the future to use. Can over shoot when too high
753 m_fJitterRadius = fJitterRadius; // Size of the radius where jitter is removed. Can do too much smoothing when too high
754
755 Reset();
756 }
757
758 void Shutdown()
759 {
760 }
761
762 void Reset()
763 {
764 m_dwFrameCount = 0;
765 m_filteredPoints.clear();
766 m_prevPoints.clear();
767 m_prevfilteredPoints.clear();
768 m_pointsTrend.clear();
769 }
770
771 void Update(std::vector<double> points)
772 {
773 double diffPoints;
774 std::vector<double> trendPoints;
775 float fDiff;
776
777 if (points.size() != m_filteredPoints.size())
778 {
779 m_filteredPoints = points;
780 m_prevPoints = points;
781 m_prevfilteredPoints = points;
782 m_pointsTrend = points;
783
784 /*for (unsigned int k = 0; k < points.size(); ++k)
785 {
786 m_filteredPoints.push_back(0.0);
787 m_prevPoints.push_back(0.0);
788 m_prevfilteredPoints.push_back(0.0);
789 m_pointsTrend.push_back(0.0);
790 }*/
791 }
792
793 for (unsigned int k = 0; k < points.size(); ++k)
794 {
795 trendPoints.push_back(0.0);
796 }
797
798 // Initial start values
799 if (m_dwFrameCount == 0)
800 {
801 for (unsigned int i = 0; i < points.size(); i++)
802 {
803 m_filteredPoints[i] = points[i];
804 }
805 m_dwFrameCount++;
806 }
807 else if (m_dwFrameCount == 1)
808 {
809 for (unsigned int i = 0; i < points.size(); i++)
810 {
811 m_filteredPoints[i] = points[i] + m_prevPoints[i];
812 m_filteredPoints[i] *= 0.5f;
813
814 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
815
816 double cdiff = diffPoints;
817 cdiff *= m_fCorrection;
818
819 double pdiff = m_pointsTrend[i];
820 pdiff *= 1.0f - m_fCorrection;
821 trendPoints[i] = cdiff + pdiff;
822 }
823
824 m_dwFrameCount++;
825 }
826 else
827 {
828 for (unsigned int i = 0; i < points.size(); i++)
829 {
830 diffPoints = points[i] - m_prevfilteredPoints[i];
831
832 fDiff = fabs(sqrt(diffPoints * diffPoints));
833 if (fDiff <= m_fJitterRadius)
834 {
835 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
836
837 double cVal = points[i];
838 cVal *= fDiff / m_fJitterRadius;
839
840 double pVal = m_prevfilteredPoints[i];
841 pVal *= 1.0f - fDiff / m_fJitterRadius;
842 m_filteredPoints[i] = cVal + pVal;
843 }
844 else
845 {
846 m_filteredPoints[i] = points[i];
847 }
848
849 // Now the double exponential smoothing filter
850 double cVal = m_filteredPoints[i];
851 cVal *= 1.0f - m_fSmoothing;
852
853 double pVal = m_prevfilteredPoints[i] + m_pointsTrend[i];
854 pVal *= m_fSmoothing;
855
856 m_filteredPoints[i] = cVal + pVal;
857
858 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
859
860 cVal = diffPoints;
861 cVal *= m_fCorrection;
862
863 pVal = m_pointsTrend[i];
864 pVal *= 1.0f - m_fCorrection;
865
866 trendPoints[i] = cVal + pVal;
867
868 // Predict into the future to reduce latency
869 cVal = trendPoints[i];
870 cVal *= m_fPrediction;
871
872 double predictedPoint = m_filteredPoints[i] + cVal;
873
874 // Check that we are not too far away from raw data
875 diffPoints = predictedPoint - points[i];
876 fDiff = fabs(sqrt(diffPoints * diffPoints));
877
878 if (fDiff > m_fMaxDeviationRadius)
879 {
880 cVal = predictedPoint;
881 cVal *= m_fMaxDeviationRadius / fDiff;
882
883 pVal = points[i];
884 pVal *= 1.0f - m_fMaxDeviationRadius / fDiff;
885
886 predictedPoint = cVal + pVal;
887 }
888
889 m_filteredPoints[i] = predictedPoint;
890 }
891 }
892
893 for (unsigned int i = 0; i < points.size(); i++)
894 {
895 m_prevfilteredPoints[i] = m_filteredPoints[i];
896 m_prevPoints[i] = points[i];
897 m_pointsTrend[i] = trendPoints[i];
898 }
899 }
900
901 std::vector<double> GetFilteredPoints()
902 {
903 return m_filteredPoints;
904 }
905};
906
907
909{
910private:
911 std::vector<cv::Point3f> m_filteredPoints;
912 std::vector<cv::Point3f> m_prevPoints;
913 std::vector<cv::Point3f> m_prevfilteredPoints;
914 std::vector<cv::Point3f> m_pointsTrend;
915 float m_fSmoothing;
916 float m_fCorrection;
917 float m_fPrediction;
918 float m_fJitterRadius;
919 float m_fMaxDeviationRadius;
920 int m_dwFrameCount;
921
922public:
925
926 void Init(float fSmoothing = 0.25f, float fCorrection = 0.25f, float fPrediction = 0.25f, float fJitterRadius = 0.03f, float fMaxDeviationRadius = 0.05f)
927 {
928 m_fMaxDeviationRadius = fMaxDeviationRadius; // Size of the max prediction radius Can snap back to noisy data when too high
929 m_fSmoothing = fSmoothing; // How much smothing will occur. Will lag when too high
930 m_fCorrection = fCorrection; // How much to correct back from prediction. Can make things springy
931 m_fPrediction = fPrediction; // Amount of prediction into the future to use. Can over shoot when too high
932 m_fJitterRadius = fJitterRadius; // Size of the radius where jitter is removed. Can do too much smoothing when too high
933
934 Reset();
935 }
936
937 void Shutdown()
938 {
939 }
940
941 void Reset()
942 {
943 m_dwFrameCount = 0;
944 m_filteredPoints.clear();
945 m_prevPoints.clear();
946 m_prevfilteredPoints.clear();
947 m_pointsTrend.clear();
948 for (unsigned int k = 0; k < 2; ++k)
949 {
950 m_filteredPoints.push_back(cv::Point3f(0.0f, 0.0f, 0.0f));
951 m_prevPoints.push_back(cv::Point3f(0.0f, 0.0f, 0.0f));
952 m_prevfilteredPoints.push_back(cv::Point3f(0.0f, 0.0f, 0.0f));
953 m_pointsTrend.push_back(cv::Point3f(0.0f, 0.0f, 0.0f));
954 }
955 }
956
957 void Update(std::vector<cv::Point3f> points)
958 {
959 cv::Point3f diffPoints;
960 std::vector<cv::Point3f> trendPoints;
961 float fDiff;
962
963 for (unsigned int k = 0; k < 2; ++k)
964 {
965 trendPoints.push_back(cv::Point3f(0.0f, 0.0f, 0.0f));
966 }
967
968 // Initial start values
969 if (m_dwFrameCount == 0)
970 {
971 for (unsigned int i = 0; i < 2; i++)
972 {
973 m_filteredPoints[i] = points[i];
974 }
975 m_dwFrameCount++;
976 }
977 else if (m_dwFrameCount == 1)
978 {
979 for (unsigned int i = 0; i < 2; i++)
980 {
981 m_filteredPoints[i] = points[i] + m_prevPoints[i];
982 m_filteredPoints[i].x *= 0.5f;
983 m_filteredPoints[i].y *= 0.5f;
984 m_filteredPoints[i].z *= 0.5f;
985
986 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
987
988 cv::Point3f cdiff = diffPoints;
989 cdiff.x *= m_fCorrection;
990 cdiff.y *= m_fCorrection;
991 cdiff.z *= m_fCorrection;
992
993 cv::Point3f pdiff = m_pointsTrend[i];
994 pdiff.x *= 1.0f - m_fCorrection;
995 pdiff.y *= 1.0f - m_fCorrection;
996 pdiff.z *= 1.0f - m_fCorrection;
997 trendPoints[i] = cdiff + pdiff;
998 }
999
1000 m_dwFrameCount++;
1001 }
1002 else
1003 {
1004 for (unsigned int i = 0; i < 2; i++)
1005 {
1006 diffPoints = points[i] - m_prevfilteredPoints[i];
1007
1008 fDiff = fabs(sqrt(diffPoints.x * diffPoints.x + diffPoints.y * diffPoints.y));
1009 if (fDiff <= m_fJitterRadius)
1010 {
1011 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
1012
1013 cv::Point3f cVal = points[i];
1014 cVal.x *= fDiff / m_fJitterRadius;
1015 cVal.y *= fDiff / m_fJitterRadius;
1016 cVal.z *= fDiff / m_fJitterRadius;
1017
1018 cv::Point3f pVal = m_prevfilteredPoints[i];
1019 pVal.x *= 1.0f - fDiff / m_fJitterRadius;
1020 pVal.y *= 1.0f - fDiff / m_fJitterRadius;
1021 pVal.z *= 1.0f - fDiff / m_fJitterRadius;
1022 m_filteredPoints[i] = cVal + pVal;
1023 }
1024 else
1025 {
1026 m_filteredPoints[i] = points[i];
1027 }
1028
1029 // Now the double exponential smoothing filter
1030 cv::Point3f cVal = m_filteredPoints[i];
1031 cVal.x *= 1.0f - m_fSmoothing;
1032 cVal.y *= 1.0f - m_fSmoothing;
1033 cVal.z *= 1.0f - m_fSmoothing;
1034
1035 cv::Point3f pVal = m_prevfilteredPoints[i] + m_pointsTrend[i];
1036 pVal.x *= m_fSmoothing;
1037 pVal.y *= m_fSmoothing;
1038 pVal.z *= m_fSmoothing;
1039 m_filteredPoints[i] = cVal + pVal;
1040
1041 diffPoints = m_filteredPoints[i] - m_prevfilteredPoints[i];
1042
1043 cVal = diffPoints;
1044 cVal.x *= m_fCorrection;
1045 cVal.y *= m_fCorrection;
1046 cVal.z *= m_fCorrection;
1047
1048 pVal = m_pointsTrend[i];
1049 pVal.x *= 1.0f - m_fCorrection;
1050 pVal.y *= 1.0f - m_fCorrection;
1051 pVal.z *= 1.0f - m_fCorrection;
1052
1053 trendPoints[i] = cVal + pVal;
1054
1055 // Predict into the future to reduce latency
1056 cVal = trendPoints[i];
1057 cVal.x *= m_fPrediction;
1058 cVal.y *= m_fPrediction;
1059 cVal.z *= m_fPrediction;
1060
1061 cv::Point3f predictedPoint = m_filteredPoints[i] + cVal;
1062
1063 // Check that we are not too far away from raw data
1064 diffPoints = predictedPoint - points[i];
1065 fDiff = fabs(sqrt(diffPoints.x * diffPoints.x + diffPoints.y * diffPoints.y));
1066
1067 if (fDiff > m_fMaxDeviationRadius)
1068 {
1069 cVal = predictedPoint;
1070 cVal.x *= m_fMaxDeviationRadius / fDiff;
1071 cVal.y *= m_fMaxDeviationRadius / fDiff;
1072 cVal.z *= m_fMaxDeviationRadius / fDiff;
1073
1074 pVal = points[i];
1075 pVal.x *= 1.0f - m_fMaxDeviationRadius / fDiff;
1076 pVal.y *= 1.0f - m_fMaxDeviationRadius / fDiff;
1077 pVal.z *= 1.0f - m_fMaxDeviationRadius / fDiff;
1078
1079 predictedPoint = cVal + pVal;
1080 }
1081
1082 m_filteredPoints[i] = predictedPoint;
1083 }
1084 }
1085
1086 for (unsigned int i = 0; i < 2; i++)
1087 {
1088 m_prevfilteredPoints[i] = m_filteredPoints[i];
1089 m_prevPoints[i] = points[i];
1090 m_pointsTrend[i] = trendPoints[i];
1091 }
1092 }
1093
1094 std::vector<cv::Point3f> GetFilteredPoints()
1095 {
1096 return m_filteredPoints;
1097 }
1098};
1099
1100static bool NiceHomography(cv::Mat Homography)
1101{
1102 cv::Mat H;
1103 Homography.convertTo(H, CV_32FC1);
1104
1105 const float det = H.at<float>(0, 0) * H.at<float>(1, 1) - H.at<float>(1, 0) * H.at<float>(0, 1);
1106 if (det < 0)
1107 return false;
1108
1109 const float N1 = sqrt(H.at<float>(0, 0) * H.at<float>(0, 0) + H.at<float>(1, 0) * H.at<float>(1, 0));
1110 if (N1 > 4 || N1 < 0.1)
1111 return false;
1112
1113 const float N2 = sqrt(H.at<float>(0, 1) * H.at<float>(0, 1) + H.at<float>(1, 1) * H.at<float>(1, 1));
1114 if (N2 > 4 || N2 < 0.1)
1115 return false;
1116
1117 const float N3 = sqrt(H.at<float>(2, 0) * H.at<float>(2, 0) + H.at<float>(2, 1) * H.at<float>(2, 1));
1118 if (N3 > 0.002)
1119 return false;
1120
1121 return true;
1122}
1123
1124// Converts a given Rotation Matrix to Euler angles
1125static cv::Point3f rot2euler(const cv::Mat &rotationMatrix)
1126{
1127 cv::Point3d euler;
1128
1129 double m00 = rotationMatrix.at<float>(0, 0);
1130 double m02 = rotationMatrix.at<float>(0, 2);
1131 double m10 = rotationMatrix.at<float>(1, 0);
1132 double m11 = rotationMatrix.at<float>(1, 1);
1133 double m12 = rotationMatrix.at<float>(1, 2);
1134 double m20 = rotationMatrix.at<float>(2, 0);
1135 double m22 = rotationMatrix.at<float>(2, 2);
1136
1137 double x, y, z;
1138
1139 // Assuming the angles are in radians.
1140 if (m10 > 0.998f) { // singularity at north pole
1141 x = 0;
1142 y = CV_PI / 2;
1143 z = atan2(m02, m22);
1144 }
1145 else if (m10 < -0.998f) { // singularity at south pole
1146 x = 0;
1147 y = -CV_PI / 2;
1148 z = atan2(m02, m22);
1149 }
1150 else
1151 {
1152 x = atan2(-m12, m11);
1153 y = asin(m10);
1154 z = atan2(-m20, m00);
1155 }
1156
1157 euler.x = x;
1158 euler.y = y;
1159 euler.z = z;
1160
1161 return euler;
1162}
1163
1164// Converts a given Euler angles to Rotation Matrix
1165static cv::Mat euler2rot(const cv::Point3f &euler)
1166{
1167 cv::Mat rotationMatrix(3, 3, CV_32F);
1168
1169 float x = euler.x;
1170 float y = euler.y;
1171 float z = euler.z;
1172
1173 // Assuming the angles are in radians.
1174 float ch = cos(z);
1175 float sh = sin(z);
1176 float ca = cos(y);
1177 float sa = sin(y);
1178 float cb = cos(x);
1179 float sb = sin(x);
1180
1181 float m00, m01, m02, m10, m11, m12, m20, m21, m22;
1182
1183 m00 = ch * ca;
1184 m01 = sh * sb - ch * sa*cb;
1185 m02 = ch * sa*sb + sh * cb;
1186 m10 = sa;
1187 m11 = ca * cb;
1188 m12 = -ca * sb;
1189 m20 = -sh * ca;
1190 m21 = sh * sa*cb + ch * sb;
1191 m22 = -sh * sa*sb + ch * cb;
1192
1193 rotationMatrix.at<float>(0, 0) = m00;
1194 rotationMatrix.at<float>(0, 1) = m01;
1195 rotationMatrix.at<float>(0, 2) = m02;
1196 rotationMatrix.at<float>(1, 0) = m10;
1197 rotationMatrix.at<float>(1, 1) = m11;
1198 rotationMatrix.at<float>(1, 2) = m12;
1199 rotationMatrix.at<float>(2, 0) = m20;
1200 rotationMatrix.at<float>(2, 1) = m21;
1201 rotationMatrix.at<float>(2, 2) = m22;
1202
1203 return rotationMatrix;
1204}
1205
1206#ifdef ANDROID
1207#include <android/log.h>
1208#define LOG_TAG "ScolApp"
1209#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
1210#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
1211#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
1212
1213#include <sys/stat.h>
1214static std::string CopyFileFromAssetToSD(std::string source, std::string dest, std::string destdir)
1215{
1216 std::string out = "";
1217 char*(*GetUserPath)() = (char*(__cdecl *)()) SCgetExtra("GetUserPath");
1218
1219 if (GetUserPath)
1220 {
1221 int n;
1222 FILE *r, *w;
1223 char buf[1024];
1224
1225 std::string userPath = GetUserPath();
1226 LOGI("CopyFileFromAssetToSD > User path : %s", userPath.c_str());
1227
1228 source = "apk/" + source;
1229
1230 dest = userPath + "/" + destdir + "/" + dest;
1231 destdir = userPath + "/" + destdir;
1232
1233 if (boost::filesystem::exists(dest))
1234 {
1235 LOGI("CopyFileFromAssetToSD > source already exist : %s", dest.c_str());
1236 out = dest;
1237 return out;
1238 }
1239
1240 LOGI("CopyFileFromAssetToSD > make dir : %s", destdir.c_str());
1241 boost::filesystem::create_directories(destdir.c_str());
1242
1243 r = fopen(source.c_str(), "rb");
1244 if (r == NULL)
1245 {
1246 LOGI("CopyFileFromAssetToSD > source not found : %s", source.c_str());
1247 return out;
1248 }
1249
1250 w = fopen(dest.c_str(), "wb");
1251 if (w)
1252 {
1253 do
1254 {
1255 n = fread(buf, 1, 1024, r);
1256 if (n > 0) fwrite(buf, 1, n, w);
1257 } while (n == 1024);
1258 fclose(w);
1259 }
1260 else
1261 {
1262 fclose(r);
1263 LOGI("CopyFileFromAssetToSD > dest failed to create : %s", dest.c_str());
1264 return out;
1265 }
1266
1267 fclose(r);
1268 LOGI("CopyFileFromAssetToSD > succeed : %s", dest.c_str());
1269 out = dest;
1270 return out;
1271 }
1272
1273 return out;
1274}
1275
1276static std::string cloneFileFromAssetToSD(std::string source)
1277{
1278 if (source.compare(0, 4, "APK/") == 0)
1279 source = source.substr(4, source.length());
1280
1281 boost::filesystem::path file(source);
1282 return CopyFileFromAssetToSD(source, file.filename().generic_string(), file.parent_path().generic_string());
1283 }
1284#endif
1285
1286static cv::Mat createMask(cv::Size img_size, std::vector<cv::Point2f>& pts)
1287{
1288 cv::Mat mask(img_size, CV_8UC1);
1289 mask = 0;
1290
1291 // ax+by+c=0
1292 float a[4];
1293 float b[4];
1294 float c[4];
1295
1296 a[0] = pts[3].y - pts[0].y;
1297 a[1] = pts[2].y - pts[1].y;
1298 a[2] = pts[1].y - pts[0].y;
1299 a[3] = pts[2].y - pts[3].y;
1300
1301 b[0] = pts[0].x - pts[3].x;
1302 b[1] = pts[1].x - pts[2].x;
1303 b[2] = pts[0].x - pts[1].x;
1304 b[3] = pts[3].x - pts[2].x;
1305
1306 c[0] = pts[0].y * pts[3].x - pts[3].y * pts[0].x;
1307 c[1] = pts[1].y * pts[2].x - pts[2].y * pts[1].x;
1308 c[2] = pts[0].y * pts[1].x - pts[1].y * pts[0].x;
1309 c[3] = pts[3].y * pts[2].x - pts[2].y * pts[3].x;
1310
1311 float max_x, min_x, max_y, min_y;
1312 max_x = 0;
1313 min_x = img_size.width;
1314 max_y = 0;
1315 min_y = img_size.height;
1316
1317 int i;
1318 for (i = 0; i < 4; i++)
1319 {
1320 if (pts[i].x > max_x)
1321 max_x = pts[i].x;
1322 if (pts[i].x < min_x)
1323 min_x = pts[i].x;
1324 if (pts[i].y > max_y)
1325 max_y = pts[i].y;
1326 if (pts[i].y < min_y)
1327 min_y = pts[i].y;
1328 }
1329
1330 if (max_x >= img_size.width)
1331 max_x = img_size.width - 1;
1332 if (max_y >= img_size.height)
1333 max_y = img_size.height - 1;
1334 if (min_x < 0)
1335 min_x = 0;
1336 if (min_y < 0)
1337 min_y = 0;
1338
1339 unsigned char *ptr = mask.data;
1340 int x, y;
1341 int offset;
1342 float val[4];
1343 for (y = min_y; y <= max_y; y++)
1344 {
1345 offset = y * img_size.width;
1346 for (x = min_x; x <= max_x; x++)
1347 {
1348 for (i = 0; i < 4; i++)
1349 {
1350 val[i] = a[i] * x + b[i] * y + c[i];
1351 }
1352
1353 if (val[0] * val[1] <= 0 && val[2] * val[3] <= 0)
1354 *(ptr + offset + x) = 255;
1355 }
1356 }
1357
1358 return mask;
1359}
1360
1361static std::vector<cv::Point2f> scalePoints(std::vector<cv::Point2f>& point_vec, double scale)
1362{
1363 std::vector<cv::Point2f> ret_vec;
1364
1365 std::vector<cv::Point2f>::iterator itr = point_vec.begin();
1366 while (itr != point_vec.end())
1367 {
1368 ret_vec.push_back(*itr * scale);
1369 itr++;
1370 }
1371 return ret_vec;
1372}
1373
1374// Check the validity of transformed rectangle shape
1375// the sign of outer products of each edge vector must be same
1376static bool checkRectShape(std::vector<cv::Point2f>& rectPts)
1377{
1378 if (rectPts.size() != 4)
1379 return false;
1380
1381 bool result = true;
1382 float vec[4][2];
1383 unsigned int i, j;
1384
1385 vec[0][0] = rectPts[1].x - rectPts[0].x;
1386 vec[0][1] = rectPts[1].y - rectPts[0].y;
1387 vec[1][0] = rectPts[2].x - rectPts[1].x;
1388 vec[1][1] = rectPts[2].y - rectPts[1].y;
1389 vec[2][0] = rectPts[3].x - rectPts[2].x;
1390 vec[2][1] = rectPts[3].y - rectPts[2].y;
1391 vec[3][0] = rectPts[0].x - rectPts[3].x;
1392 vec[3][1] = rectPts[0].y - rectPts[3].y;
1393
1394 int s;
1395 float val = vec[3][0] * vec[0][1] - vec[3][1] * vec[0][0];
1396 if (val > 0)
1397 s = 1;
1398 else
1399 s = -1;
1400
1401 for (i = 0; i < 3; i++)
1402 {
1403 val = vec[i][0] * vec[i + 1][1] - vec[i][1] * vec[i + 1][0];
1404 if (val * s <= 0) {
1405 result = false;
1406 break;
1407 }
1408 }
1409
1410 if (cv::isContourConvex(cv::Mat(rectPts)))
1411 {
1412 for (j = 0; j < rectPts.size(); j++)
1413 {
1414 int pdx = j == 0 ? rectPts.size() - 1 : j - 1; // predecessor of idx
1415 int sdx = j == rectPts.size() - 1 ? 0 : j + 1; // successor of idx
1416
1417 cv::Point v1 = rectPts[sdx] - rectPts[j];
1418 cv::Point v2 = rectPts[pdx] - rectPts[j];
1419
1420 // one of the low interior angle + within upper 90% of region the marker seems bad
1421 double angle = acos(static_cast<double>(v1.x*v2.x + v1.y*v2.y) / (cv::norm(v1) * cv::norm(v2)));
1422 if (angle < 0.9)
1423 {
1424 result = false;
1425 break;
1426 }
1427 }
1428 }
1429
1430 return result;
1431}
1432
1433static void rotateImage(const cv::Mat &input, cv::Mat &output, cv::Mat &outwarp, double alpha, double beta, double gamma, double dx, double dy, double dz, double f)
1434{
1435 alpha = alpha * (CV_PI / 180.);
1436 beta = beta * (CV_PI / 180.);
1437 gamma = gamma * (CV_PI / 180.);
1438
1439 // get width and height for ease of use in matrices
1440 double w = (double)input.cols;
1441 double h = (double)input.rows;
1442
1443 // Projection 2D -> 3D matrix
1444 cv::Mat A1 = (cv::Mat_<double>(4, 3) <<
1445 1, 0, -w / 2,
1446 0, 1, -h / 2,
1447 0, 0, 0,
1448 0, 0, 1);
1449
1450 // Rotation matrices around the X, Y, and Z axis
1451 cv::Mat RX = (cv::Mat_<double>(4, 4) <<
1452 1, 0, 0, 0,
1453 0, cos(alpha), -sin(alpha), 0,
1454 0, sin(alpha), cos(alpha), 0,
1455 0, 0, 0, 1);
1456
1457 cv::Mat RY = (cv::Mat_<double>(4, 4) <<
1458 cos(beta), 0, -sin(beta), 0,
1459 0, 1, 0, 0,
1460 sin(beta), 0, cos(beta), 0,
1461 0, 0, 0, 1);
1462
1463 cv::Mat RZ = (cv::Mat_<double>(4, 4) <<
1464 cos(gamma), -sin(gamma), 0, 0,
1465 sin(gamma), cos(gamma), 0, 0,
1466 0, 0, 1, 0,
1467 0, 0, 0, 1);
1468
1469 // Composed rotation matrix with (RX, RY, RZ)
1470 cv::Mat R = RX * RY * RZ;
1471
1472 // Translation matrix
1473 cv::Mat T = (cv::Mat_<double>(4, 4) <<
1474 1, 0, 0, dx,
1475 0, 1, 0, dy,
1476 0, 0, 1, dz,
1477 0, 0, 0, 1);
1478 // 3D -> 2D matrix
1479 cv::Mat A2 = (cv::Mat_<double>(3, 4) <<
1480 f, 0, w / 2, 0,
1481 0, f, h / 2, 0,
1482 0, 0, 1, 0);
1483
1484 // Final transformation matrix
1485 outwarp = A2 * (T * (R * A1));
1486
1487 // Apply matrix transformation
1488 warpPerspective(input, output, outwarp, input.size(), cv::INTER_LANCZOS4);
1489}
1490
1491#endif
cbmachine ww
Scol machine declaration for MM macros.
Definition PluginBT.cpp:48
int LoadArToolkit(mmachine m)
Vector2 operator/(Vector2 u, float scalar)
int UnloadMediaPlayerToolkit()
int LoadMathToolkit(mmachine m)
Load the packages in Scol virtual machine.
Vector2 operator*(Vector2 u, float scalar)
int LoadCaptureToolkit(mmachine m)
Vector2 operator+(Vector2 u, Vector2 v)
int UnloadArToolkit()
Vector2 operator-(Vector2 u, Vector2 v)
int Random(int mi, int mx)
int LoadMediaPlayerToolkit(mmachine m)
int WM_ML_TRAINING_FINISHED
Definition MlToolkit.cpp:34
int LoadMlToolkit(mmachine m)
int LoadBitmapToolKit(mmachine m)
int WM_ML_DETECTION
Definition MlToolkit.cpp:35
static BtQuaternion Slerp(float fT, const BtQuaternion &rkP, const BtQuaternion &rkQ, bool shortestPath)
BtQuaternion Inverse() const
BtQuaternion(float quat[4])
BtQuaternion operator*(float s) const
bool operator!=(const BtQuaternion &rhs) const
BtQuaternion(float ww, float xx, float yy, float zz)
BtQuaternion operator+(const BtQuaternion &rkQ) const
BtQuaternion(double quat[4])
BtQuaternion operator-() const
static const BtQuaternion IDENTITY
float normalise(void)
friend BtQuaternion operator*(float s, const BtQuaternion &q)
float Dot(const BtQuaternion &rkQ) const
bool operator==(const BtQuaternion &rhs) const
float Norm() const
static BtQuaternion FromRotationMatrix(double rotMatrix[16], bool reverseX=false, bool reverseY=true)
void Update(std::vector< cv::Point3f > points)
std::vector< cv::Point3f > GetFilteredPoints()
void Init(float fSmoothing=0.25f, float fCorrection=0.25f, float fPrediction=0.25f, float fJitterRadius=0.03f, float fMaxDeviationRadius=0.05f)
std::vector< double > GetFilteredPoints()
void Init(float fSmoothing=0.25f, float fCorrection=0.25f, float fPrediction=0.25f, float fJitterRadius=0.03f, float fMaxDeviationRadius=0.05f)
void Update(std::vector< double > points)
std::vector< cv::Point2f > GetFilteredPoints()
void Update(std::vector< cv::Point2f > points)
void Init(float fSmoothing=0.25f, float fCorrection=0.25f, float fPrediction=0.25f, float fJitterRadius=0.03f, float fMaxDeviationRadius=0.05f)
Vector2 operator-()
Vector2 operator*=(float scalar)
float DotProduct(Vector2 other)
float GetMagnitude()
Vector2 operator+=(Vector2 other)
Vector2 operator/=(float scalar)
Vector2 GetNoramlizedVector()
Vector2(float xx, float yy)
Vector2 operator-=(Vector2 other)
Vector3(float xx, float yy, float zz)
Vector3 operator*=(float scalar)
float DotProduct(Vector3 other)
Vector3 operator/=(float scalar)
Vector3 CrossProduct(Vector3 other)
float GetMagnitude()
Vector3 operator-()
Vector3 operator+=(Vector3 other)
Vector3 operator-=(Vector3 other)
Vector3 GetNoramlizedVector()