00001 #include "OpticalFlow.h"
00002 #include "DualCoding/DualCoding.h"
00003
00004 using namespace DualCoding;
00005
00006 OpticalFlow::OpticalFlow() : integratedFlow(0.0f), flowVectors(NUM_FLOW_VECTORS),
00007 flowVectorVisuals(NUM_FLOW_VECTORS), pastTranslations(NUM_FRAMES),
00008 pyramid1(), pyramid2(), currPyramid(&pyramid1), prevPyramid(NULL) {}
00009
00010 bool OpticalFlow::myFlowComp(const FlowVector &v1, const FlowVector &v2) {
00011 return (v1.flow(0,0) < v2.flow(0,0));
00012 }
00013
00014 bool OpticalFlow::myFlowComp2(const FlowVector &v1, const FlowVector &v2) {
00015 return (v1.relevanceScore < v2.relevanceScore);
00016 }
00017
00018
00019 void OpticalFlow::computeRelevanceScores() {
00020 for(unsigned int i = 0; i < NUM_FLOW_VECTORS; i++) {
00021 float score = 0;
00022 for(unsigned int j = 0; j < NUM_FRAMES; j++) {
00023 score += (1.0f/((float)(j+1))) * fabs(flowVectors[i].flow(0,0) - pastTranslations[j]);
00024 }
00025 flowVectors[i].relevanceScore = score;
00026 }
00027 }
00028
00029 void OpticalFlow::updateFlow() {
00030 currPyramid->loadFromRawY();
00031 if(prevPyramid == NULL) {
00032 swapPyramids();
00033 return;
00034 }
00035
00036 initializePositions();
00037 for(unsigned int L = RawImagePyramid::NUM_PYRAMID_LAYERS; L > 0; L--) {
00038 for(unsigned int i = 0; i < NUM_FLOW_VECTORS; i++) {
00039 fmat::Column<2> flow = iterativeLucasKanade(flowVectors[i].position/pow(2,L-1),
00040 flowVectors[i].flow,
00041 (*prevPyramid)[L-1],
00042 (*currPyramid)[L-1],
00043 FLOW_WINDOW);
00044 if(L != 0)
00045 flowVectors[i].flow = 2 * (flowVectors[i].flow + flow);
00046 else
00047 flowVectors[i].flow = (flowVectors[i].flow + flow);
00048 }
00049 }
00050
00051 computeRelevanceScores();
00052 sort(flowVectors.begin(), flowVectors.end(), myFlowComp2);
00053 sort(flowVectors.begin(), flowVectors.begin()+(2*NUM_FLOW_VECTORS/3), myFlowComp);
00054
00055 float trans = flowVectors[2*NUM_FLOW_VECTORS/6].flow(0,0);
00056 integratedFlow += trans;
00057
00058 for(int i = NUM_FRAMES-1; i>=1; i--)
00059 pastTranslations[i] = pastTranslations[i-1];
00060 pastTranslations[0] = trans;
00061
00062 swapPyramids();
00063 }
00064
00065 void OpticalFlow::swapPyramids() {
00066 if(currPyramid == &pyramid1) {
00067 currPyramid = &pyramid2;
00068 prevPyramid = &pyramid1;
00069 }
00070 else {
00071 currPyramid = &pyramid1;
00072 prevPyramid = &pyramid2;
00073 }
00074 }
00075
00076 void OpticalFlow::drawFlow() {
00077 static Sketch<uchar> rawY(VRmixin::sketchFromRawY(), "rawY", true);
00078
00079 rawY = VRmixin::sketchFromRawY();
00080
00081 int i = 0;
00082 SHAPEVEC_ITERATE(flowVectorVisuals, LineData, line) {
00083 fmat::Column<2> startPt = 2*flowVectors[i].position;
00084 fmat::Column<2> endPt = 2*flowVectors[i].position + flowVectors[i].flow;
00085 EndPoint startPt2 = EndPoint(startPt(0,0), startPt(1,0));
00086 EndPoint endPt2 = EndPoint(endPt(0,0),endPt(1,0));
00087 if(!line.isValid()) {
00088 LineData line2(VRmixin::camShS,startPt2,endPt2);
00089 line = Shape<LineData>(line2);
00090 } else {
00091 line->setEndPts(startPt2, endPt2);
00092 }
00093 i++;
00094 }}
00095 }
00096
00097 void OpticalFlow::initializePositions() {
00098 unsigned int j = 0;
00099 unsigned int const width = (*prevPyramid)[SCORE_LAYER].getWidth();
00100 unsigned int const height = (*prevPyramid)[SCORE_LAYER].getHeight();
00101 unsigned int const xinc = width/CANDIDATE_FEATURE_RESOLUTION;
00102 unsigned int const yinc = height/CANDIDATE_FEATURE_RESOLUTION;
00103 unsigned int const numFeatures = (width/xinc) * (height/yinc);
00104 std::vector<ScorePoint> eigens(numFeatures);
00105
00106 for(unsigned int x = 0; x < width; x+=xinc) {
00107 for(unsigned int y = 0; y < height; y+=yinc) {
00108 if ( j >= numFeatures )
00109 std::cout << "*** j = " << j << std::endl;
00110 eigens[j].position(0,0) = x;
00111 eigens[j].position(1,0) = y;
00112 eigens[j].score = (*prevPyramid)[SCORE_LAYER].imageScore(x,y,SCORE_WINDOW);
00113
00114 j++;
00115 }
00116 }
00117
00118 sort(eigens.begin(), eigens.end(), scoreComp);
00119 if(eigens[0].score == 0) {
00120 cout << "VISUAL ODOMETRY FAILED" << endl;
00121 return;
00122 }
00123
00124 for(unsigned int i = 0; i < NUM_FLOW_VECTORS; i++) {
00125 flowVectors[i].position = eigens[i].position;
00126 flowVectors[i].flow = fmat::pack(0,0);
00127 }
00128 }
00129
00130 fmat::Column<2>
00131 OpticalFlow::iterativeLucasKanade(fmat::Column<2> center, fmat::Column<2> trans,
00132 RawImage& img1, RawImage& img2, int window) {
00133 fmat::Matrix<2,2> G = img1.spatialGradientMatrix(center(0,0),center(1,0),window);
00134 if(fmat::det(G) == 0)
00135 return fmat::pack(0,0);
00136 fmat::Matrix<2,2> Ginv = fmat::invert(G);
00137
00138 const unsigned int MAX_ITERATIONS = 5;
00139 const float ACCURACY_THRESHOLD = 0.1f;
00140 fmat::Column<2> opticalFlow;
00141 for(unsigned int i = 0; i < MAX_ITERATIONS; i++) {
00142 fmat::Column<2> b;
00143 for(float x = center(0,0) - window; x <= center(0,0)+window; x++) {
00144 for(float y = center(1,0) - window; y <= center(1,0)+window; y++) {
00145 float delta = img1(x,y) - img2(x + trans(0,0) + opticalFlow(0,0),
00146 y + trans(1,0) + opticalFlow(1,0));
00147 fmat::Column<2> grad = img1.gradient(x,y);
00148
00149 b += grad * delta;
00150 }
00151 }
00152
00153 fmat::Column<2> gamma = Ginv * b;
00154 opticalFlow += gamma;
00155
00156
00157
00158 if( (gamma(0,0) * gamma(0,0)) + (gamma(1,0) * gamma(1,0)) < ACCURACY_THRESHOLD )
00159 break;
00160 }
00161
00162 return opticalFlow;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205