diff --git a/samples/stitch.png~ b/samples/stitch.png~ new file mode 100644 index 0000000..b6a91ba Binary files /dev/null and b/samples/stitch.png~ differ diff --git a/samples/stitch.png~~ b/samples/stitch.png~~ new file mode 100644 index 0000000..b27d560 Binary files /dev/null and b/samples/stitch.png~~ differ diff --git a/src/cam.py b/src/cam.py deleted file mode 100644 index 53dbde1..0000000 --- a/src/cam.py +++ /dev/null @@ -1,60 +0,0 @@ -import cv2 -import numpy as np -import os - - -def variance_of_laplacian(image): - return cv2.Laplacian(image, cv2.CV_64F).var() - - - -os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"]="rtsp_transport;tcp" - -gstreamerstr = "tcpclientsrc host=192.168.0.144 port=5000 ! jpegdec ! videoconvert ! appsink" - - - -#if not capture.isOpened() : print("CANNOT OPEN STREAM") -capture = cv2.VideoCapture("vid.mp4") -keypressNo = 1 -while(True): - #capture = cv2.VideoCapture(gstreamerstr,cv2.CAP_GSTREAMER) - - ret, frame = capture.read() - if not ret: - print('fail') - break - - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - variance = variance_of_laplacian(frame) - - cv2.putText(frame, "{}: {:.2f}".format("Variance:", variance), (10, 30), - cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3) - cv2.imshow('frame',frame) - #cv2.waitKey(0) - - if cv2.waitKey(70) == ord('v'): - frames=[] - maxVarIdx = 0 - maxVar = 0 - for i in range(5): - ret, frame = capture.read() - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - frames.append(frame) - var = variance_of_laplacian(frame) - if var > maxVar: - maxVar = var - maxVarIdx = i - cv2.waitKey(20) - #test to see if the image with the highest variance gets picked - #cv2.putText(frame, "{}: {:.2f}".format("Variance:", var), (10, 30), - #cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3) - #writeString="imgtest"+str(keypressNo)+str(i)+".jpg" - #cv2.imwrite(writeString, frames[i]) - writeString="img"+str(keypressNo)+".jpg" - cv2.imwrite(writeString, frames[maxVarIdx]) - keypressNo=keypressNo+1 - - -capture.release() -cv2.destroyAllWindows() diff --git a/src/imgvar.py b/src/imgvar.py deleted file mode 100644 index c7976da..0000000 --- a/src/imgvar.py +++ /dev/null @@ -1,38 +0,0 @@ -import cv2 -import numpy as np -import os -from imutils import paths -import argparse - - -def variance_of_laplacian(image): - return cv2.Laplacian(image, cv2.CV_64F).var() - - -def minVarInFolder(path): - minVar = 90000 - minPath="" - files = os.listdir(path) - for p in files: - if ".png" in p and ".mask" not in p: - print(path+p) - img = cv2.imread(path+p) - cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) - var = variance_of_laplacian(img) - if var < minVar: - minPath = path+p - minVar = var - return minPath,minVar - -ap = argparse.ArgumentParser() -ap.add_argument("-i", "--images", required=True, - help="path to image") -args = vars(ap.parse_args()) - -path = args["images"] - -#img = cv2.imread(path) -#cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) -#var = variance_of_laplacian(img) - -print(minVarInFolder(path)) \ No newline at end of file diff --git a/src/pointbase.cpp b/src/pointbase.cpp index acbb9e8..5bc555b 100644 --- a/src/pointbase.cpp +++ b/src/pointbase.cpp @@ -6,6 +6,8 @@ #include #include #include "opencv2/calib3d/calib3d.hpp" +#include +#include #include #include #include @@ -67,6 +69,7 @@ class PointBase { //cout << "x: " << coords["depthPos"]["x"].asDouble() << std::endl; //cout << "y: " << coords["depthPos"]["y"].asDouble() << std::endl; Point2d newPoint = Point2d(coords["depthPos"]["x"].asDouble() , coords["depthPos"]["y"].asDouble()); + //if (newPoint.x >360.0) continue; newPoint.x = fmod(newPoint.x,360.0) ; pathMap[newPoint] = filePath; @@ -208,7 +211,7 @@ class PointBase { }*/ - if(abs(yDifference)<0.9*imgHeightDeg && abs(xDifference)<0.8*imgWidthDeg) + if(abs(yDifference)<0.9*imgHeightDeg && abs(xDifference)<0.45*imgWidthDeg) { resultVector.push_back(points[i]); toDoVector.push_back(points[i]); @@ -221,11 +224,276 @@ class PointBase { } + //rotation function + //https://stackoverflow.com/questions/22041699/rotate-an-image-without-cropping-in-opencv-in-c + Mat rotate(Mat src, double angle) + { + cv::Point2f center((src.cols-1)/2.0, (src.rows-1)/2.0); + cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0); + // determine bounding rectangle, center not relevant + cv::Rect2f bbox = cv::RotatedRect(cv::Point2f(), src.size(), angle).boundingRect2f(); + // adjust transformation matrix + rot.at(0,2) += bbox.width/2.0 - src.cols/2.0; + rot.at(1,2) += bbox.height/2.0 - src.rows/2.0; + + cv::Mat dst; + cv::warpAffine(src, dst, rot, bbox.size()); + return dst; + } + + + + + + //blends using distance transform + //roi - original roi with 1 or more stitched images + //tranformedRoi - roi-sized image with the new image in the appropriate location + //showImg - bool, switch to enable showing of the new roi + Mat dtBlend(Mat roi, Mat transformedRoi, bool showImg = false) + { + + + Mat roiMask, roiDT, imgWarpedMask,imgDT,roiMaskFinal,imgMaskFinal,imgNew; + threshold(roi,roiMask,1,255,CV_8U); + threshold(transformedRoi,imgWarpedMask,1,255,CV_8U); + + + distanceTransform(roiMask,roiDT,DIST_L2, 3); + distanceTransform(imgWarpedMask,imgDT,DIST_L2, 3); + normalize(roiDT, roiDT, 0.0, 1.0, NORM_MINMAX); + normalize(imgDT, imgDT, 0.0, 1.0, NORM_MINMAX); + + cv::divide(roiDT,(roiDT+imgDT),roiMaskFinal); + cv::divide(imgDT,(roiDT+imgDT),imgMaskFinal); + + + + normalize(roiMaskFinal, roiMaskFinal, 0.0, 255.0, NORM_MINMAX); + normalize(imgMaskFinal, imgMaskFinal, 0.0, 255.0, NORM_MINMAX); + + + + roi.convertTo(roi,CV_32FC1); + transformedRoi.convertTo(transformedRoi,CV_32FC1); + roiMaskFinal.convertTo(roiMaskFinal,CV_32FC1); + imgMaskFinal.convertTo(imgMaskFinal,CV_32FC1); + + + multiply(roiMaskFinal,roi,roi); + multiply(imgMaskFinal,transformedRoi,transformedRoi); + cv::add(roi,transformedRoi, roi); + + if(showImg) + { + normalize(roi, roi, 0.0, 1.0, NORM_MINMAX); + imshow("newRoi",roi); + waitKey(0); + } + + normalize(roi, roi, 0.0, 255.0, NORM_MINMAX); + return roi; + + + } + + + + + + + + + + + + + + + + + + Mat exposureBlend(Mat roi, Mat transformedRoi, bool showImg = false) + { + std::vector images; + UMat umat,umat2; + cv::cvtColor(roi, roi, cv::COLOR_GRAY2BGR); + cv::cvtColor(transformedRoi, transformedRoi, cv::COLOR_GRAY2BGR); + + roi.copyTo(umat); + images.push_back(umat); + + transformedRoi.copyTo(umat2); + images.push_back(umat2); + + + + cv::Mat_ corners(2,1); + /*corners.push_back(Point(0.0,0.0)); + corners.push_back(Point(0.0,0.0));*/ + corners(0,0) = Point(0.0,0.0); + corners(1,0) = Point(0.0,0.0); + + + std::vector masks(2); + + //masks[0] = Mat::ones(roi.size(), CV_8UC3); + //masks[1] = Mat::ones(transformedRoi.size(), CV_8UC3); + threshold(roi,masks[0],1,255,CV_8U); + threshold(transformedRoi,masks[1],1,255,CV_8U); + //cout<<"\n"<< cv::typeToString( masks[0].type() )<<"\n"; + /*cv::cvtColor(masks[0], masks[0], cv::COLOR_GRAY2BGR); + cv::cvtColor(masks[1], masks[1], cv::COLOR_GRAY2BGR);*/ + normalize(masks[0], masks[0], 0.0, 255.0, NORM_MINMAX); + normalize(masks[1], masks[1], 0.0, 255.0, NORM_MINMAX); + + std::vector umatMasks; + for (int i=0; i compensator = detail::ExposureCompensator::createDefault(detail::ExposureCompensator::GAIN); + + + compensator->feed(corners, images, umatMasks ); + + + for (size_t i = 0; i < images.size(); ++i) + { + + cout<< cv::typeToString( umatMasks[i].type() ); + compensator->apply(i, Point(0, 0), images[i], umatMasks[i]); + } + imshow("1",images[0]); + imshow("2",images[1]); + waitKey(0); + //return images[0]; + } + + + + + + + + + + Mat pyramidBlend(Mat roi, Mat transformedRoi, bool showImg = false) + { + /*roi.convertTo(roi,CV_32F); + transformedRoi.convertTo(transformedRoi,CV_32F);*/ + Mat mask1, mask2, overlapMask; + threshold(roi,mask1,1,255,CV_8U); + threshold(transformedRoi,mask2,1,255,CV_8U); + + bitwise_and(mask1,mask2,overlapMask); + int levels = 4; + + std::vector roiPyr(levels), transPyr(levels); + buildPyramid(roi, roiPyr, levels); + buildPyramid(transformedRoi, transPyr, levels); + + + std::vector maskPyr(levels); + maskPyr[0] = overlapMask; + + for (int i = 1; i < levels; i++) + { + Mat tmp; + pyrDown(maskPyr[i - 1], tmp); + maskPyr[i] = tmp; + + } + + for (int i = 0; i < levels; i++) + { + roiPyr[i].convertTo(roiPyr[i],CV_8U); + transPyr[i].convertTo(transPyr[i],CV_8U); + maskPyr[i].convertTo(maskPyr[i],CV_8U); + //normalize(roiPyr[i],roiPyr[i],0.0,1.0,NORM_MINMAX); + //normalize(transPyr[i],transPyr[i],0.0,1.0,NORM_MINMAX); + normalize(maskPyr[i],maskPyr[i],0.0,1.0,NORM_MINMAX); + + } + + + std::vector blendPyr(levels); + for (int i = levels-1; i >=0; i--) { + cout<< cv::typeToString( maskPyr[i].type() )<(3, 3) << 0, -1, 0, + -1, 5 -1, + 0, -1, 0); + filter2D(result, result, 0, sharpening_kernel); + normalize(result,result,0.0,255.0,NORM_MINMAX); + imshow("newRoi",result); + waitKey(0); + } + + return(result); + + + } + + + + + + + + /* stitches images points have to be loaded in the pointBase first @@ -519,6 +787,7 @@ class PointBase { //resizing cout << "w:" < clahe = cv::createCLAHE(4.0, cv::Size(8,8)); clahe->apply(imgSmall,imgSmall); @@ -648,7 +917,7 @@ class PointBase { } } */ - float ratio =0.4; + float ratio =0.4; //0.15 malo vysledok 0 for (int i = 0; i < matches.size(); ++i) { @@ -685,164 +954,98 @@ class PointBase { if(good_matches.size()<3 || H.empty()) { tempMatchCounter++; - Mat workRoi, workImg; - workRoi = roi.clone(); - workImg = imgSmall.clone(); + //Mat workRoi, workImg; + //workRoi = roi.clone(); + //workImg = imgSmall.clone(); + + Mat roiEdit, imgSmallEdit; + roiEdit = roi.clone(); + imgSmallEdit = imgSmall.clone(); + + + GaussianBlur(roi, roiEdit, Size(3, 3), 0); + GaussianBlur(imgSmall, imgSmallEdit, Size(3, 3), 0); + + Canny(roiEdit, roiEdit, 100, 200, 3, false); + Canny(imgSmallEdit, imgSmallEdit, 100, 200, 3, false); - GaussianBlur(roi, workRoi, Size(3, 3), 0); - GaussianBlur(imgSmall, workImg, Size(3, 3), 0); - Canny(workRoi, workRoi, 100, 200, 3, false); - Canny(workImg, workImg, 100, 200, 3, false); Mat result; double min_val, max_val; Point min_loc, max_loc; - matchTemplate(workRoi,workImg,result,TM_CCOEFF); + matchTemplate(roiEdit,imgSmallEdit,result,TM_CCOEFF); minMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc); - Mat roiMask, roiDT, imgWarpedMask,imgDT,roiMaskFinal,imgMaskFinal,imgNew; - threshold(roi,roiMask,1,255,CV_8U); - imgWarpedMask = Mat::zeros(roi.rows,roi.cols,CV_8U); - imgWarpedMask(Rect(max_loc.x,max_loc.y,imgSmall.cols,imgSmall.rows))=1.0; - - - distanceTransform(roiMask,roiDT,DIST_L2, 3); - distanceTransform(imgWarpedMask,imgDT,DIST_L2, 3); - normalize(roiDT, roiDT, 0.0, 1.0, NORM_MINMAX); - normalize(imgDT, imgDT, 0.0, 1.0, NORM_MINMAX); - - cv::divide(roiDT,(roiDT+imgDT),roiMaskFinal); - cv::divide(imgDT,(roiDT+imgDT),imgMaskFinal); - - - - normalize(roiMaskFinal, roiMaskFinal, 0.0, 255.0, NORM_MINMAX); - normalize(imgMaskFinal, imgMaskFinal, 0.0, 255.0, NORM_MINMAX); + Mat imgNew; imgNew = Mat::zeros(roi.rows,roi.cols,CV_8U); imgSmall.copyTo(imgNew(Rect(max_loc.x , max_loc.y , imgSmall.cols,imgSmall.rows))); + //hodnotenie + Mat imgEvalSource = imgNew(Rect(max_loc.x, max_loc.y, imgSmall.cols,imgSmall.rows)); + imwrite("hodnotenie/"+to_string(imgIdx)+"sift-temp-src.png",imgEvalSource); - roiMaskFinal.convertTo(roiMaskFinal,CV_8UC1); - imgMaskFinal.convertTo(imgMaskFinal,CV_8UC1); - roi.convertTo(roi,CV_32FC1); - imgNew.convertTo(imgNew,CV_32FC1); - roiMaskFinal.convertTo(roiMaskFinal,CV_32FC1); - imgMaskFinal.convertTo(imgMaskFinal,CV_32FC1); - - - multiply(roiMaskFinal,roi,roi); - cout< windowWidth) xWitdth = windowWidth - xLoc; - if (yLoc + yHeight > windowHeight) yHeight = windowHeight - yLoc; + if (xLoc + xWitdth > windowWidth) + { + xWitdth = windowWidth - xLoc + 64; + xLoc = xLoc -64; + } + if (yLoc + yHeight > windowHeight) + { + yHeight = windowHeight - yLoc +64; + yLoc = yLoc - 64; + } //create the ROI Mat roi; //we dont need to apply CLAHE to ROI, since it consists of images which have clahe already applied @@ -1182,8 +1400,36 @@ class PointBase { Canny(roiEdit, roiEdit, 100, 200, 3, false); Canny(imgSmallEdit, imgSmallEdit, 100, 200, 3, false); + + //3x3 ball dilation + //Mat circleKernel; + //circleKernel = getStructuringElement(MORPH_ELLIPSE,cv::Size(5,5)); + //dilate everything + //dilate( roiEdit, roiEdit, circleKernel ); + //dilate( imgSmallEdit, imgSmallEdit, circleKernel ); + + + //Mat rectKernel = getStructuringElement(MORPH_RECT,cv::Size(15,5)); + //rectKernel = rotate(rectKernel,-81.0); + + //Mat roiEditOpening, imgSmallEditOpening; + //morphologyEx(roiEdit, roiEditOpening, cv::MORPH_OPEN, rectKernel); + //morphologyEx(imgSmallEdit, imgSmallEditOpening, cv::MORPH_OPEN, rectKernel); + //roiEdit=roiEdit-roiEditOpening; + //imgSmallEdit=imgSmallEdit-imgSmallEditOpening; + + + + //imshow("roiEdit",roiEdit); + //imshow("rectKernel",rectKernel); + //imshow("imgSmallEdit",imgSmallEdit); + //waitKey(0); + cout <<"ROTATE SUCC" < rectHolder; //Mat rect1,rect2,rect3,rect4,rect5; int rectH = imgSmall.rows, rectW = imgSmall.cols; @@ -1259,6 +1505,8 @@ class PointBase { matchTemplate(roiEdit,imgSmallEdit,result,TM_CCOEFF); minMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc); + + //debug stuff Mat roiWithLocation, chosenSmallRoiImg; @@ -1274,7 +1522,16 @@ class PointBase { cout<<"Location in roi X:" << max_loc.x << " Y " << max_loc.y << "\n"; //imshow("chosen smallROI", rects[minIDX]); - + Mat imgNew; + imgNew = Mat::zeros(roi.rows,roi.cols,CV_8U); + imgSmall.copyTo(imgNew(Rect(max_loc.x , max_loc.y , rectW,rectH))); + + //hodnotenie + Mat imgEvalSource = imgNew(Rect(max_loc.x, max_loc.y,rectW,rectH)); + imwrite("hodnotenie/"+to_string(imgIdx)+"src.png",imgEvalSource); + + //moved to dtBlend function + /* Mat roiMask, roiDT, imgWarpedMask,imgDT,roiMaskFinal,imgMaskFinal,imgNew; threshold(roi,roiMask,1,255,CV_8U); imgWarpedMask = Mat::zeros(roi.rows,roi.cols,CV_8U); @@ -1323,9 +1580,22 @@ class PointBase { normalize(roi, roi, 0.0, 255.0, NORM_MINMAX); roi.copyTo(img(Rect(xLoc, yLoc, xWitdth, yHeight))); + */ + imshow("roiorig",roi); + imshow("imgSmall", imgSmall); + Mat newRoi; + newRoi = dtBlend(roi,imgNew,false); + //newRoi = pyramidBlend(roi,imgNew,true); + newRoi.copyTo(img(Rect(xLoc, yLoc, xWitdth, yHeight))); + + //hodnotenie + Mat imgEvalDst= newRoi(Rect(max_loc.x, max_loc.y,rectW,rectH)); + imwrite("hodnotenie/"+to_string(imgIdx)+"dst.png",imgEvalDst); + imgIdx++; + - imwrite("roiafter.jpg",roi); - waitKey(0); + imwrite("roiafter.jpg",newRoi); + //waitKey(0); @@ -1381,7 +1651,562 @@ class PointBase { -}; + + + + + + + + + + + + + + + + + + + + + + + void onlineStitch(int imgW,int imgH, string path) + { + + int idx = 0; + PointBase curr,newPb; + vector diffVector; + Mat img; + int windowHeight,windowWidth; + + + int imgWidth = imgW; + int imgHeight = imgH; + + windowHeight = (int)(3000*(600/50))+imgHeight*2; + windowWidth = (int)((360/60)*1200) + imgWidth; + + + img = Mat::zeros(windowHeight,windowWidth,CV_8UC1); + + + + + + while (true) + { + while (diffVector.empty()) + { + if (idx ==0) + { + if(curr.load(path) == -1) {continue;} //no points loaded + else + { + diffVector=curr.points; + + + } + + + } + else + { + diffVector.clear(); + if (newPb.load(path) == -1) {continue;} //no points loaded + else + { + for (int i = 0; i < newPb.points.size(); i++) + { + if(std::find(curr.points.begin(), curr.points.end(), newPb.points[i]) != curr.points.end()) + { + /* v contains x */ + cout<<"FOUND NOTHING \n"; + } + else + { + diffVector.push_back(newPb.points[i]); + cout<<"FOUND\n"; + } + } + + curr.points=newPb.points; + curr.pathMap=newPb.pathMap; + idx++; + } + + + + } + sleep(2); + } + + + + + + + + + + int qIdx = 0; + for (Point2d coords: diffVector) + { + idx++; + //log to stdout + cout << "x: " << coords.x << std::endl; + cout << "y: " << coords.y << std::endl; + + + string jsonPath = curr.pathMap[coords]; + curr.printPoints(0); + + string pngPath = jsonPath.erase(jsonPath.length()-4); + + pngPath = pngPath + "png"; + cout<< "path: " < clahe = cv::createCLAHE(4.0, cv::Size(8,8)); + clahe->apply(imgSmall,imgSmall); + cout<< cv::typeToString( imgSmall.type() ); + + + //cout << (int)round(coords.x)-(int)round(minX)<< "\n"; + //cout << (int)round(coords.y)-(int)round(minY)<< "\n"; + cout << (int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg)<< "\n"; + + //we need to calculate ROI first, to decide whether it will be empty - if yes, we can just place the picture at the req. location + //default ROI location and size + int xLoc=(int)round(coords.x)*(int)(imgWidth/curr.imgWidthDeg) - imgWidth; //=normalized x-coord. minus 1 width of image + int yLoc=(int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg) - imgHeight; + int xWitdth=3*imgWidth; + int yHeight=3*imgHeight; + //edge cases + if ((int)round(coords.x)*(int)(imgWidth/curr.imgWidthDeg) - imgWidth < 0) xLoc=0; + if ((int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg) - imgHeight < 0) yLoc = 0; + if (xLoc + xWitdth > windowWidth) xWitdth = windowWidth - xLoc; + if (yLoc + yHeight > windowHeight) yHeight = windowHeight - yLoc; + + //create the ROI + Mat roi; //we dont need to apply CLAHE to ROI, since it consists of images which have clahe already applied + roi = img(Rect(xLoc, yLoc, xWitdth, yHeight)); + imshow("roiprev",roi); + //waitKey(0); + cout< rectHolder; + //Mat rect1,rect2,rect3,rect4,rect5; + int rectH = imgSmall.rows, rectW = imgSmall.cols; + + + Mat result; + double min_val, max_val; + Point min_loc, max_loc; + matchTemplate(roiEdit,imgSmallEdit,result,TM_CCOEFF); + minMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc); + + + //debug stuff + Mat roiWithLocation, chosenSmallRoiImg; + //imshow("matchResult",result); + roiWithLocation= roiEdit.clone(); + chosenSmallRoiImg = imgSmallEdit.clone(); + rectangle(roiWithLocation,max_loc,Point(max_loc.x+rectW,max_loc.y+rectH),Scalar(128,128, 0),2,2,0); + rectangle(chosenSmallRoiImg,max_loc,Point(rectW,rectH),Scalar(128,128, 0),2,2,0); + //imshow("roiWithLocation",roiWithLocation); + //imshow("chosenSmallRoiImg",chosenSmallRoiImg); + + //cout<<"HOW MANY RECTS " < diffVector; + Mat img; + int windowHeight,windowWidth; + + + int imgWidth = imgW; + int imgHeight = imgH; + + windowHeight = (int)(3000*(600/50))+imgHeight*2; + windowWidth = (int)((360/60)*1200) + imgWidth; + + + img = Mat::zeros(windowHeight,windowWidth,CV_8UC1); + + + + + + while (true) + { + while (diffVector.empty()) + { + if (idx ==0) + { + if(curr.load(path) == -1) {continue;} //no points loaded + else + { + diffVector=curr.points; + + + } + + + } + else + { + diffVector.clear(); + if (newPb.load(path) == -1) {continue;} //no points loaded + else + { + for (int i = 0; i < newPb.points.size(); i++) + { + if(std::find(curr.points.begin(), curr.points.end(), newPb.points[i]) != curr.points.end()) + { + /* v contains x */ + cout<<"FOUND NOTHING \n"; + } + else + { + diffVector.push_back(newPb.points[i]); + cout<<"FOUND\n"; + } + } + + curr.points=newPb.points; + curr.pathMap=newPb.pathMap; + idx++; + } + + + + } + sleep(2); + } + + + + + + + + + + int qIdx = 0; + for (Point2d coords: diffVector) + { + idx++; + //log to stdout + cout << "x: " << coords.x << std::endl; + cout << "y: " << coords.y << std::endl; + + + string jsonPath = curr.pathMap[coords]; + curr.printPoints(0); + + string pngPath = jsonPath.erase(jsonPath.length()-4); + + pngPath = pngPath + "png"; + cout<< "path: " < clahe = cv::createCLAHE(4.0, cv::Size(8,8)); + clahe->apply(imgSmall,imgSmall); + cout<< cv::typeToString( imgSmall.type() ); + + + //cout << (int)round(coords.x)-(int)round(minX)<< "\n"; + //cout << (int)round(coords.y)-(int)round(minY)<< "\n"; + cout << (int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg)<< "\n"; + + //we need to calculate ROI first, to decide whether it will be empty - if yes, we can just place the picture at the req. location + //default ROI location and size + int xLoc=(int)round(coords.x)*(int)(imgWidth/curr.imgWidthDeg) - imgWidth; //=normalized x-coord. minus 1 width of image + int yLoc=(int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg) - imgHeight; + int xWitdth=3*imgWidth; + int yHeight=3*imgHeight; + //edge cases + if ((int)round(coords.x)*(int)(imgWidth/curr.imgWidthDeg) - imgWidth < 0) xLoc=0; + if ((int)round(coords.y)*(int)(imgHeight/curr.imgHeightDeg) - imgHeight < 0) yLoc = 0; + if (xLoc + xWitdth > windowWidth) xWitdth = windowWidth - xLoc; + if (yLoc + yHeight > windowHeight) yHeight = windowHeight - yLoc; + + //create the ROI + Mat roi; //we dont need to apply CLAHE to ROI, since it consists of images which have clahe already applied + roi = img(Rect(xLoc, yLoc, xWitdth, yHeight)); + imshow("roiprev",roi); + //waitKey(0); + cout< siftPtr = SIFT::create(200); + std::vector keypointsROI, keypointsImg; + cv::Ptr siftExtrPtr; + cv::Mat descriptorsROI, descriptorsImg; + siftPtr->detect(roi, keypointsROI); + siftPtr->detect(imgSmall, keypointsImg); + + + + //compute descriptors from found keypoints + cout<<" SIZE \n"<compute(roi, + keypointsROI, + descriptorsROI); + siftPtr->compute(imgSmall, + keypointsImg, + descriptorsImg); + + //match the descriptors + cv::FlannBasedMatcher matcher; + + std::vector> matches; + matcher.knnMatch(descriptorsROI, descriptorsImg, matches, 2); // Find 2 nearest matches + cv::Mat imageMatches; + + drawMatches(roi,keypointsROI,imgSmall,keypointsImg,matches,imageMatches); + //cv::namedWindow("matches"); + //cv::imshow("matches",imageMatches); + //cv::waitKey(0); + + + cout<<"TU BY MALI BYT MATCHE " <<'\n'; + std::vector< DMatch > good_matches; + + float ratio =0.4; //0.15 malo vysledok 0 + for (int i = 0; i < matches.size(); ++i) + { + + if (matches[i][0].distance < ratio * matches[i][1].distance) + { + good_matches.push_back(matches[i][0]); + cout<<"GOOD MATCH DISTANCE " << matches[i][0].distance <<'\n'; + } + } + + + + std::vector< Point2d > obj; + std::vector< Point2d > scene; + + for( int i = 0; i < good_matches.size(); i++ ) + { + //Get the keypoints from the good matches + obj.push_back( static_cast( keypointsImg[ good_matches[i].trainIdx ].pt )); + scene.push_back( static_cast(keypointsROI[ good_matches[i].queryIdx ].pt )); + } + + //find a transformation based on good matches + //we do not need a Homography, since we deal with affine transformations (no viewport transf. are expected) + //Mat H = findHomography( Mat(obj), Mat(scene), RANSAC ); + Mat H; + if(good_matches.size()>=3) H = estimateAffinePartial2D( Mat(obj), Mat(scene), noArray(),RANSAC ); + + + //here we check for errors - either there were not enough good matches, OR an affine transformation could not be estimated + //we use template matching if errors occured + if(good_matches.size()<3 || H.empty()) + { + + Mat roiEdit, imgSmallEdit; + roiEdit = roi.clone(); + imgSmallEdit = imgSmall.clone(); + + + GaussianBlur(roi, roiEdit, Size(3, 3), 0); + GaussianBlur(imgSmall, imgSmallEdit, Size(3, 3), 0); + + Canny(roiEdit, roiEdit, 100, 200, 3, false); + Canny(imgSmallEdit, imgSmallEdit, 100, 200, 3, false); + + Mat result; + double min_val, max_val; + Point min_loc, max_loc; + matchTemplate(roiEdit,imgSmallEdit,result,TM_CCOEFF); + minMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc); + + + + Mat imgNew; + imgNew = Mat::zeros(roi.rows,roi.cols,CV_8U); + imgSmall.copyTo(imgNew(Rect(max_loc.x , max_loc.y , imgSmall.cols,imgSmall.rows))); + + Mat newRoi; + newRoi = dtBlend(roi,imgNew, false); + newRoi.copyTo(img(Rect(xLoc, yLoc, xWitdth, yHeight))); + + } + else + { + cout<<"SIFT"< -using namespace cv; -using namespace std; -// static void help() -// { -// cout << "\nThis program demonstrates kmeans clustering.\n" -// "It generates an image with random points, then assigns a random number of cluster\n" -// "centers and uses kmeans to move those cluster centers to their representitive location\n" -// "Call\n" -// "./kmeans\n" << endl; -// } -int main( int /*argc*/, char** /*argv*/ ) -{ - const int MAX_CLUSTERS = 5; - Scalar colorTab[] = - { - Scalar(0, 0, 255), - Scalar(0,255,0), - Scalar(255,100,100), - Scalar(255,0,255), - Scalar(0,255,255) - }; - Mat img(500, 500, CV_8UC3); - RNG rng(12345); - for(;;) - { - int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1); - int i, sampleCount = rng.uniform(1, 1001); - Mat points(sampleCount, 1, CV_32FC2), labels; - clusterCount = MIN(clusterCount, sampleCount); - std::vector centers; - /* generate random sample from multigaussian distribution */ - for( k = 0; k < clusterCount; k++ ) - { - Point center; - center.x = rng.uniform(0, img.cols); - center.y = rng.uniform(0, img.rows); - Mat pointChunk = points.rowRange(k*sampleCount/clusterCount, - k == clusterCount - 1 ? sampleCount : - (k+1)*sampleCount/clusterCount); - rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05)); - } - randShuffle(points, 1, &rng); - double compactness = kmeans(points, clusterCount, labels, - TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0), - 3, KMEANS_PP_CENTERS, centers); - img = Scalar::all(0); - for( i = 0; i < sampleCount; i++ ) - { - int clusterIdx = labels.at(i); - Point ipt = points.at(i); - circle( img, ipt, 2, colorTab[clusterIdx], FILLED, LINE_AA ); - } - for (i = 0; i < (int)centers.size(); ++i) - { - Point2f c = centers[i]; - circle( img, c, 40, colorTab[i], 1, LINE_AA ); - } - cout << "Compactness: " << compactness << endl; - cout << "Labels rows" << labels.rows; - cout << "Labels cols" << labels.cols; - imshow("clusters", img); - char key = (char)waitKey(); - if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC' - break; - } - return 0; -} \ No newline at end of file diff --git a/src/test-stitch.cpp b/src/test-stitch.cpp deleted file mode 100644 index 74887b6..0000000 --- a/src/test-stitch.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// CPP program to Stitch -// input images (panorama) using OpenCV -#include -#include - -// Include header files from OpenCV directory -// required to stitch images. -#include "opencv2/imgcodecs.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/stitching.hpp" - -using namespace std; -using namespace cv; - -// Define mode for stitching as panorama -// (One out of many functions of Stitcher) -Stitcher::Mode mode = Stitcher::SCANS; - -// Array for pictures -vector imgs; - -int main(int argc, char* argv[]) -{ - // Get all the images that need to be - // stitched as arguments from command line - for (int i = 1; i < argc; ++i) - { - // Read the ith argument or image - // and push into the image array - Mat img = imread(argv[i]); - if (img.empty()) - { - // Exit if image is not present - cout << "Can't read image '" << argv[i] << "'\n"; - return -1; - } - imgs.push_back(img); - } - - // Define object to store the stitched image - Mat pano; - - // Create a Stitcher class object with mode panoroma - Ptr stitcher = Stitcher::create(mode); - - // Command to stitch all the images present in the image array - Stitcher::Status status = stitcher->stitch(imgs, pano); - - if (status != Stitcher::OK) - { - // Check if images could not be stitched - // status is OK if images are stitched successfully - cout << "Can't stitch images\n"; - return -1; - } - - // Store a new image stitched from the given - //set of images as "result.jpg" - imwrite("result.jpg", pano); - - // Show the result - imshow("Result", pano); - - waitKey(0); - return 0; -} \ No newline at end of file diff --git a/src/test.cpp b/src/test.cpp index 9ff4aca..414a9f5 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -43,12 +43,12 @@ int main(int argc, char** argv) //120/2022-11-15_09-35-09 //155/2022-11-15_07-18-56 //2/2022-10-13_13-33-22 - //1/2022-10-13_11-50-12 + //v //pb.load("../1/2022-10-13_11-50-12/snapshots/"); - pb.load("../data/"); + pb.load("../155/2022-11-15_07-18-56/snapshots/"); //test print all point info - pb.printPoints(0); + //pb.printPoints(0); /* test get path path: ../data/0000044.json; @@ -57,7 +57,7 @@ int main(int argc, char** argv) */ cout << pb.getPath(206.500,1051.00) << '\n'; - pb.showPointImg(); + //pb.showPointImg(); /* vector res = pb.getAdjacents(Point2d(75.1,3220.80)); @@ -69,8 +69,10 @@ int main(int argc, char** argv) */ //pb.stitchImgs(); - cout <<"IMG HEIGHT:" << pb.imgHeightDeg <<"\n"; - cout <<"IMG WIDTH DEG:" << pb.imgWidthDeg <<"\n"; - pb.cumdump(650,525); + //cout <<"IMG HEIGHT:" << pb.imgHeightDeg <<"\n"; + //cout <<"IMG WIDTH DEG:" << pb.imgWidthDeg <<"\n"; + //pb.cumdump(770,605); + pb.patternMatchTry(770,605); + //pb.onlineStitchSIFT(1280,720,"online/"); } \ No newline at end of file