#include "alignment.h" #include //-------------------------------------------------alignment order void ImageAligner::sortImageOrder(int referNo, bool shallLoad, bool isInorder) { cout<<"#Finding topology ..."< costGraph = Utils::buildCostGraph(_similarityMat); cout<<"-Completed"<_imgSizeList; //! =============== Topology sorting =============== bool shallLoad = loadTopology, isInOrder = isSeqData; //! ### set this for new data sortImageOrder(referNo, shallLoad, isInOrder); //! =============== build match net =============== fillImageMatchNet(); // loadHomographies(); cout<<"#Sequential image alignment start ..."< identMatrix = Mat::eye(3,3,CV_64FC1); //cvtMatrix of reference image _alignModelList.push_back(identMatrix); _initModelList.push_back(identMatrix); Quadra bar; bar.imgSize = _imgSizeList[_visitOrder[0].imgNo]; bar.centroid = Point2d(bar.imgSize.width/2, bar.imgSize.height/2); _projCoordSet.push_back(bar); for (int i = 1; i < _groupCusorList.size(); i ++) { int sIndex = _groupCusorList[i-1]+1; int eIndex = _groupCusorList[i]; cout<<"Aligning Group "<_imgSizeList; //! =============== Topology sorting =============== bool shallLoad = loadTopology, isInOrder = isSeqData; //! ### set this for new data sortImageOrder(referNo, shallLoad, isInOrder); // return false; //! =============== build match net =============== fillImageMatchNet(); cout<<"#Sequential image alignment start ..."< identMatrix = Mat::eye(3,3,CV_64FC1); //cvtMatrix of reference image _alignModelList.push_back(identMatrix); _initModelList.push_back(identMatrix); bool needRefine = true; for (int i = 1; i < _imgNum; i ++) { cout<<"Aligning Image "<<_visitOrder[i].imgNo<<" "; solveSingleModel(i); if (needRefine && 0) { for (int j = 0; j < _groupCusorList.size(); j ++) { if (i == _groupCusorList[j]) { int sIndex = _groupCusorList[j-1]+1; int eIndex = _groupCusorList[j]; bundleAdjustingA(sIndex, eIndex); break; } } } cout<<"Done!"< PtSet1, PtSet2; if (!Utils::loadMatchPts(i,j,PtSet1,PtSet2)) { continue; } sum += PtSet1.size(); int indexj = findVisitIndex(j); _matchNetList[i].relatedImgs.push_back(indexj); _matchNetList[i].PointSet.push_back(PtSet1); int indexi = findVisitIndex(i); _matchNetList[j].relatedImgs.push_back(indexi); _matchNetList[j].PointSet.push_back(PtSet2); } } cout<<"-Completed! - with "< > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) //! avoid repeating counting { measureNum += pointSet[j].size(); } } } int paramNum = 6*(eIndex-sIndex+1); Mat_ A = Mat(2*measureNum, paramNum, CV_64FC1, Scalar(0)); Mat_ L = Mat(2*measureNum, 1, CV_64FC1, Scalar(0)); int rn = 0; for (int i = sIndex; i <= eIndex; i ++) { int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { int neigIndex = relatedNos[j]; if (neigIndex > i) { continue; } int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; vector curPts, neigPts; curPts = pointSet[j]; //! case 1 : aligning with aligned image if (neigIndex < sIndex) { for (int t = 0; t < neigRelatedNos.size(); t ++) { if (neigRelatedNos[t] == i) { neigPts = _matchNetList[neigImgNo].PointSet[t]; Utils::pointTransform(_alignModelList[neigIndex], neigPts); break; } } int fillPos = 6*(i-sIndex); for (int k = 0; k < curPts.size(); k ++) { A(2*rn,fillPos) = curPts[k].x; A(2*rn,fillPos+1) = curPts[k].y; A(2*rn,fillPos+2) = 1; A(2*rn+1,fillPos+3) = curPts[k].x; A(2*rn+1,fillPos+4) = curPts[k].y; A(2*rn+1,fillPos+5) = 1; L(2*rn) = neigPts[k].x; L(2*rn+1) = neigPts[k].y; rn ++; } } //! case 2 : aligning with unaligned image else if (neigIndex >= sIndex) { for (int t = 0; t < neigRelatedNos.size(); t ++) { if (neigRelatedNos[t] == i) { neigPts = _matchNetList[neigImgNo].PointSet[t]; break; } } int fillPos1 = 6*(i-sIndex), fillPos2 = 6*(neigIndex-sIndex); for (int k = 0; k < curPts.size(); k ++) { A(2*rn,fillPos1) = curPts[k].x; A(2*rn,fillPos1+1) = curPts[k].y; A(2*rn,fillPos1+2) = 1; A(2*rn+1,fillPos1+3) = curPts[k].x; A(2*rn+1,fillPos1+4) = curPts[k].y; A(2*rn+1,fillPos1+5) = 1; A(2*rn,fillPos2) = -neigPts[k].x; A(2*rn,fillPos2+1) = -neigPts[k].y; A(2*rn,fillPos2+2) = -1; A(2*rn+1,fillPos2+3) = -neigPts[k].x; A(2*rn+1,fillPos2+4) = -neigPts[k].y; A(2*rn+1,fillPos2+5) = -1; L(2*rn) = 0; L(2*rn+1) = 0; rn ++; } } } } Mat_ X = (A.t()*A).inv()*(A.t()*L); for (int i = 0; i < paramNum; i += 6) { Mat_ affineModel = (Mat_(3,3) << X(i) , X(i+1), X(i+2), X(i+3), X(i+4), X(i+5), 0, 0, 1); _alignModelList.push_back(affineModel); _initModelList.push_back(affineModel); } } void ImageAligner::solveGroupModelsS(int sIndex, int eIndex) { int measureNum = 0; for (int i = sIndex; i <= eIndex; i ++) { int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) //! avoid repeating counting { measureNum += pointSet[j].size(); } } } int paramNum = 4*(eIndex-sIndex+1); Mat_ A = Mat(2*measureNum, paramNum, CV_64FC1, Scalar(0)); Mat_ L = Mat(2*measureNum, 1, CV_64FC1, Scalar(0)); int rn = 0; for (int i = sIndex; i <= eIndex; i ++) { int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { int neigIndex = relatedNos[j]; if (neigIndex > i) { continue; } int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; vector curPts, neigPts; curPts = pointSet[j]; //! case 1 : aligning with aligned image if (neigIndex < sIndex) { for (int t = 0; t < neigRelatedNos.size(); t ++) { if (neigRelatedNos[t] == i) { neigPts = _matchNetList[neigImgNo].PointSet[t]; Utils::pointTransform(_alignModelList[neigIndex], neigPts); break; } } int fillPos = 4*(i-sIndex); for (int k = 0; k < curPts.size(); k ++) { A(2*rn,fillPos) = curPts[k].x; A(2*rn,fillPos+1) = -curPts[k].y; A(2*rn,fillPos+2) = 1; A(2*rn+1,fillPos) = curPts[k].y; A(2*rn+1,fillPos+1) = curPts[k].x; A(2*rn+1,fillPos+3) = 1; L(2*rn) = neigPts[k].x; L(2*rn+1) = neigPts[k].y; rn ++; } } //! case 2 : aligning with unaligned image else if (neigIndex >= sIndex) { for (int t = 0; t < neigRelatedNos.size(); t ++) { if (neigRelatedNos[t] == i) { neigPts = _matchNetList[neigImgNo].PointSet[t]; break; } } int fillPos1 = 4*(i-sIndex), fillPos2 = 4*(neigIndex-sIndex); for (int k = 0; k < curPts.size(); k ++) { A(2*rn,fillPos1) = curPts[k].x; A(2*rn,fillPos1+1) = -curPts[k].y; A(2*rn,fillPos1+2) = 1; A(2*rn+1,fillPos1) = curPts[k].y; A(2*rn+1,fillPos1+1) = curPts[k].x; A(2*rn+1,fillPos1+3) = 1; A(2*rn,fillPos2) = -neigPts[k].x; A(2*rn,fillPos2+1) = neigPts[k].y; A(2*rn,fillPos2+2) = -1; A(2*rn+1,fillPos2) = -neigPts[k].y; A(2*rn+1,fillPos2+1) = -neigPts[k].x; A(2*rn+1,fillPos2+3) = -1; L(2*rn) = 0; L(2*rn+1) = 0; rn ++; } } } } Mat_ X = (A.t()*A).inv()*(A.t()*L); for (int i = 0; i < paramNum; i += 4) { Mat_ affineModel = (Mat_(3,3) << X(i) , -X(i+1), X(i+2), X(i+1), X(i), X(i+3), 0, 0, 1); // cout< relatedNos = _matchNetList[imgNo].relatedImgs; vector > pointSet = _matchNetList[imgNo].PointSet; for (int i = 0; i < relatedNos.size(); i ++) { if (relatedNos[i] < imgIndex) { measureNum += pointSet[i].size(); } } int paramNum = 6; Mat_ A = Mat(2*measureNum, paramNum, CV_64FC1, Scalar(0)); Mat_ L = Mat(2*measureNum, 1, CV_64FC1, Scalar(0)); int rn = 0; vector PtSet1, PtSet2; for (int i = 0; i < relatedNos.size(); i ++) { int neigIndex = relatedNos[i]; if (neigIndex > imgIndex) { continue; } vector curPts, neigPts; curPts = pointSet[i]; int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; for (int t = 0; t < neigRelatedNos.size(); t ++) { if (neigRelatedNos[t] == imgIndex) { neigPts = _matchNetList[neigImgNo].PointSet[t]; Utils::pointTransform(_alignModelList[neigIndex], neigPts); break; } } for (int k = 0; k < curPts.size(); k ++) { A(2*rn,0) = curPts[k].x; A(2*rn,1) = curPts[k].y; A(2*rn,2) = 1; A(2*rn+1,3) = curPts[k].x; A(2*rn+1,4) = curPts[k].y; A(2*rn+1,5) = 1; L(2*rn) = neigPts[k].x; L(2*rn+1) = neigPts[k].y; rn ++; } //! for homogaphy //for (int k = 0; k < curPts.size(); k ++) //{ // PtSet1.push_back(curPts[k]); // PtSet2.push_back(neigPts[k]); //} } Mat_ X = (A.t()*A).inv()*(A.t()*L); Mat_ affineModel = (Mat_(3,3) << X(0), X(1), X(2), X(3), X(4), X(5), 0, 0, 1); // Mat_ homoMat = findHomography(PtSet1, PtSet2, CV_RANSAC, 1.5); _alignModelList.push_back(affineModel); _initModelList.push_back(affineModel); } void ImageAligner::bundleAdjusting(int sIndex, int eIndex) { cout<<"Bundle adjusting ...("< > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) //! avoid repeating counting { int num = pointSet[j].size(); num = num%3 == 0 ? (num/3) : (num/3+1); measureNum += num; //! only 1/3 of matching pairs for optimization } } } int paramNum = 8*(eIndex-sIndex+1); //! optimizing homgraphic model with 8 DoF double *X = new double[paramNum]; double *initX = new double[6*(eIndex-sIndex+1)]; buildIniSolution(X, initX, sIndex, eIndex); //! parameters setting of least square optimization double lambada = Lambada; int max_iters = 10; int rn = 0, ite = 0; while (1) { double meanBias = 0; rn = 0; Mat_ AtA = Mat(paramNum, paramNum, CV_64FC1, Scalar(0)); Mat_ AtL = Mat(paramNum, 1, CV_64FC1, Scalar(0)); for (int i = sIndex; i <= eIndex; i ++) { //! prepare relative data or parameters of current image int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { int neigIndex = relatedNos[j]; if (neigIndex > i) { continue; } vector curPts, neigPts; curPts = pointSet[j]; int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; for (int k = 0; k < neigRelatedNos.size(); k ++) { if (neigRelatedNos[k] == i) { neigPts = _matchNetList[neigImgNo].PointSet[k]; break; } } int curse0 = i-sIndex, curse1 = neigIndex-sIndex; int fillPos0 = curse0*8, fillPos1 = curse1*8; int num = curPts.size(), n = 0; Mat_ Ai = Mat(num, paramNum, CV_64FC1, Scalar(0)); Mat_ Li = Mat(num, 1, CV_64FC1, Scalar(0)); double *AiPtr = (double*)Ai.data; double *LiPtr = (double*)Li.data; //! case 1 : with a fixed image if (neigIndex < sIndex) { Utils::pointTransform(_alignModelList[neigIndex], neigPts); for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; double K1 = 2*(hX0/hW0-x1) + 2*lambada*(hX0/hW0-orgx0); double K2 = 2*(hY0/hW0-y1) + 2*lambada*(hY0/hW0-orgy0); //! for : x = ... AiPtr[n*paramNum+fillPos0] = K1*x0/hW0; AiPtr[n*paramNum+fillPos0+1] = K1*y0/hW0; AiPtr[n*paramNum+fillPos0+2] = K1*1/hW0; AiPtr[n*paramNum+fillPos0+3] = K2*x0/hW0; AiPtr[n*paramNum+fillPos0+4] = K2*y0/hW0; AiPtr[n*paramNum+fillPos0+5] = K2*1/hW0; AiPtr[n*paramNum+fillPos0+6] = -(K1+K2)*x0*hX0/(hW0*hW0); AiPtr[n*paramNum+fillPos0+7] = -(K1+K2)*y0*hX0/(hW0*hW0); double delta_d = (hX0/hW0-x1)*(hX0/hW0-x1) + (hY0/hW0-y1)*(hY0/hW0-y1); double delta_r = lambada*((hX0/hW0-orgx0)*(hX0/hW0-orgx0) + (hY0/hW0-orgy0)*(hY0/hW0-orgy0)); LiPtr[n] = -(delta_d+delta_r); double bias = sqrt(delta_d+delta_r); meanBias += bias; n ++; rn ++; } //! get in normal equation matrix Mat_ Ait = Ai.t(); Mat_ barA = Ait*Ai, barL = Ait*Li; AtA += barA; AtL += barL; continue; } //! case 2 : with a remain optimized image for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 double hX1 = X[fillPos1+0]*x1 + X[fillPos1+1]*y1 + X[fillPos1+2]; //! h1'*x1 + h2'*y1 + h3' double hY1 = X[fillPos1+3]*x1 + X[fillPos1+4]*y1 + X[fillPos1+5]; //! h4'*x1 + h5'*y1 + h6' double hW1 = X[fillPos1+6]*x1 + X[fillPos1+7]*y1 + 1; //! h7'*x1 + h8'*y1 + 1 double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; double orgx1 = initX[6*curse1+0]*x1 + initX[6*curse1+1]*y1 + initX[6*curse1+2]; double orgy1 = initX[6*curse1+3]*x1 + initX[6*curse1+4]*y1 + initX[6*curse1+5]; double K1 = 2*(hX0/hW0-hX1/hW1) + 2*lambada*(hX0/hW0-orgx0); double K2 = 2*(hY0/hW0-hY1/hW1) + 2*lambada*(hY0/hW0-orgy0); double K3 = -2*(hX0/hW0-hX1/hW1) + 2*lambada*(hX1/hW1-orgx1); double K4 = -2*(hY0/hW0-hY1/hW1) + 2*lambada*(hY1/hW1-orgy1); //! for : x = ... //! cur-image AiPtr[n*paramNum+fillPos0] = K1*x0/hW0; AiPtr[n*paramNum+fillPos0+1] = K1*y0/hW0; AiPtr[n*paramNum+fillPos0+2] = K1*1/hW0; AiPtr[n*paramNum+fillPos0+3] = K2*x0/hW0; AiPtr[n*paramNum+fillPos0+4] = K2*y0/hW0; AiPtr[n*paramNum+fillPos0+5] = K2*1/hW0; AiPtr[n*paramNum+fillPos0+6] = -(K1+K2)*x0*hX0/(hW0*hW0); AiPtr[n*paramNum+fillPos0+7] = -(K1+K2)*y0*hX0/(hW0*hW0); //! neig-image AiPtr[n*paramNum+fillPos1] = K3*x1/hW1; AiPtr[n*paramNum+fillPos1+1] = K3*y1/hW1; AiPtr[n*paramNum+fillPos1+2] = K3*1/hW1; AiPtr[n*paramNum+fillPos1+3] = K4*x1/hW1; AiPtr[n*paramNum+fillPos1+4] = K4*y1/hW1; AiPtr[n*paramNum+fillPos1+5] = K4*1/hW1; AiPtr[n*paramNum+fillPos1+6] = -(K3+K4)*x1*hX1/(hW1*hW1); AiPtr[n*paramNum+fillPos1+7] = -(K3+K4)*y1*hX1/(hW1*hW1); double delta_d = (hX0/hW0-hX1/hW1)*(hX0/hW0-hX1/hW1) + (hY0/hW0-hY1/hW1)*(hY0/hW0-hY1/hW1); double delta_r = lambada*((hX0/hW0-orgx0)*(hX0/hW0-orgx0) + (hY0/hW0-orgy0)*(hY0/hW0-orgy0) + (hX1/hW1-orgx1)*(hX1/hW1-orgx1) + (hY1/hW1-orgy1)*(hY1/hW1-orgy1)); LiPtr[n] = -(delta_d+delta_r); double bias = sqrt(delta_d+delta_r); meanBias += bias; rn ++; n ++; } //! get in normal equation matrix Mat_ Ait = Ai.t(); Mat_ barA = Ait*Ai, barL = Ait*Li; AtA += barA; AtL += barL; } } meanBias = meanBias/rn; cout<<"Iteration: "< dX = AtA.inv()*AtL; double *dXPtr = (double*)dX.data; double delta = 0; //! record the translation parameters of images int num = 0; for (int i = 0; i < paramNum; i ++) { X[i] += dXPtr[i]; if ((i+1)%8 == 3 || (i+1)%8 == 6) { // cout< > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) //! avoid repeating counting { int num = pointSet[j].size(); num = num%3 == 0 ? (num/3) : (num/3+1); measureNum += num; //! only 1/3 of matching pairs for optimization } } } int paramNum = 8*(eIndex-sIndex+1); //! optimizing homgraphic model with 8 DoF Mat_ A = Mat(2*measureNum, paramNum, CV_64FC1, Scalar(0)); Mat_ L = Mat(2*measureNum, 1, CV_64FC1, Scalar(0)); double *APtr = (double*)A.data; double *LPtr = (double*)L.data; double *X = new double[paramNum]; double *initX = new double[6*(eIndex-sIndex+1)]; buildIniSolution(X, initX, sIndex, eIndex); //! parameters setting of least square optimization double lambada = Lambada; int max_iters = 10; int rn = 0, ite = 0; while (1) { double meanBias = 0; rn = 0; for (int i = sIndex; i <= eIndex; i ++) { //! prepare relative data or parameters of current image int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { int neigIndex = relatedNos[j]; if (neigIndex > i) { continue; } vector curPts, neigPts; curPts = pointSet[j]; int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; for (int k = 0; k < neigRelatedNos.size(); k ++) { if (neigRelatedNos[k] == i) { neigPts = _matchNetList[neigImgNo].PointSet[k]; break; } } int curse0 = i-sIndex, curse1 = neigIndex-sIndex; int fillPos0 = curse0*8, fillPos1 = curse1*8; //! case 1 : with a fixed image if (neigIndex < sIndex) { Utils::pointTransform(_alignModelList[neigIndex], neigPts); for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 //! for : x = ... //A(2*rn,fillPos0) = (1+lambada)*x0/hW0; A(2*rn,fillPos0+1) = (1+lambada)*y0/hW0; A(2*rn,fillPos0+2) = (1+lambada)*1/hW0; //A(2*rn,fillPos0+6) = -(1+lambada)*x0*hX0/(hW0*hW0); A(2*rn,fillPos0+7) = -(1+lambada)*y0*hX0/(hW0*hW0); APtr[2*rn*paramNum+fillPos0] = (1+lambada)*x0/hW0; APtr[2*rn*paramNum+fillPos0+1] = (1+lambada)*y0/hW0; APtr[2*rn*paramNum+fillPos0+2] = (1+lambada)*1/hW0; APtr[2*rn*paramNum+fillPos0+6] = -(1+lambada)*x0*hX0/(hW0*hW0); APtr[2*rn*paramNum+fillPos0+7] = -(1+lambada)*y0*hX0/(hW0*hW0); double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; //L(2*rn) = lambada*(orgx0)+x1 - ((1+lambada)*hX0/hW0); LPtr[2*rn] = lambada*(orgx0)+x1 - ((1+lambada)*hX0/hW0); //! for : y = ... //A(2*rn+1,fillPos0+3) = (1+lambada)*x0/hW0; A(2*rn+1,fillPos0+4) = (1+lambada)*y0/hW0; A(2*rn+1,fillPos0+5) = (1+lambada)*1/hW0; //A(2*rn+1,fillPos0+6) = -(1+lambada)*x0*hY0/(hW0*hW0); A(2*rn+1,fillPos0+7) = -(1+lambada)*y0*hY0/(hW0*hW0); APtr[(2*rn+1)*paramNum+fillPos0+3] = (1+lambada)*x0/hW0; APtr[(2*rn+1)*paramNum+fillPos0+4] = (1+lambada)*y0/hW0; APtr[(2*rn+1)*paramNum+fillPos0+5] = (1+lambada)*1/hW0; APtr[(2*rn+1)*paramNum+fillPos0+6] = -(1+lambada)*x0*hY0/(hW0*hW0); APtr[(2*rn+1)*paramNum+fillPos0+7] = -(1+lambada)*y0*hY0/(hW0*hW0); double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; //L(2*rn+1) = lambada*(orgy0)+y1 - ((1+lambada)*hY0/hW0); LPtr[2*rn+1] = lambada*(orgy0)+y1 - ((1+lambada)*hY0/hW0); double bias = (L(2*rn)*L(2*rn) + L(2*rn+1)*L(2*rn+1)); meanBias += sqrt(bias); rn ++; } continue; } //! case 2 : with a remain optimized image for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 double hX1 = X[fillPos1+0]*x1 + X[fillPos1+1]*y1 + X[fillPos1+2]; //! h1'*x1 + h2'*y1 + h3' double hY1 = X[fillPos1+3]*x1 + X[fillPos1+4]*y1 + X[fillPos1+5]; //! h4'*x1 + h5'*y1 + h6' double hW1 = X[fillPos1+6]*x1 + X[fillPos1+7]*y1 + 1; //! h7'*x1 + h8'*y1 + 1 //! for : x = ... //! cur-image //A(2*rn,fillPos0) = (1+lambada)*x0/hW0; A(2*rn,fillPos0+1) = (1+lambada)*y0/hW0; A(2*rn,fillPos0+2) = (1+lambada)*1/hW0; //A(2*rn,fillPos0+6) = -(1+lambada)*x0*hX0/(hW0*hW0); A(2*rn,fillPos0+7) = -(1+lambada)*y0*hX0/(hW0*hW0); APtr[2*rn*paramNum+fillPos0] = (1+lambada)*x0/hW0; APtr[2*rn*paramNum+fillPos0+1] = (1+lambada)*y0/hW0; APtr[2*rn*paramNum+fillPos0+2] = (1+lambada)*1/hW0; APtr[2*rn*paramNum+fillPos0+6] = -(1+lambada)*x0*hX0/(hW0*hW0); APtr[2*rn*paramNum+fillPos0+7] = -(1+lambada)*y0*hX0/(hW0*hW0); //! neig-image //A(2*rn,fillPos1) = (lambada-1)*x1/hW1; A(2*rn,fillPos1+1) = (lambada-1)*y1/hW1; A(2*rn,fillPos1+2) = (lambada-1)*1/hW1; //A(2*rn,fillPos1+6) = -(lambada-1)*x1*hX1/(hW1*hW1); A(2*rn,fillPos1+7) = -(lambada-1)*y1*hX1/(hW1*hW1); APtr[2*rn*paramNum+fillPos1] = (lambada-1)*x1/hW1; APtr[2*rn*paramNum+fillPos1+1] = (lambada-1)*y1/hW1; APtr[2*rn*paramNum+fillPos1+2] = (lambada-1)*1/hW1; APtr[2*rn*paramNum+fillPos1+6] = -(lambada-1)*x1*hX1/(hW1*hW1); APtr[2*rn*paramNum+fillPos1+7] = -(lambada-1)*y1*hX1/(hW1*hW1); double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; double orgx1 = initX[6*curse1+0]*x1 + initX[6*curse1+1]*y1 + initX[6*curse1+2]; //L(2*rn) = lambada*(orgx0+orgx1) - ((1+lambada)*hX0/hW0 + (lambada-1)*hX1/hW1); LPtr[2*rn] = lambada*(orgx0+orgx1) - ((1+lambada)*hX0/hW0 + (lambada-1)*hX1/hW1); //! for : y = ... //! cur-image //A(2*rn+1,fillPos0+3) = (1+lambada)*x0/hW0; A(2*rn+1,fillPos0+4) = (1+lambada)*y0/hW0; A(2*rn+1,fillPos0+5) = (1+lambada)*1/hW0; //A(2*rn+1,fillPos0+6) = -(1+lambada)*x0*hY0/(hW0*hW0); A(2*rn+1,fillPos0+7) = -(1+lambada)*y0*hY0/(hW0*hW0); APtr[(2*rn+1)*paramNum+fillPos0+3] = (1+lambada)*x0/hW0; APtr[(2*rn+1)*paramNum+fillPos0+4] = (1+lambada)*y0/hW0; APtr[(2*rn+1)*paramNum+fillPos0+5] = (1+lambada)*1/hW0; APtr[(2*rn+1)*paramNum+fillPos0+6] = -(1+lambada)*x0*hY0/(hW0*hW0); APtr[(2*rn+1)*paramNum+fillPos0+7] = -(1+lambada)*y0*hY0/(hW0*hW0); //! neig-image //A(2*rn+1,fillPos1+3) = (lambada-1)*x1/hW1; A(2*rn+1,fillPos1+4) = (lambada-1)*y1/hW1; A(2*rn+1,fillPos1+5) = (lambada-1)*1/hW1; //A(2*rn+1,fillPos1+6) = -(lambada-1)*x1*hY1/(hW1*hW1); A(2*rn+1,fillPos1+7) = -(lambada-1)*y1*hY1/(hW1*hW1); APtr[(2*rn+1)*paramNum+fillPos1+3] = (lambada-1)*x1/hW1; APtr[(2*rn+1)*paramNum+fillPos1+4] = (lambada-1)*y1/hW1; APtr[(2*rn+1)*paramNum+fillPos1+5] = (lambada-1)*1/hW1; APtr[(2*rn+1)*paramNum+fillPos1+6] = -(lambada-1)*x1*hY1/(hW1*hW1); APtr[(2*rn+1)*paramNum+fillPos1+7] = -(lambada-1)*y1*hY1/(hW1*hW1); double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; double orgy1 = initX[6*curse1+3]*x1 + initX[6*curse1+4]*y1 + initX[6*curse1+5]; //L(2*rn+1) = lambada*(orgy0+orgy1) - ((1+lambada)*hY0/hW0 + (lambada-1)*hY1/hW1); LPtr[2*rn+1] = lambada*(orgy0+orgy1) - ((1+lambada)*hY0/hW0 + (lambada-1)*hY1/hW1); double bias = (L(2*rn)*L(2*rn) + L(2*rn+1)*L(2*rn+1)); meanBias += sqrt(bias); rn ++; } } } meanBias = meanBias/rn; cout<<"Iteration: "< At = A.t(); Mat_ dX = (At*A).inv()*(At*L); // cout< > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) //! avoid repeating counting { int num = pointSet[j].size(); num = num%3 == 0 ? (num/3) : (num/3+1); measureNum += num; //! only 1/3 of matching pairs for optimization } } } int paramNum = 8*(eIndex-sIndex+1); //! optimizing homgraphic model with 8 DoF double *X = new double[paramNum]; double *initX = new double[6*(eIndex-sIndex+1)]; buildIniSolution(X, initX, sIndex, eIndex); //! parameters setting of least square optimization double lambada = Lambada; int max_iters = 10; int rn = 0, ite = 0; while (1) { double meanBias = 0; rn = 0; Mat_ AtA = Mat(paramNum, paramNum, CV_64FC1, Scalar(0)); Mat_ AtL = Mat(paramNum, 1, CV_64FC1, Scalar(0)); for (int i = sIndex; i <= eIndex; i ++) { //! prepare relative data or parameters of current image int imgNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[imgNo].PointSet; vector relatedNos = _matchNetList[imgNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { int neigIndex = relatedNos[j]; if (neigIndex > i) { continue; } vector curPts, neigPts; curPts = pointSet[j]; int neigImgNo = _visitOrder[neigIndex].imgNo; vector neigRelatedNos = _matchNetList[neigImgNo].relatedImgs; for (int k = 0; k < neigRelatedNos.size(); k ++) { if (neigRelatedNos[k] == i) { neigPts = _matchNetList[neigImgNo].PointSet[k]; break; } } int curse0 = i-sIndex, curse1 = neigIndex-sIndex; int fillPos0 = curse0*8, fillPos1 = curse1*8; int num = curPts.size(), n = 0; Mat_ Ai = Mat(2*num, paramNum, CV_64FC1, Scalar(0)); Mat_ Li = Mat(2*num, 1, CV_64FC1, Scalar(0)); double *AiPtr = (double*)Ai.data; double *LiPtr = (double*)Li.data; //! case 1 : with a fixed image if (neigIndex < sIndex) { Utils::pointTransform(_alignModelList[neigIndex], neigPts); for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 //! for : x = ... AiPtr[2*n*paramNum+fillPos0] = (1+lambada)*x0/hW0; AiPtr[2*n*paramNum+fillPos0+1] = (1+lambada)*y0/hW0; AiPtr[2*n*paramNum+fillPos0+2] = (1+lambada)*1/hW0; AiPtr[2*n*paramNum+fillPos0+6] = -(1+lambada)*x0*hX0/(hW0*hW0); AiPtr[2*n*paramNum+fillPos0+7] = -(1+lambada)*y0*hX0/(hW0*hW0); double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; LiPtr[2*n] = lambada*(orgx0)+x1 - ((1+lambada)*hX0/hW0); //! for : y = ... AiPtr[(2*n+1)*paramNum+fillPos0+3] = (1+lambada)*x0/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+4] = (1+lambada)*y0/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+5] = (1+lambada)*1/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+6] = -(1+lambada)*x0*hY0/(hW0*hW0); AiPtr[(2*n+1)*paramNum+fillPos0+7] = -(1+lambada)*y0*hY0/(hW0*hW0); double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; LiPtr[2*n+1] = lambada*(orgy0)+y1 - ((1+lambada)*hY0/hW0); double bias = (LiPtr[2*n]*LiPtr[2*n] + LiPtr[2*n+1]*LiPtr[2*n+1]); meanBias += sqrt(bias); n ++; rn ++; } //! get in normal equation matrix Mat_ Ait = Ai.t(); Mat_ barA = Ait*Ai, barL = Ait*Li; AtA += barA; AtL += barL; continue; } //! case 2 : with a remain optimized image for (int t = 0; t < curPts.size(); t += 3) { int x0 = curPts[t].x, y0 = curPts[t].y, x1 = neigPts[t].x, y1 = neigPts[t].y; double hX0 = X[fillPos0+0]*x0 + X[fillPos0+1]*y0 + X[fillPos0+2]; //! h1*x0 + h2*y0 + h3 double hY0 = X[fillPos0+3]*x0 + X[fillPos0+4]*y0 + X[fillPos0+5]; //! h4*x0 + h5*y0 + h6 double hW0 = X[fillPos0+6]*x0 + X[fillPos0+7]*y0 + 1; //! h7*x0 + h8*y0 + 1 double hX1 = X[fillPos1+0]*x1 + X[fillPos1+1]*y1 + X[fillPos1+2]; //! h1'*x1 + h2'*y1 + h3' double hY1 = X[fillPos1+3]*x1 + X[fillPos1+4]*y1 + X[fillPos1+5]; //! h4'*x1 + h5'*y1 + h6' double hW1 = X[fillPos1+6]*x1 + X[fillPos1+7]*y1 + 1; //! h7'*x1 + h8'*y1 + 1 //! for : x = ... //! cur-image AiPtr[2*n*paramNum+fillPos0] = (1+lambada)*x0/hW0; AiPtr[2*n*paramNum+fillPos0+1] = (1+lambada)*y0/hW0; AiPtr[2*n*paramNum+fillPos0+2] = (1+lambada)*1/hW0; AiPtr[2*n*paramNum+fillPos0+6] = -(1+lambada)*x0*hX0/(hW0*hW0); AiPtr[2*n*paramNum+fillPos0+7] = -(1+lambada)*y0*hX0/(hW0*hW0); //! neig-image AiPtr[2*n*paramNum+fillPos1] = (lambada-1)*x1/hW1; AiPtr[2*n*paramNum+fillPos1+1] = (lambada-1)*y1/hW1; AiPtr[2*n*paramNum+fillPos1+2] = (lambada-1)*1/hW1; AiPtr[2*n*paramNum+fillPos1+6] = -(lambada-1)*x1*hX1/(hW1*hW1); AiPtr[2*n*paramNum+fillPos1+7] = -(lambada-1)*y1*hX1/(hW1*hW1); double orgx0 = initX[6*curse0+0]*x0 + initX[6*curse0+1]*y0 + initX[6*curse0+2]; double orgx1 = initX[6*curse1+0]*x1 + initX[6*curse1+1]*y1 + initX[6*curse1+2]; LiPtr[2*n] = lambada*(orgx0+orgx1) - ((1+lambada)*hX0/hW0 + (lambada-1)*hX1/hW1); //! for : y = ... //! cur-image AiPtr[(2*n+1)*paramNum+fillPos0+3] = (1+lambada)*x0/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+4] = (1+lambada)*y0/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+5] = (1+lambada)*1/hW0; AiPtr[(2*n+1)*paramNum+fillPos0+6] = -(1+lambada)*x0*hY0/(hW0*hW0); AiPtr[(2*n+1)*paramNum+fillPos0+7] = -(1+lambada)*y0*hY0/(hW0*hW0); //! neig-image AiPtr[(2*n+1)*paramNum+fillPos1+3] = (lambada-1)*x1/hW1; AiPtr[(2*n+1)*paramNum+fillPos1+4] = (lambada-1)*y1/hW1; AiPtr[(2*n+1)*paramNum+fillPos1+5] = (lambada-1)*1/hW1; AiPtr[(2*n+1)*paramNum+fillPos1+6] = -(lambada-1)*x1*hY1/(hW1*hW1); AiPtr[(2*n+1)*paramNum+fillPos1+7] = -(lambada-1)*y1*hY1/(hW1*hW1); double orgy0 = initX[6*curse0+3]*x0 + initX[6*curse0+4]*y0 + initX[6*curse0+5]; double orgy1 = initX[6*curse1+3]*x1 + initX[6*curse1+4]*y1 + initX[6*curse1+5]; LiPtr[2*n+1] = lambada*(orgy0+orgy1) - ((1+lambada)*hY0/hW0 + (lambada-1)*hY1/hW1); double bias = (LiPtr[2*n]*LiPtr[2*n] + LiPtr[2*n+1]*LiPtr[2*n+1]); meanBias += sqrt(bias); n ++; rn ++; } //! get in normal equation matrix Mat_ Ait = Ai.t(); Mat_ barA = Ait*Ai, barL = Ait*Li; AtA += barA; AtL += barL; } } meanBias = meanBias/rn; cout<<"Iteration: "< dX = AtA.inv()*AtL; double *dXPtr = (double*)dX.data; // cout< tempMat = _alignModelList[i]; double *data = (double*)tempMat.data; for (int j = 0; j < 8; j ++) { X[cnt++] = data[j]; } } cnt = 0; for (int i = sIndex; i <= eIndex; i ++) { Mat_ tempMat = _initModelList[i]; double *data = (double*)tempMat.data; for (int j = 0; j < 6; j ++) { initX[cnt++] = data[j]; } } } void ImageAligner::buildIniSolution(double* X, int sIndex, int eIndex) { int cnt = 0; for (int i = sIndex; i <= eIndex; i ++) { Mat_ tempMat = _alignModelList[i]; double *data = (double*)tempMat.data; for (int j = 0; j < 8; j ++) { X[cnt++] = data[j]; } } } void ImageAligner::RefineAligningModels(int sIndex, int eIndex) { int m = 0, n = 0, max_its = 200; m = (eIndex-sIndex+1) * 8; //without optimizing the start one for (int i = sIndex; i <= eIndex; i ++) { int curNo = _visitOrder[i].imgNo; vector > pointSet = _matchNetList[curNo].PointSet; vector relatedNos = _matchNetList[curNo].relatedImgs; for (int j = 0; j < relatedNos.size(); j ++) { if (relatedNos[j] < i) { //! using only one third of corresponding for optimization n += pointSet[j].size()/3; } } } double *d = new double[n]; for (int i = 0; i < n; i ++) { d[i] = 0; } double *X = new double[m]; buildIniSolution(X, sIndex, eIndex); LMData *LMInput = new LMData; //! prepare input data for optimization LMInput->sIndex = sIndex; LMInput->eIndex = eIndex; LMInput->matchPtr = &_matchNetList; LMInput->modelPtr = &_alignModelList; LMInput->visitOrder = _visitOrder; double opts[LM_OPTS_SZ], info[LM_INFO_SZ]; opts[0]=1E-20; opts[1]=1E-30; opts[2]=1E-30; opts[3]=1E-30; opts[4]= 1e-9; int ret = dlevmar_dif(OptimizationFunction, X, d, m, n, max_its, opts, info, NULL, NULL, (void*)LMInput); for (int i = sIndex; i <= eIndex; i ++) //stock optimized homographic matrix { double *homoVec = X + 8*(i-sIndex); Mat_ homoMat(3,3,CV_64FC1); homoMat(0,0) = homoVec[0]; homoMat(0,1) = homoVec[1]; homoMat(0,2) = homoVec[2]; homoMat(1,0) = homoVec[3]; homoMat(1,1) = homoVec[4]; homoMat(1,2) = homoVec[5]; homoMat(2,0) = homoVec[6]; homoMat(2,1) = homoVec[7]; homoMat(2,2) = 1.0; _alignModelList[i] = homoMat; } delete []d; //free stack delete []X; delete LMInput; cout<<"Optimization done with iterations("< *matchNetPtr = dataPtr->matchPtr; int startIndex = dataPtr->sIndex, endIndex = dataPtr->eIndex; vector > *modelListPtr = dataPtr->modelPtr; vector visitOrder = dataPtr->visitOrder; int cnt = 0; double meanError = 0; for (int i = startIndex; i <= endIndex; i ++) //without the start image { int curNo = visitOrder[i].imgNo; Match_Net matchNet = (*matchNetPtr)[curNo]; vector relatedImgs = matchNet.relatedImgs; double *homoVec1, *homoVec2; double *iniHomoVec1, *iniHomoVec2; homoVec1 = X + 8*(i-startIndex); iniHomoVec1 = (double*)(*modelListPtr)[i].data; for (int j = 0; j < relatedImgs.size(); j ++) { int neigIndex = relatedImgs[j]; if (neigIndex > i) { continue; } vector ptSet1, ptSet2; ptSet1 = matchNet.PointSet[j]; //! points on cur_image int neigNo = visitOrder[neigIndex].imgNo; Match_Net neigMatchNet = (*matchNetPtr)[neigNo]; for (int k = 0; k < neigMatchNet.relatedImgs.size(); k ++) { if (neigMatchNet.relatedImgs[k] == i) { ptSet2 = neigMatchNet.PointSet[k]; break; } } bool fixedNeigh = false; if (neigIndex < startIndex) { double *data = (double*)(*modelListPtr)[neigIndex].data; homoVec2 = data; fixedNeigh = true; } else { homoVec2 = X + 8*(neigIndex-startIndex); iniHomoVec2 = (double*)(*modelListPtr)[neigIndex].data; } //! using only one third of corresponding for optimization for (int t = 0; t < ptSet1.size(); t += 3) { double x1 = ptSet1[t].x, y1 = ptSet1[t].y; double x2 = ptSet2[t].x, y2 = ptSet2[t].y; double mosaic_x1 = (homoVec1[0]*x1 + homoVec1[1]*y1 + homoVec1[2])/(homoVec1[6]*x1 + homoVec1[7]*y1 + 1.0); double mosaic_y1 = (homoVec1[3]*x1 + homoVec1[4]*y1 + homoVec1[5])/(homoVec1[6]*x1 + homoVec1[7]*y1 + 1.0); double mosaic_x2 = (homoVec2[0]*x2 + homoVec2[1]*y2 + homoVec2[2])/(homoVec2[6]*x2 + homoVec2[7]*y2 + 1.0); double mosaic_y2 = (homoVec2[3]*x2 + homoVec2[4]*y2 + homoVec2[5])/(homoVec2[6]*x2 + homoVec2[7]*y2 + 1.0); double bias = sqrt((mosaic_x1-mosaic_x2)*(mosaic_x1-mosaic_x2)+(mosaic_y1-mosaic_y2)*(mosaic_y1-mosaic_y2)); //! perspective penalty items double penalty = 0; if (!fixedNeigh) { double iniMosaic_x1 = (iniHomoVec1[0]*x1 + iniHomoVec1[1]*y1 + iniHomoVec1[2])/(iniHomoVec1[6]*x1 + iniHomoVec1[7]*y1 + 1.0); double iniMosaic_y1 = (iniHomoVec1[3]*x1 + iniHomoVec1[4]*y1 + iniHomoVec1[5])/(iniHomoVec1[6]*x1 + iniHomoVec1[7]*y1 + 1.0); double iniMosaic_x2 = (iniHomoVec2[0]*x2 + iniHomoVec2[1]*y2 + iniHomoVec2[2])/(iniHomoVec2[6]*x2 + iniHomoVec2[7]*y2 + 1.0); double iniMosaic_y2 = (iniHomoVec2[3]*x2 + iniHomoVec2[4]*y2 + iniHomoVec2[5])/(iniHomoVec2[6]*x2 + iniHomoVec2[7]*y2 + 1.0); double penalty1 = sqrt((mosaic_x1-iniMosaic_x1)*(mosaic_x1-iniMosaic_x1)+(mosaic_y1-iniMosaic_y1)*(mosaic_y1-iniMosaic_y1)); double penalty2 = sqrt((mosaic_x2-iniMosaic_x2)*(mosaic_x2-iniMosaic_x2)+(mosaic_y2-iniMosaic_y2)*(mosaic_y2-iniMosaic_y2)); penalty = (penalty1 + penalty2)/2; } else { double iniMosaic_x1 = (iniHomoVec1[0]*x1 + iniHomoVec1[1]*y1 + iniHomoVec1[2])/(iniHomoVec1[6]*x1 + iniHomoVec1[7]*y1 + 1.0); double iniMosaic_y1 = (iniHomoVec1[3]*x1 + iniHomoVec1[4]*y1 + iniHomoVec1[5])/(iniHomoVec1[6]*x1 + iniHomoVec1[7]*y1 + 1.0); penalty = sqrt((mosaic_x1-iniMosaic_x1)*(mosaic_x1-iniMosaic_x1)+(mosaic_y1-iniMosaic_y1)*(mosaic_y1-iniMosaic_y1)); } d[cnt++] = bias + PENALTY_COEFF*penalty; meanError += bias; } } } meanError /= cnt; cout<<"current mean-warping-bias is: "< &nodePts) { vector marginPtList; int i, j; for (i = 0; i < _imgNum; i ++) { Mat_ homoMat = _alignModelList[i]; int curImgNo = _visitOrder[i].imgNo; Size imgSize = _imgSizeList[curImgNo]; int height = imgSize.height, width = imgSize.width; Point2d srcPt00(0,0), srcPt01(width,0), srcPt10(0,height), srcPt11(width,height); Point2d dstPt00, dstPt01, dstPt10, dstPt11; Utils::pointTransform(homoMat, srcPt00, dstPt00); Utils::pointTransform(homoMat, srcPt01, dstPt01); Utils::pointTransform(homoMat, srcPt10, dstPt10); Utils::pointTransform(homoMat, srcPt11, dstPt11); marginPtList.push_back(dstPt00); marginPtList.push_back(dstPt01); marginPtList.push_back(dstPt10); marginPtList.push_back(dstPt11); if (i != 0) { nodePts.push_back(dstPt10); nodePts.push_back(dstPt11); } } int minX = 999, minY = 999, maxX = 0, maxY = 0; for (i = 0; i < marginPtList.size(); i ++) { Point2d tmpPt = marginPtList[i]; int x = int(fabs(tmpPt.x)+1)*(tmpPt.x < 0 ? -1 : 1); int y = int(fabs(tmpPt.y)+1)*(tmpPt.y < 0 ? -1 : 1); if (x > maxX) maxX = x; if (x < minX) minX = x; if (y > maxY) maxY = y; if (y < minY) minY = y; } for (i = 0; i < nodePts.size(); i ++) { nodePts[i].x -= minX; nodePts[i].y -= minY; } Rect mosaicRect; mosaicRect.x = minX; mosaicRect.y = minY; mosaicRect.width = maxX-minX+1; mosaicRect.height = maxY-minY+1; return mosaicRect; } void ImageAligner::saveMosaicImage() { cout<<"#Warping sequential images ..."< nodePts; Rect mosaicRect = setImageSize(nodePts); int newRow = mosaicRect.height, newCol = mosaicRect.width; int i, j; Rect newImgRect; Mat stitchImage(newRow, newCol, CV_8UC3, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX)); uchar *mosaicData = (uchar*)stitchImage.data; for (i = 0; i < _imgNum; i ++) { int curImgNo = _visitOrder[i].imgNo; cout<<"Warping Image: "< homoMat = _alignModelList[i]; Size imgSize = _imgSizeList[curImgNo]; int height = imgSize.height, width = imgSize.width; Point2d srcPt00(0,0), srcPt01(width,0), srcPt10(0,height), srcPt11(width,height); Point2d dstPt00, dstPt01, dstPt10, dstPt11; Utils::pointTransform(homoMat, srcPt00, dstPt00); Utils::pointTransform(homoMat, srcPt01, dstPt01); Utils::pointTransform(homoMat, srcPt10, dstPt10); Utils::pointTransform(homoMat, srcPt11, dstPt11); double fminX, fminY, fmaxX, fmaxY; fminX = min(min(dstPt00.x, dstPt01.x), min(dstPt10.x, dstPt11.x)); fmaxX = max(max(dstPt00.x, dstPt01.x), max(dstPt10.x, dstPt11.x)); fminY = min(min(dstPt00.y, dstPt01.y), min(dstPt10.y, dstPt11.y)); fmaxY = max(max(dstPt00.y, dstPt01.y), max(dstPt10.y, dstPt11.y)); int minX, minY, maxX, maxY; minX = int(fabs(fminX)+1)*(fminX < 0 ? -1 : 1); maxX = int(fabs(fmaxX)+1)*(fmaxX < 0 ? -1 : 1); minY = int(fabs(fminY)+1)*(fminY < 0 ? -1 : 1); maxY = int(fabs(fmaxY)+1)*(fmaxY < 0 ? -1 : 1); int startX = minX-mosaicRect.x; int endX = startX+maxX-minX; int startY = minY-mosaicRect.y; int endY = startY+maxY-minY; int r, c; Mat warpedImage; if (needMask && needAlpha) { warpedImage = Mat(newRow, newCol, CV_8UC4, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX,0)); } else if (needMask && !needAlpha) { warpedImage = Mat(newRow, newCol, CV_8UC3, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX)); } uchar *curWarpData = (uchar*)warpedImage.data; string filePath = _filePathList[curImgNo]; Mat image = imread(filePath); uchar *curImgData = (uchar*)image.data; Mat_ invHomoMat = homoMat.inv(); for (r = startY; r < endY; r ++) { for (c = startX; c < endX; c ++) { int grayValueR, grayValueG, grayValueB; Point2d dstPt(c+mosaicRect.x,r+mosaicRect.y), srcPt(0,0); Utils::pointTransform(invHomoMat, dstPt, srcPt); int u = int(srcPt.x), v = int(srcPt.y); if (0 < u && width-1 > u && 0 < v && height-1 > v) { int grayValueR1 = 0, grayValueR2 = 0; int grayValueG1 = 0, grayValueG2 = 0; int grayValueB1 = 0, grayValueB2 = 0; //bilinear interpolation grayValueR1 = curImgData[3*(v*width+u)+0]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+0]*(srcPt.x-u); grayValueG1 = curImgData[3*(v*width+u)+1]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+1]*(srcPt.x-u); grayValueB1 = curImgData[3*(v*width+u)+2]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+2]*(srcPt.x-u); grayValueR2 = curImgData[3*((v+1)*width+u)+0]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+0]*(srcPt.x-u); grayValueG2 = curImgData[3*((v+1)*width+u)+1]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+1]*(srcPt.x-u); grayValueB2 = curImgData[3*((v+1)*width+u)+2]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+2]*(srcPt.x-u); grayValueR = grayValueR1*(1-(srcPt.y-v)) + grayValueR2*(srcPt.y-v); grayValueG = grayValueG1*(1-(srcPt.y-v)) + grayValueG2*(srcPt.y-v); grayValueB = grayValueB1*(1-(srcPt.y-v)) + grayValueB2*(srcPt.y-v); if (needMask) { if (!needAlpha) { curWarpData[3*(r*newCol+c)+0] = grayValueR; curWarpData[3*(r*newCol+c)+1] = grayValueG; curWarpData[3*(r*newCol+c)+2] = grayValueB; } else { warpedImage.at(r,c)[3] = 255; //! for alpha channel warpedImage.at(r,c)[0] = grayValueR; //! B warpedImage.at(r,c)[1] = grayValueG; //! G warpedImage.at(r,c)[2] = grayValueB; //! R } } //! set for the mosaic image mosaicData[3*(r*newCol+c)+0] = grayValueR; mosaicData[3*(r*newCol+c)+1] = grayValueG; mosaicData[3*(r*newCol+c)+2] = grayValueB; } } } if (!needMask) { continue; } char name[512]; sprintf(name,"/Masks/warp%03d.png", curImgNo); string savePath = Utils::baseDir + string(name); imwrite(savePath, warpedImage); } string filePath = Utils::baseDir + "/mosaic.png"; imwrite(filePath, stitchImage); cout<<"-Completed!"< nodePts; Rect mosaicRect = setImageSize(nodePts); int newRow = mosaicRect.height, newCol = mosaicRect.width; int i, j; Rect newImgRect; Mat stitchImage(newRow, newCol, CV_8UC3, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX)); uchar *mosaicData = (uchar*)stitchImage.data; Rect refRect; for (i = 0; i < _imgNum; i ++) { int curImgNo = i; int curIndex = findVisitIndex(curImgNo); cout<<"Warping Image: "< homoMat = _alignModelList[curIndex]; Size imgSize = _imgSizeList[curImgNo]; int height = imgSize.height, width = imgSize.width; Point2d srcPt00(0,0), srcPt01(width,0), srcPt10(0,height), srcPt11(width,height); Point2d dstPt00, dstPt01, dstPt10, dstPt11; Utils::pointTransform(homoMat, srcPt00, dstPt00); Utils::pointTransform(homoMat, srcPt01, dstPt01); Utils::pointTransform(homoMat, srcPt10, dstPt10); Utils::pointTransform(homoMat, srcPt11, dstPt11); double fminX, fminY, fmaxX, fmaxY; fminX = min(min(dstPt00.x, dstPt01.x), min(dstPt10.x, dstPt11.x)); fmaxX = max(max(dstPt00.x, dstPt01.x), max(dstPt10.x, dstPt11.x)); fminY = min(min(dstPt00.y, dstPt01.y), min(dstPt10.y, dstPt11.y)); fmaxY = max(max(dstPt00.y, dstPt01.y), max(dstPt10.y, dstPt11.y)); int minX, minY, maxX, maxY; minX = int(fabs(fminX)+1)*(fminX < 0 ? -1 : 1); maxX = int(fabs(fmaxX)+1)*(fmaxX < 0 ? -1 : 1); minY = int(fabs(fminY)+1)*(fminY < 0 ? -1 : 1); maxY = int(fabs(fmaxY)+1)*(fmaxY < 0 ? -1 : 1); int startX = minX-mosaicRect.x; int endX = startX+maxX-minX; int startY = minY-mosaicRect.y; int endY = startY+maxY-minY; if (i == _refImgNo) { refRect.x = startX; refRect.y = startY; refRect.width = endX-startX+1; refRect.height = endY-startY+1; } int r, c; Mat warpedImage; if (needMask && needAlpha) { warpedImage = Mat(newRow, newCol, CV_8UC4, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX,0)); } else if (needMask && !needAlpha) { warpedImage = Mat(newRow, newCol, CV_8UC3, Scalar(BKGRNDPIX,BKGRNDPIX,BKGRNDPIX)); } uchar *curWarpData = (uchar*)warpedImage.data; string filePath = _filePathList[curImgNo]; Mat image = imread(filePath); uchar *curImgData = (uchar*)image.data; Mat_ invHomoMat = homoMat.inv(); for (r = startY; r < endY; r ++) { for (c = startX; c < endX; c ++) { int grayValueR, grayValueG, grayValueB; Point2d dstPt(c+mosaicRect.x,r+mosaicRect.y), srcPt(0,0); Utils::pointTransform(invHomoMat, dstPt, srcPt); int u = int(srcPt.x), v = int(srcPt.y); if (0+1 < u && width-2 > u && 0+1 < v && height-2 > v) { int grayValueR1 = 0, grayValueR2 = 0; int grayValueG1 = 0, grayValueG2 = 0; int grayValueB1 = 0, grayValueB2 = 0; //bilinear interpolation grayValueR1 = curImgData[3*(v*width+u)+0]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+0]*(srcPt.x-u); grayValueG1 = curImgData[3*(v*width+u)+1]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+1]*(srcPt.x-u); grayValueB1 = curImgData[3*(v*width+u)+2]*(1-(srcPt.x-u)) + curImgData[3*(v*width+u+1)+2]*(srcPt.x-u); grayValueR2 = curImgData[3*((v+1)*width+u)+0]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+0]*(srcPt.x-u); grayValueG2 = curImgData[3*((v+1)*width+u)+1]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+1]*(srcPt.x-u); grayValueB2 = curImgData[3*((v+1)*width+u)+2]*(1-(srcPt.x-u)) + curImgData[3*((v+1)*width+(u+1))+2]*(srcPt.x-u); grayValueR = grayValueR1*(1-(srcPt.y-v)) + grayValueR2*(srcPt.y-v); grayValueG = grayValueG1*(1-(srcPt.y-v)) + grayValueG2*(srcPt.y-v); grayValueB = grayValueB1*(1-(srcPt.y-v)) + grayValueB2*(srcPt.y-v); if (needMask) { if (!needAlpha) { curWarpData[3*(r*newCol+c)+0] = grayValueR; curWarpData[3*(r*newCol+c)+1] = grayValueG; curWarpData[3*(r*newCol+c)+2] = grayValueB; } else { warpedImage.at(r,c)[3] = 255; //! for alpha channel warpedImage.at(r,c)[0] = grayValueR; //! B warpedImage.at(r,c)[1] = grayValueG; //! G warpedImage.at(r,c)[2] = grayValueB; //! R } } //! set for the mosaic image mosaicData[3*(r*newCol+c)+0] = grayValueR; mosaicData[3*(r*newCol+c)+1] = grayValueG; mosaicData[3*(r*newCol+c)+2] = grayValueB; } } } if (!needMask) { continue; } char name[512]; sprintf(name,"/Masks/warp%03d.png", curImgNo); string savePath = Utils::baseDir + string(name); imwrite(savePath, warpedImage); } if (0) { rectangle(stitchImage, Point2d(refRect.x,refRect.y), Point2d(refRect.x+refRect.width,refRect.y+refRect.height), Scalar(0,0,255), 5); } string filePath = Utils::baseDir + "/mosaic.png"; imwrite(filePath, stitchImage); cout<<"-Completed!"< pointSet1, vector pointSet2, Mat_ cvtMat, vector weightList) { unsigned i; int ptNum = pointSet1.size(); if (weightList.size() == 0) { for (i = 0; i < ptNum; i ++) { weightList.push_back(1.0); } } double meanDist = 0, allWeight = 0; // vector errorList; for (i = 0; i < ptNum; i ++) //mean value { Point2d warpedPt; Utils::pointTransform(cvtMat, pointSet2[i], warpedPt); double dist = 0; dist = sqrt((warpedPt.x-pointSet1[i].x)*(warpedPt.x-pointSet1[i].x) + (warpedPt.y-pointSet1[i].y)*(warpedPt.y-pointSet1[i].y)); meanDist += dist*weightList[i]; allWeight += weightList[i]; } meanDist /= allWeight; return meanDist; } void ImageAligner::recheckTopology(int sIndex, int eIndex) { cout<<"-Recheck potential topology ..."< affineMat = _alignModelList[i]; //! calculating projecting centroid Quadra bar; bar.imgSize = _imgSizeList[curNo]; Point2d centroid(bar.imgSize.width/2.0, bar.imgSize.height/2.0); bar.centroid = Utils::pointTransform(affineMat, centroid); _projCoordSet.push_back(bar); vector relatedNos = _matchNetList[curNo].relatedImgs; //! check with previously aligned images, except for its known neighbors for (int j = 0; j < sIndex; j ++) { bool isOldFriend = false; for (int k = 0; k < relatedNos.size(); k ++) { if (relatedNos[k] == j) { isOldFriend = true; break; } } if (isOldFriend) { continue; } int testNo = _visitOrder[j].imgNo; Quadra testObj = _projCoordSet[j]; double threshold = 0.5*(max(bar.imgSize.width,bar.imgSize.height) + max(testObj.imgSize.width, testObj.imgSize.height)); double dist = Utils::calPointDist(bar.centroid, testObj.centroid); if (dist > threshold*0.6) { continue; } vector PtSet1, PtSet2; bool yeah = _matcher->featureMatcher(curNo,testNo,PtSet1,PtSet2); if (yeah) { _similarityMat(testNo,curNo) = PtSet1.size(); _similarityMat(curNo,testNo) = PtSet1.size(); _matchNetList[curNo].relatedImgs.push_back(j); _matchNetList[curNo].PointSet.push_back(PtSet1); _matchNetList[testNo].relatedImgs.push_back(i); _matchNetList[testNo].PointSet.push_back(PtSet2); addedPairs ++; } } } cout<<"-Done! added "< coreLocations; int i, j, k; //! in the order of '_visitOrser' for (i = 0; i < _imgNum; i ++) { int imgNo = _visitOrder[i].imgNo; double x0 = _imgSizeList[imgNo].width/2.0; double y0 = _imgSizeList[imgNo].height/2.0; Point2d centroid(x0, y0); Point2d warpPt; Utils::pointTransform(_alignModelList[i], centroid, warpPt); coreLocations.push_back(warpPt); } int minX = 999, minY = 999, maxX = 0, maxY = 0; for (i = 0; i < coreLocations.size(); i ++) { Point2d tmpPt = coreLocations[i]; int x = int(fabs(tmpPt.x)+1)*(tmpPt.x < 0 ? -1 : 1); int y = int(fabs(tmpPt.y)+1)*(tmpPt.y < 0 ? -1 : 1); if (x > maxX) maxX = x; if (x < minX) minX = x; if (y > maxY) maxY = y; if (y < minY) minY = y; } double width = maxX - minX; double height = maxY - minY; int imageRange = 2000; //maximum side_length int edgeRange = 60; double cvtScale = imageRange/min(height,width); int imageRow = height * cvtScale + edgeRange*2; // add an edge space of 20 pixel int imageCol = width * cvtScale + edgeRange*2; Mat displayPlane(imageRow, imageCol, CV_8UC3, Scalar(255,255,255)); CvFont font; double hScale = 1; double vScale = 1; cvInitFont(&font,CV_FONT_HERSHEY_PLAIN, hScale,vScale,0,1); //¶¨Òå±ê¼Ç×ÖÌå vector dotPtList; //! in the order of '_visitOrser' for (i = 0; i < coreLocations.size(); i ++) { int c = int((coreLocations[i].x-minX) * cvtScale + 1) + edgeRange; int r = int((coreLocations[i].y-minY) * cvtScale + 1) + edgeRange; dotPtList.push_back(Point2i(c,r)); circle(displayPlane, Point2i(c,r), 24, Scalar(255,0,0), -1); // circle(displayPlane, Point2i(c,r), 3, Scalar(255,255,0), -1); int imgNo = _visitOrder[i].imgNo; char text[100]; sprintf(text,"%d", imgNo); Point2i dotPt(c+3, r+3); // cv::putText(displayPlane, text, dotPt, 2, 1, Scalar(0,0,0)); } for (i = 0; i < _imgNum-1; i ++) //draw all related lines { for (j = i+1; j < _imgNum; j ++) { int imgNo1 = _visitOrder[i].imgNo; int imgNo2 = _visitOrder[j].imgNo; int PtNum = _similarityMat(imgNo1,imgNo2); if (PtNum != 0) { Point2i startPt = dotPtList[i]; Point2i endPt = dotPtList[j]; if (PtNum < 100 || 1) { line(displayPlane, startPt, endPt, Scalar(128,128,128), 2); } else { line(displayPlane, startPt, endPt, Scalar(0,255,0), 2); } } } } for (i = 1; i < _imgNum; i ++) //! draw the related lines in MST { int refNo = _visitOrder[i].refNo; int refIndex = findVisitIndex(refNo); Point2i startPt = dotPtList[i]; Point2i endPt = dotPtList[refIndex]; line(displayPlane, startPt, endPt, Scalar(0,0,255), 3); } string savePath = Utils::baseDir + "/finalTopology.png"; imwrite(savePath, displayPlane); cout<<"#the topology graph of images is saved!"< coreLocations; int i, j, k; //! in the order of '_visitOrser' for (i = 0; i < _imgNum; i ++) { int imgNo = _visitOrder[i].imgNo; double x0 = _imgSizeList[imgNo].width/2.0; double y0 = _imgSizeList[imgNo].height/2.0; Point2d centroid(x0, y0); Point2d warpPt; Utils::pointTransform(_alignModelList[i], centroid, warpPt); coreLocations.push_back(warpPt); } int minX = 999, minY = 999, maxX = 0, maxY = 0; for (i = 0; i < coreLocations.size(); i ++) { Point2d tmpPt = coreLocations[i]; int x = int(fabs(tmpPt.x)+1)*(tmpPt.x < 0 ? -1 : 1); int y = int(fabs(tmpPt.y)+1)*(tmpPt.y < 0 ? -1 : 1); if (x > maxX) maxX = x; if (x < minX) minX = x; if (y > maxY) maxY = y; if (y < minY) minY = y; } double width = maxX - minX; double height = maxY - minY; int imageRange = 1000; //maximum side_length int edgeRange = 50; double cvtScale = imageRange/min(height,width); int imageRow = height * cvtScale + edgeRange*2; // add an edge space of 20 pixel int imageCol = width * cvtScale + edgeRange*2; Mat displayPlane(imageRow, imageCol, CV_8UC3, Scalar(255,255,255)); CvFont font; double hScale = 1; double vScale = 1; cvInitFont(&font,CV_FONT_HERSHEY_PLAIN, hScale,vScale,0,1); //¶¨Òå±ê¼Ç×ÖÌå vector dotPtList; //! label aligning group for (i = 0; i < _groupCusorList.size(); i ++) { int sIndex = 0, eIndex = 0; if (i != 0) { sIndex = _groupCusorList[i-1]+1; eIndex = _groupCusorList[i]; } int r = rand()%255; int g = rand()%255; int b = rand()%255; for (j = sIndex; j <= eIndex; j ++) { int c = int((coreLocations[j].x-minX) * cvtScale + 1) + edgeRange; int r1 = int((coreLocations[j].y-minY) * cvtScale + 1) + edgeRange; dotPtList.push_back(Point2i(c,r1)); circle(displayPlane, Point2i(c,r1), 25, Scalar(r,g,b), -1); int imgNo = _visitOrder[j].imgNo; char text[100]; sprintf(text,"%d", imgNo); Point2i dotPt(c+3, r1+3); cv::putText(displayPlane, text, dotPt, 2, 1, Scalar(0,0,0)); } } for (i = 0; i < _imgNum-1; i ++) //draw all related lines { for (j = i+1; j < _imgNum; j ++) { int imgNo1 = _visitOrder[i].imgNo; int imgNo2 = _visitOrder[j].imgNo; int PtNum = _similarityMat(imgNo1,imgNo2); if (PtNum != 0) { Point2i startPt = dotPtList[i]; Point2i endPt = dotPtList[j]; if (PtNum < 100) { line(displayPlane, startPt, endPt, Scalar(128,128,128), 1); } else { line(displayPlane, startPt, endPt, Scalar(0,255,0), 1); } } } } for (i = 1; i < _imgNum; i ++) //! draw the related lines in MST { int refNo = _visitOrder[i].refNo; int refIndex = findVisitIndex(refNo); Point2i startPt = dotPtList[i]; Point2i endPt = dotPtList[refIndex]; line(displayPlane, startPt, endPt, Scalar(0,0,255), 2); } string savePath = Utils::baseDir + "/groupLabel.jpg"; imwrite(savePath, displayPlane); } void ImageAligner::drawSimilarMatrix() { int margin = 50; int imageRow = 800, imageCol = 800; int unitSize = 800/_imgNum; CvFont font; double hScale = 1; double vScale = 1; cvInitFont(&font,CV_FONT_HERSHEY_PLAIN, hScale,vScale,0,1); //define the label font Mat displayPlane(imageRow+2*margin, imageCol+2*margin, CV_8UC3, Scalar(0,0,0)); for (int i = 0; i < _imgNum; i ++) { Point2i startPt_h(margin+i*unitSize, margin); //draw vertical lines Point2i endPt_h(margin+i*unitSize, margin+unitSize*_imgNum); line(displayPlane, startPt_h, endPt_h, Scalar(128,128,128), 1); char text_h[100]; sprintf(text_h,"%d", i+1); Point2i dotPt1(startPt_h.x, startPt_h.y-10); //draw horizontal labels(the dot is at left-bottom of the label) cv::putText(displayPlane, text_h, dotPt1, 1, 1, Scalar(255,255,255)); Point2i startPt_v(margin, margin+i*unitSize); //draw horizontal lines Point2i endPt_v(margin+unitSize*_imgNum, margin+i*unitSize); line(displayPlane, startPt_v, endPt_v, Scalar(128,128,128), 1); char text_v[100]; sprintf(text_v,"%d", i+1); Point2i dotPt2(startPt_v.x-25, startPt_v.y+10); //draw vertical labels cv::putText(displayPlane, text_v, dotPt2, 1, 1, Scalar(255,255,255)); } int* numDataPtr = (int*)_similarityMat.data; int max_match_num = 0, min_match_num = 9999; for (int i = 0; i < _imgNum-1; i ++) { for (int j = i+1; j < _imgNum; j ++) { int num = numDataPtr[i*_imgNum+j]; if (num > max_match_num) { max_match_num = num; } if (num < min_match_num) { min_match_num = num; } } } double grayScale = (255-64+1)*1.0 / (max_match_num-min_match_num+1); for (int i = 0; i < _imgNum-1; i ++) { for (int j = i+1; j < _imgNum; j ++) { Point2i leftTop, rigtBtm; leftTop.x = margin + i*unitSize; leftTop.y = margin + j*unitSize; rigtBtm.x = leftTop.x + unitSize; rigtBtm.y = leftTop.y + unitSize; int PtNum = _similarityMat(i,j); if (PtNum == 0) { continue; } int grayValue = 64 + int((PtNum-min_match_num) * grayScale); int r, c; for (c = leftTop.x; c < rigtBtm.x; c ++) { for (r = leftTop.y; r < rigtBtm.y; r ++) { //! down triangle displayPlane.at(r,c)[0] = grayValue; displayPlane.at(r,c)[1] = grayValue; displayPlane.at(r,c)[2] = grayValue; //! up triangle displayPlane.at(c,r)[0] = grayValue; displayPlane.at(c,r)[1] = grayValue; displayPlane.at(c,r)[2] = grayValue; } } } } string savePath = Utils::baseDir + "/similarTable.jpg"; imwrite(savePath, displayPlane); cout<<"the similarity table of images is saved!"< deviations; int cnt = 0; for (int i = 1; i < _imgNum; i ++) { int curNo = _visitOrder[i].imgNo; Match_Net matchNet = _matchNetList[curNo]; vector relatedImgs = _matchNetList[curNo].relatedImgs; Mat_ homoMat1 = _alignModelList[i]; Mat_ homoMat2; double curBias = 0; int cnt1 = 0; for (int j = 0; j < relatedImgs.size(); j ++) { int neigIndex = relatedImgs[j]; if (neigIndex > i) { continue; } vector ptSet1, ptSet2; ptSet1 = matchNet.PointSet[j]; //! points on cur_image int neigNo = _visitOrder[neigIndex].imgNo; Match_Net neigMatchNet = _matchNetList[neigNo]; for (int k = 0; k < neigMatchNet.relatedImgs.size(); k ++) { if (neigMatchNet.relatedImgs[k] == i) { ptSet2 = neigMatchNet.PointSet[k]; break; } } homoMat2 = _alignModelList[neigIndex]; //! using only one third of corresponding for optimization for (int t = 0; t < ptSet1.size(); t += 3) { Point2d mosaicPt1 = Utils::pointTransform(homoMat1, ptSet1[t]); Point2d mosaicPt2 = Utils::pointTransform(homoMat2, ptSet2[t]); double bias = sqrt((mosaicPt1.x-mosaicPt2.x)*(mosaicPt1.x-mosaicPt2.x)+(mosaicPt1.y-mosaicPt2.y)*(mosaicPt1.y-mosaicPt2.y)); deviations.push_back(bias); meanBias += bias; cnt ++; } } } meanBias /= cnt; //! statistic the distribute of error string savePath = Utils::baseDir + "/precise.txt"; ofstream fout(savePath, ios::out); if (!fout.is_open()) { cout<<"Save path not exists!"< homoMat = Mat::eye(3,3,CV_64FC1); _alignModelList.push_back(homoMat); } double u0 = 500.971, v0 = 323.486; Mat_ trans0 = (Mat_(3,3) << 1, 0, -u0, 0, -1, 641-v0, 0, 0, 1); Mat_ trans1 = (Mat_(3,3) << 1, 0, u0, 0, -1, -641+v0, 0, 0, 1); double kappa = 180; Mat_ Rz = (Mat_(3,3) << cos(kappa), -sin(kappa), 0, sin(kappa), cos(kappa), 0, 0, 0, 1); Mat_ t1 = (Mat_(3,3) << 1, 0, -u0, 0, 1, -v0, 0, 0, 1); Mat_ t2 = (Mat_(3,3) << 1, 0, u0, 0, 1, v0, 0, 0, 1); Mat_ bar = t2*Rz*t1; for (int i = 0; i < _imgNum; i ++) { Mat_ homoMat = Mat::eye(3,3,CV_64FC1); double* dataPtr = (double*)homoMat.data; for (int j = 0; j < 8; j ++) { double param = 0; fin >> param; dataPtr[j] = param; } int curImgNo = i; int curIndex = findVisitIndex(curImgNo); if ((i/31)%2 == 0) //! rotate 180 { _alignModelList[curIndex] = trans1*homoMat*trans0; } else { _alignModelList[curIndex] = trans1*homoMat*trans0; } } fin.close(); cout<<"-Completed!"<