cv::Mat mu::dlt(const std::vector<cv::Mat_<double> > &points3D, const std::vector<cv::Matx31d> &points2D) { cv::Mat A(2 * points3D.size(), 12, CV_64F); double *p = A.ptr<double>(0); //Compute A for (uint i = 0; i < points3D.size(); ++i) { // TODO: Put matrix from theory cv::Matx41d p3D(points3D.at(i).at<double>(0), points3D.at(i).at<double>(1), points3D.at(i).at<double>(2), 1); cv::Point2d p2D(points2D.at(i).val[0], points2D.at(i).val[1]); // first row *p++ = p3D.val[0]; *p++ = p3D.val[1]; *p++ = p3D.val[2]; *p++ = 1; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = -(p2D.x * p3D.val[0]); *p++ = -(p2D.x * p3D.val[1]); *p++ = -(p2D.x * p3D.val[2]); *p++ = -p2D.x; // second row *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = p3D.val[0]; *p++ = p3D.val[1]; *p++ = p3D.val[2]; *p++ = 1; *p++ = -(p2D.y * p3D.val[0]); *p++ = -(p2D.y * p3D.val[1]); *p++ = -(p2D.y * p3D.val[2]); *p++ = -p2D.y; } cv::SVD svd(A, cv::SVD::MODIFY_A | cv::SVD::FULL_UV); cv::Mat Hn = svd.vt.row(11).reshape(0, 3); // H12 return Hn; }
bool Viewer::on_eventbox_extrinsics_clicked(GdkEventButton * event) { if (mCalibration){ pthread_mutex_lock(&mutex); bool res = mCalibration->addPatternPixel ( Eigen::Vector3d ((int) event->x, (int) event->y, 1.0), mDepthVector); if (res == false) { Eigen::Vector3d p2D ((int) event->x, (int) event->y, 1.0); mCalibration->test(p2D, mDepthVector); } pthread_mutex_unlock(&mutex); } return true; }
void Run2D::runPoisson2D(int argc, char** argv) { Device2D dev2D = createDevice2D(argc, argv); Poisson2D p2D(dev2D); std::vector<double> vtgArray =p2D.rangeByStep(io2D.vtgArray[0], io2D.vtgArray[1], io2D.vtgArray[2]); std::vector<double> vbgArray =p2D.rangeByStep(io2D.vbgArray[0], io2D.vbgArray[1], io2D.vbgArray[2]); std::vector<double> vdsArray =p2D.rangeByStep(io2D.vdsArray[0], io2D.vdsArray[1], io2D.vdsArray[2]); std::vector<double> vssArray =p2D.rangeByStep(io2D.vssArray[0], io2D.vssArray[1], io2D.vssArray[2]); std::vector<int> sdIndex = p2D.sourceDrain2DLayerIndex(io2D.connect2Drain, io2D.connect2Source); std::cout << "drain index: " << sdIndex[0] << " , source index: " << sdIndex[1] << std::endl; std::cout << " ***** Poisson2D is started." << std::endl; Capacitance capa; GateEfficiency gE; GateEfficiency gE2; // for gate efficiency at the edge. /* [different bias][different bands][band data at different point] */ std::vector< std::vector< std::vector<double> > > band2DPerBias; for (double Vbg : vbgArray) { for (double Vss : vssArray) { for (double Vds : vdsArray) { // used to calculate gate efficiency: /* [different Vtg][different bands][band data at different point] */ std::vector< std::vector< std::vector<double> > > band2DPerVtg; for (double Vtg : vtgArray) { if (io2D.terminalConnect[0] == true) // Vbg = Vtg always Vbg = Vtg; std::cout << "Vbg = " << Vbg << " V; " << "Vtg = " << Vtg << " V; " << "Vds = " << Vds << " V; " << "Vss = " << Vss << std::endl; // Gate bias p2D.setGateBias_2D(io2D.gateBiasMap(Vtg, Vbg)); // Fermi levels /* Vds: Caution: the negative sign is taken into consideration within createFermiLevelMap */ p2D.setFLnArray_2D(p2D.createFermiLevelMap(io2D.connect2Drain, Vds, io2D.connect2Source, Vss)); p2D.setFLpArray_2D(p2D.createFermiLevelMap(io2D.connect2Drain, Vds, io2D.connect2Source, Vss)); // when equilibrum, Flp = Fln p2D.runPoisson2D(io2D.voltageErr, io2D.carrierConcenErr, io2D.magicNum, true); std::cout << "2D Poisson Finished." << std::endl; // Extract Data ExtractData eD; eD.bandAndCharge2D(p2D, dev2D); // first read into band info for this bias // Store the bandAlignment for selected layer for gate efficiency calculation if (Vss == 0) { eD.bASemiOnly2D(sdIndex); band2DPerVtg.push_back(eD.bandByLayer); /* [different Vtg][different bands][band data at different point] */ band2DPerBias.push_back(eD.bandByLayer); /* [different bias][different bands][band data at different point] */ } // read top gate charge into capa for later capacitance calculation capa.readCharge(Vtg, Vbg, Vds, Vss, eD.topGateCharge2D(dev2D, io2D.topGateArea)); // read in all the data needed for capa } if (Vss == 0) { // measure near the center of the channel gE.calGateEfficiency(Vbg, Vds, io2D.vtgArray[0], io2D.vtgArray[2], 100, 100, 10, 100, band2DPerVtg); // measure at the edge for Thin-TFET (SO, only use it for Thin-TFET!!) gE2.calGateEfficiency(Vbg, Vds, io2D.vtgArray[0], io2D.vtgArray[2], io2D.blockPoint[0] + io2D.blockPoint[1], io2D.blockPoint[0] + io2D.blockPoint[1], // for ThinTFET, valence band in bottom, conduction band in top 10, 100, band2DPerVtg); } } } if (io2D.terminalConnect[0] == true) // Vbg = Vtg always break; } capa.calCggCgsCgd(vtgArray, vbgArray, vdsArray, vssArray, io2D.terminalConnect); // calculate capacitance /** * Output */ io2D.writeBandsinSemi(io2D.devName+"_"+io2D.userCom+"_Bands", vtgArray, vdsArray, vbgArray, band2DPerBias); // io2D.writeCapaMap(io2D.devName+"_"+io2D.userCom+"_Cgs", capa.getCgsMap()); // io2D.writeCapaMap(io2D.devName+"_"+io2D.userCom+"_Cgd", capa.getCgdMap()); // io2D.writeCapaMap(io2D.devName+"_"+io2D.userCom+"_Cgg", capa.getCggMap()); // io2D.writeGateEffMap(io2D.devName+"_"+io2D.userCom+"_GateEfficiency_atChannelCenter", gE.getGateEffMap()); // io2D.writeGateEffMap(io2D.devName+"_"+io2D.userCom+"_GateEfficiency_atEdgeThinTFET", gE2.getGateEffMap()); }
/** * @brief Generates a optimised point cloud from a collection of processed keyframes using sparse bundle adjustment. * @param allFrames A vector containing keyframes which have been completely processed. * @param outputCloud The cloud generated from the keyframes. */ void utils::calculateSBACloud(std::vector<KeyframeContainer>& allFrames,boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >& outputCloud) { sba::SysSBA bundleAdjuster; //set the verbosity of the bundle adjuster #ifndef NDEBUG bundleAdjuster.verbose=100; #else bundleAdjuster.verbose=0; #endif //a list of keypoints that already have been added to the SBA system std::vector<std::pair<int,uint> > addedPoints; //(frameID,keypointIndex) //maps frame IDs to frame index in the vector std::map<int,uint> ID2Ind; for(uint f=0;f<allFrames.size();++f) ID2Ind[allFrames[f].ID]=f; //maps the frame vector index to the node vector index std::map<uint,int> fInd2NInd; //count the number of 2D/3D-points and camera nodes if in debug mode #ifndef NDEBUG uint nrP3D=0; uint nrP2D=0; uint nrC=0; #endif //add every valid frame as a camera node to the sba system for(uint f=0;f<allFrames.size();++f) { if(!allFrames[f].invalid) { //get rotation and translation from the projection matrix Eigen::Matrix3d rot; cv::Mat_<double> cvT; Eigen::Vector4d t; //get rotation for(int x=0;x<3;++x) for(int y=0;y<3;++y) rot(x,y)=allFrames[f].projectionMatrix(x,y); //solve for translation cv::solve(allFrames[f].projectionMatrix(cv::Range(0,3),cv::Range(0,3)),allFrames[f].projectionMatrix(cv::Range(0,3),cv::Range(3,4)),cvT); //save translation for(int x=0;x<3;++x) t(x)=-cvT(x,0); t(3)=1.0; //convert rotation to quaternion Eigen::Quaterniond qrot(rot); qrot.normalize(); //convert camera calibration matrix frame_common::CamParams cameraParameters; cameraParameters.fx=allFrames[f].cameraCalibration(0,0); cameraParameters.fy=allFrames[f].cameraCalibration(1,1); cameraParameters.cx=allFrames[f].cameraCalibration(0,2); cameraParameters.cy=allFrames[f].cameraCalibration(1,2); cameraParameters.tx=0.0; //add the frame as a camera node fInd2NInd[f]=bundleAdjuster.addNode(t,qrot,cameraParameters,false); #ifndef NDEBUG ++nrC; #endif } else fInd2NInd[f]=-1; } //add the points to the correct nodes for(uint f=0;f<allFrames.size();++f) { if(!allFrames[f].invalid) { //add the points for(uint m=0;m<allFrames[f].matches.size();++m) { std::pair<int,uint> myP(allFrames[f].ID,m); bool goodToAdd=!utils::vectorContainsElement(addedPoints,myP); //point hasn't been added yet if(goodToAdd) { //check if the point has valid depth information float depth=allFrames[f].depthImg.image.at<float>(allFrames[f].keypoints[m].pt.y,allFrames[f].keypoints[m].pt.x); if(isnan(depth)==0) { //find the largest completely connected component emanating from this point (clique) std::vector<std::pair<int,uint> > pointsComplete; pointsComplete.push_back(std::pair<int,uint>(allFrames[f].ID,m)); //check all matches of the point if they haven't been added yet and their frame is valid for(uint o=0;o<allFrames[f].matches[m].size();++o) { std::pair<int,uint> newElement(allFrames[f].matches[m][o].first.val[0],allFrames[f].matches[m][o].first.val[1]); if(!utils::vectorContainsElement(addedPoints,newElement) && !allFrames[ID2Ind[newElement.first]].invalid) pointsComplete.push_back(newElement); } //weed out all points that are not completely connected while(pointsComplete.size()>1) { //find the point with the fewest connections (if the component is completely connected all points have the same number of connections) uint minCorrespondences=pointsComplete.size(); uint worstInd=0; for(uint i=0;i<pointsComplete.size();++i) { //count the number of connections that this point has uint fInd=ID2Ind[pointsComplete[i].first]; uint myCorr=0; for(uint q=0;q<allFrames[fInd].matches.size();++q) for(uint r=0;r<allFrames[fInd].matches[q].size();++r) { std::pair<int,uint> tmpElement(allFrames[fInd].matches[q][r].first.val[0],allFrames[fInd].matches[q][r].first.val[1]); if(utils::vectorContainsElement(pointsComplete,tmpElement)) ++myCorr; } //save this point if it is the current worst if(myCorr<minCorrespondences) { minCorrespondences=myCorr; worstInd=i; } } //if the worst point has not the maximal number of connections erase it, else break as all points have the maximal number of connections if(minCorrespondences<pointsComplete.size()-1) { pointsComplete.erase(pointsComplete.begin()+worstInd); } else break; } //now pointsComplete contains the clique if the clique has more than one isolated point, write the points to the system if(pointsComplete.size()>1) { //calculate the 3D point and add it to the system cv::Mat_<double> p2D(2,1,0.0); p2D(0,0)=allFrames[f].keypoints[m].pt.x; p2D(1,0)=allFrames[f].keypoints[m].pt.y; cv::Mat_<double> p3D=reprojectImagePointTo3D(p2D,allFrames[f].cameraCalibration,allFrames[f].projectionMatrix,depth); Eigen::Vector4d newPoint; for(uint x=0;x<4;++x) newPoint(x)=p3D(x,0); int pointIndex=bundleAdjuster.addPoint(newPoint); #ifndef NDEBUG ++nrP3D; #endif //add all image points corresponding to the 3D point to the system for(uint i=0;i<pointsComplete.size();++i) { uint fInd=ID2Ind[pointsComplete[i].first]; Eigen::Vector2d imgPoint; imgPoint(0)=allFrames[fInd].keypoints[pointsComplete[i].second].pt.x; imgPoint(1)=allFrames[fInd].keypoints[pointsComplete[i].second].pt.y; bundleAdjuster.addMonoProj(fInd2NInd[fInd],pointIndex,imgPoint); #ifndef NDEBUG ++nrP2D; #endif } } } } } } } #ifndef NDEBUG ROS_INFO("C: %u;3D: %u;2D: %u",nrC,nrP3D,nrP2D); #endif //remove bad tracks bundleAdjuster.calcCost(); bundleAdjuster.removeBad(2); bundleAdjuster.reduceTracks(); //run 100 iterations of sba bundleAdjuster.doSBA(100,1e-3, SBA_SPARSE_CHOLESKY); //save the new projective matrix calculated with sba for(uint f=0;f<allFrames.size();++f) if(!allFrames[f].invalid) for(int x=0;x<3;++x) for(int y=0;y<4;++y) allFrames[f].projectionMatrix(x,y)=bundleAdjuster.nodes[fInd2NInd[f]].w2n(x,y); //generate the point cloud from the new projection matrices utils::generateCloud(allFrames,*outputCloud); }