📄 calibimage.cc
字号:
nFound++; } if(aNeighborStates[dirn+2].val >=0) { v2Dirn -= vgc[aNeighborStates[dirn+2].val].Params.v2Pos - Params.v2Pos; nFound++; } if(nFound == 0) m2Steps[dirn] = mInheritedSteps[dirn]; else m2Steps[dirn] = v2Dirn / nFound; } return m2Steps;};int CalibImage::NextToExpand(){ int nBest = -1; double dBest = 0.0; for(unsigned int i=0; i<mvGridCorners.size(); i++) { double d = mvGridCorners[i].ExpansionPotential(); if(d > dBest) { nBest = i; dBest = d; } } return nBest;}void CalibImage::ExpandByStep(int n){ static gvar3<double> gvdMaxStepDistFraction("CameraCalibrator.ExpandByStepMaxDistFrac", 0.3, SILENT); static gvar3<int> gvnCornerPatchSize("CameraCalibrator.CornerPatchPixelSize", 20, SILENT); CalibGridCorner &gSrc = mvGridCorners[n]; // First, choose which direction to expand in... // Ideally, choose a dirn for which the Step calc is good! int nDirn = -10; for(int i=0; nDirn == -10 && i<4; i++) { if(gSrc.aNeighborStates[i].val == N_NOT_TRIED && gSrc.aNeighborStates[(i+2) % 4].val >= 0) nDirn = i; } if(nDirn == -10) for(int i=0; nDirn == -10 && i<4; i++) { if(gSrc.aNeighborStates[i].val == N_NOT_TRIED) nDirn = i; } assert(nDirn != -10); Vector<2> v2Step; ImageRef irGridStep = IR_from_dirn(nDirn); v2Step = gSrc.GetSteps(mvGridCorners).T() * vec(irGridStep); Vector<2> v2SearchPos = gSrc.Params.v2Pos + v2Step; // Before the search: pre-fill the failure result for easy returns. gSrc.aNeighborStates[nDirn].val = N_FAILED; ImageRef irBest; double dBestDist = 99999; for(unsigned int i=0; i<mvCorners.size(); i++) { Vector<2> v2Diff = vec(mvCorners[i]) - v2SearchPos; if(v2Diff * v2Diff > dBestDist * dBestDist) continue; dBestDist = sqrt(v2Diff * v2Diff); irBest = mvCorners[i]; } double dStepDist= sqrt(v2Step * v2Step); if(dBestDist > *gvdMaxStepDistFraction * dStepDist) return; CalibGridCorner gTarget; gTarget.Params = gSrc.Params; gTarget.Params.v2Pos = vec(irBest); gTarget.Params.dGain *= -1; gTarget.irGridPos = gSrc.irGridPos + irGridStep; gTarget.mInheritedSteps = gSrc.GetSteps(mvGridCorners); CalibCornerPatch Patch(*gvnCornerPatchSize); if(!Patch.IterateOnImage(gTarget.Params, mim)) return; // Update connection states: int nTargetNum = mvGridCorners.size(); for(int dirn = 0; dirn<4; dirn++) { ImageRef irSearch = gTarget.irGridPos + IR_from_dirn(dirn); for(unsigned int i=0; i<mvGridCorners.size(); i++) if(mvGridCorners[i].irGridPos == irSearch) { gTarget.aNeighborStates[dirn].val = i; mvGridCorners[i].aNeighborStates[(dirn + 2) % 4].val = nTargetNum; } } mvGridCorners.push_back(gTarget); mvGridCorners.back().Draw();}void CalibImage::DrawImageGrid(){ glLineWidth(2); glColor3f(0,0,1); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBegin(GL_LINES); for(int i=0; i< (int) mvGridCorners.size(); i++) { for(int dirn=0; dirn<4; dirn++) if(mvGridCorners[i].aNeighborStates[dirn].val > i) { glVertex(mvGridCorners[i].Params.v2Pos); glVertex(mvGridCorners[mvGridCorners[i].aNeighborStates[dirn].val].Params.v2Pos); } } glEnd(); glPointSize(5); glEnable(GL_POINT_SMOOTH); glColor3f(1,0,0); glBegin(GL_POINTS); for(unsigned int i=0; i<mvGridCorners.size(); i++) glVertex(mvGridCorners[i].Params.v2Pos); glEnd();};void CalibImage::Draw3DGrid(ATANCamera &Camera){ glLineWidth(2); glColor3f(0,0,1); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBegin(GL_LINES); for(int i=0; i< (int) mvGridCorners.size(); i++) { for(int dirn=0; dirn<4; dirn++) if(mvGridCorners[i].aNeighborStates[dirn].val > i) { Vector<3> v3; v3[2] = 0.0; v3.slice<0,2>() = vec(mvGridCorners[i].irGridPos); glVertex(Camera.Project(project(mse3CamFromWorld * v3))); v3.slice<0,2>() = vec(mvGridCorners[mvGridCorners[i].aNeighborStates[dirn].val].irGridPos); glVertex(Camera.Project(project(mse3CamFromWorld * v3))); } } glEnd();};ImageRef CalibImage::IR_from_dirn(int nDirn){ ImageRef ir; ir[nDirn%2] = (nDirn < 2) ? 1: -1; return ir;}void CalibImage::GuessInitialPose(ATANCamera &Camera){ // First, find a homography which maps the grid to the unprojected image coords // Use the standard null-space-of-SVD-thing to find 9 homography parms // (c.f. appendix of thesis) int nPoints = mvGridCorners.size(); Matrix<> m2Nx9(2*nPoints, 9); for(int n=0; n<nPoints; n++) { // First, un-project the points to the image plane Vector<2> v2UnProj = Camera.UnProject(mvGridCorners[n].Params.v2Pos); double u = v2UnProj[0]; double v = v2UnProj[1]; // Then fill in the matrix.. double x = mvGridCorners[n].irGridPos.x; double y = mvGridCorners[n].irGridPos.y; m2Nx9[n*2+0][0] = x; m2Nx9[n*2+0][1] = y; m2Nx9[n*2+0][2] = 1; m2Nx9[n*2+0][3] = 0; m2Nx9[n*2+0][4] = 0; m2Nx9[n*2+0][5] = 0; m2Nx9[n*2+0][6] = -x*u; m2Nx9[n*2+0][7] = -y*u; m2Nx9[n*2+0][8] = -u; m2Nx9[n*2+1][0] = 0; m2Nx9[n*2+1][1] = 0; m2Nx9[n*2+1][2] = 0; m2Nx9[n*2+1][3] = x; m2Nx9[n*2+1][4] = y; m2Nx9[n*2+1][5] = 1; m2Nx9[n*2+1][6] = -x*v; m2Nx9[n*2+1][7] = -y*v; m2Nx9[n*2+1][8] = -v; } // The right null-space (should only be one) of the matrix gives the homography... SVD<> svdHomography(m2Nx9); Vector<9> vH = svdHomography.get_VT()[8]; Matrix<3> m3Homography(vH.get_data_ptr()); // Fix up possibly poorly conditioned bits of the homography { SVD<2> svdTopLeftBit(m3Homography.slice<0,0,2,2>()); Vector<2> v2Diagonal = svdTopLeftBit.get_diagonal(); m3Homography = m3Homography / v2Diagonal[0]; v2Diagonal = v2Diagonal / v2Diagonal[0]; double dLambda2 = v2Diagonal[1]; Vector<2> v2b; // This is one hypothesis for v2b ; the other is the negative. v2b[0] = 0.0; v2b[1] = sqrt( 1.0 - (dLambda2 * dLambda2)); Vector<2> v2aprime = v2b * svdTopLeftBit.get_VT(); Vector<2> v2a = m3Homography[2].slice<0,2>(); double dDotProd = v2a * v2aprime; if(dDotProd>0) m3Homography[2].slice<0,2>() = v2aprime; else m3Homography[2].slice<0,2>() = -v2aprime; } // OK, now turn homography into something 3D ...simple gram-schmidt ortho-norm // Take 3x3 matrix H with column: abt // And add a new 3rd column: abct Matrix<3> mRotation; Vector<3> vTranslation; double dMag1 = sqrt(m3Homography.T()[0] * m3Homography.T()[0]); m3Homography = m3Homography / dMag1; mRotation.T()[0] = m3Homography.T()[0]; // ( all components of the first vector are removed from the second... mRotation.T()[1] = m3Homography.T()[1] - m3Homography.T()[0]*(m3Homography.T()[0]*m3Homography.T()[1]); mRotation.T()[1] /= sqrt(mRotation.T()[1] * mRotation.T()[1]); mRotation.T()[2] = mRotation.T()[0]^mRotation.T()[1]; vTranslation = m3Homography.T()[2]; // Store result mse3CamFromWorld.get_rotation()=mRotation; mse3CamFromWorld.get_translation() = vTranslation;};vector<CalibImage::ErrorAndJacobians> CalibImage::Project(ATANCamera &Camera){ vector<ErrorAndJacobians> vResult; for(unsigned int n=0; n<mvGridCorners.size(); n++) { ErrorAndJacobians EAJ; // First, project into image... Vector<3> v3World; v3World[2] = 0.0; v3World.slice<0,2>() = vec(mvGridCorners[n].irGridPos); Vector<3> v3Cam = mse3CamFromWorld * v3World; if(v3Cam[2] <= 0.001) continue; Vector<2> v2Image = Camera.Project(project(v3Cam)); if(Camera.Invalid()) continue; EAJ.v2Error = mvGridCorners[n].Params.v2Pos - v2Image; // Now find motion jacobian.. double dOneOverCameraZ = 1.0 / v3Cam[2]; Matrix<2> m2CamDerivs = Camera.GetProjectionDerivs(); for(int dof=0; dof<6; dof++) { const Vector<4> v4Motion = SE3::generator_field(dof, unproject(v3Cam)); Vector<2> v2CamFrameMotion; v2CamFrameMotion[0] = (v4Motion[0] - v3Cam[0] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ; v2CamFrameMotion[1] = (v4Motion[1] - v3Cam[1] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ; EAJ.m26PoseJac.T()[dof] = m2CamDerivs * v2CamFrameMotion; }; // Finally, the camera provids its own jacobian EAJ.m2NCameraJac = Camera.GetCameraParameterDerivs(); vResult.push_back(EAJ); } return vResult;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -