184 |
jakw |
1 |
#ifndef ALGORITHMTOOLS_H
|
|
|
2 |
#define ALGORITHMTOOLS_H
|
|
|
3 |
|
|
|
4 |
#include <opencv2/opencv.hpp>
|
|
|
5 |
|
|
|
6 |
// Convert an unsigned binary number to reflected binary Gray code.
|
|
|
7 |
// Source: http://en.wikipedia.org/wiki/Gray_code
|
|
|
8 |
inline unsigned int binaryToGray(unsigned int num) {
|
|
|
9 |
return (num >> 1) ^ num;
|
|
|
10 |
}
|
|
|
11 |
|
|
|
12 |
// Convert a reflected binary Gray code number to a binary number.
|
|
|
13 |
// Source: http://en.wikipedia.org/wiki/Gray_code
|
|
|
14 |
inline unsigned int grayToBinary(unsigned int num){
|
|
|
15 |
unsigned int mask;
|
|
|
16 |
for(mask = num >> 1; mask != 0; mask = mask >> 1)
|
|
|
17 |
num = num ^ mask;
|
|
|
18 |
return num;
|
|
|
19 |
}
|
|
|
20 |
|
|
|
21 |
// Return the Nth bit of an unsigned integer number
|
|
|
22 |
inline bool getBit(int decimal, int N){
|
|
|
23 |
|
|
|
24 |
return decimal & 1 << (N-1);
|
|
|
25 |
}
|
|
|
26 |
|
|
|
27 |
// Return the position of the least significant bit that is set
|
|
|
28 |
inline int leastSignificantBitSet(int x){
|
|
|
29 |
if(x == 0)
|
|
|
30 |
return 0;
|
|
|
31 |
|
|
|
32 |
int val = 1;
|
|
|
33 |
while(x>>=1)
|
|
|
34 |
val++;
|
|
|
35 |
|
|
|
36 |
return val;
|
|
|
37 |
}
|
|
|
38 |
|
|
|
39 |
// Compute the power of a number (where the exponent is an integer)
|
|
|
40 |
inline unsigned int powi(int num, unsigned int exponent){
|
|
|
41 |
|
|
|
42 |
if(exponent == 0)
|
|
|
43 |
return 1;
|
|
|
44 |
|
|
|
45 |
float res = num;
|
|
|
46 |
for(unsigned int i=0; i<exponent-1; i++)
|
|
|
47 |
res *= num;
|
|
|
48 |
|
|
|
49 |
return res;
|
|
|
50 |
}
|
|
|
51 |
|
|
|
52 |
// Compute the power of a 2 (where the exponent is an integer)
|
|
|
53 |
inline unsigned int twopowi(unsigned int exponent){
|
|
|
54 |
return 1 << exponent;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
inline cv::Vec3b getColorSubpix(const cv::Mat& img, cv::Point2f pt){
|
|
|
58 |
assert(!img.empty());
|
|
|
59 |
assert(img.channels() == 3);
|
|
|
60 |
|
|
|
61 |
int x = (int)pt.x;
|
|
|
62 |
int y = (int)pt.y;
|
|
|
63 |
|
|
|
64 |
int x0 = cv::borderInterpolate(x, img.cols, cv::BORDER_REFLECT_101);
|
|
|
65 |
int x1 = cv::borderInterpolate(x+1, img.cols, cv::BORDER_REFLECT_101);
|
|
|
66 |
int y0 = cv::borderInterpolate(y, img.rows, cv::BORDER_REFLECT_101);
|
|
|
67 |
int y1 = cv::borderInterpolate(y+1, img.rows, cv::BORDER_REFLECT_101);
|
|
|
68 |
|
|
|
69 |
float a = pt.x - (float)x;
|
|
|
70 |
float c = pt.y - (float)y;
|
|
|
71 |
|
|
|
72 |
uchar b = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[0] * a) * (1.f - c)
|
|
|
73 |
+ (img.at<cv::Vec3b>(y1, x0)[0] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[0] * a) * c);
|
|
|
74 |
uchar g = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[1] * a) * (1.f - c)
|
|
|
75 |
+ (img.at<cv::Vec3b>(y1, x0)[1] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[1] * a) * c);
|
|
|
76 |
uchar r = (uchar)cvRound((img.at<cv::Vec3b>(y0, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y0, x1)[2] * a) * (1.f - c)
|
|
|
77 |
+ (img.at<cv::Vec3b>(y1, x0)[2] * (1.f - a) + img.at<cv::Vec3b>(y1, x1)[2] * a) * c);
|
|
|
78 |
|
|
|
79 |
return cv::Vec3b(b, g, r);
|
|
|
80 |
}
|
|
|
81 |
|
|
|
82 |
inline cv::Mat computePhaseVector(unsigned int length, float phase, float pitch){
|
|
|
83 |
|
|
|
84 |
cv::Mat phaseVector(length, 1, CV_8UC3);
|
|
|
85 |
//phaseVector.setTo(0);
|
|
|
86 |
|
|
|
87 |
const float pi = M_PI;
|
|
|
88 |
|
|
|
89 |
// Loop through vector
|
|
|
90 |
for(int i=0; i<phaseVector.rows; i++){
|
|
|
91 |
// Amplitude of channels
|
|
|
92 |
float amp = 0.5*(1+cos(2*pi*i/pitch - phase));
|
|
|
93 |
phaseVector.at<cv::Vec3b>(i, 0) = cv::Vec3b(255.0*amp,255.0*amp,255.0*amp);
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
return phaseVector;
|
|
|
97 |
}
|
|
|
98 |
|
|
|
99 |
inline cv::Mat getPhase(const cv::Mat I1, const cv::Mat I2, const cv::Mat I3){
|
|
|
100 |
|
|
|
101 |
cv::Mat_<float> I1_(I1);
|
|
|
102 |
cv::Mat_<float> I2_(I2);
|
|
|
103 |
cv::Mat_<float> I3_(I3);
|
|
|
104 |
|
|
|
105 |
cv::Mat phase;
|
|
|
106 |
|
|
|
107 |
// One call approach
|
|
|
108 |
cv::phase(2.0*I1_-I3_-I2_, sqrt(3.0)*(I2_-I3_), phase);
|
|
|
109 |
return phase;
|
|
|
110 |
|
|
|
111 |
}
|
|
|
112 |
|
|
|
113 |
// Phase unwrapping by means of a phase cue
|
|
|
114 |
inline cv::Mat unwrapWithCue(const cv::Mat up, const cv::Mat upCue, float nPhases){
|
|
|
115 |
|
|
|
116 |
const float pi = M_PI;
|
|
|
117 |
|
|
|
118 |
// Determine number of jumps
|
|
|
119 |
cv::Mat P = (upCue*nPhases-up)/(2.0*pi);
|
|
|
120 |
|
|
|
121 |
// Round to integers
|
|
|
122 |
P.convertTo(P, CV_8U);
|
|
|
123 |
P.convertTo(P, CV_32F);
|
|
|
124 |
|
|
|
125 |
// Add to phase
|
|
|
126 |
cv::Mat upUnwrapped = up + P*2*pi;
|
|
|
127 |
|
|
|
128 |
// Scale to range [0; 2pi]
|
|
|
129 |
upUnwrapped *= 1.0/nPhases;
|
|
|
130 |
|
|
|
131 |
return upUnwrapped;
|
|
|
132 |
}
|
|
|
133 |
|
|
|
134 |
// Absolute phase and magnitude from N frames
|
|
|
135 |
inline std::vector<cv::Mat> getDFTComponents(const std::vector<cv::Mat> frames){
|
|
|
136 |
|
|
|
137 |
unsigned int N = frames.size();
|
|
|
138 |
|
|
|
139 |
// std::vector<cv::Mat> framesReverse = frames;
|
|
|
140 |
// std::reverse(framesReverse.begin(), framesReverse.end());
|
|
|
141 |
|
|
|
142 |
// DFT approach
|
|
|
143 |
cv::Mat I;
|
|
|
144 |
cv::merge(frames, I);
|
|
|
145 |
unsigned int w = I.cols;
|
|
|
146 |
unsigned int h = I.rows;
|
|
|
147 |
I = I.reshape(1, h*w);
|
|
|
148 |
I.convertTo(I, CV_32F);
|
|
|
149 |
cv::Mat fI;
|
|
|
150 |
cv::dft(I, fI, cv::DFT_ROWS + cv::DFT_COMPLEX_OUTPUT);
|
|
|
151 |
fI = fI.reshape(N*2, h);
|
|
|
152 |
|
|
|
153 |
std::vector<cv::Mat> fIcomp;
|
|
|
154 |
cv::split(fI, fIcomp);
|
|
|
155 |
|
|
|
156 |
return fIcomp;
|
|
|
157 |
|
|
|
158 |
}
|
|
|
159 |
|
|
|
160 |
#endif // ALGORITHMTOOLS_H
|