|
|
@ -1,3 +1,14 @@
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @file pointbase.cpp
|
|
|
|
|
|
|
|
* @author Bc. Pavol Debnár
|
|
|
|
|
|
|
|
* This is the main file for the thesis implementing the pointBase class
|
|
|
|
|
|
|
|
* 2022/23
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "opencv2/highgui.hpp"
|
|
|
|
#include "opencv2/highgui.hpp"
|
|
|
|
#include "opencv2/core.hpp"
|
|
|
|
#include "opencv2/core.hpp"
|
|
|
|
#include "opencv2/imgproc.hpp"
|
|
|
|
#include "opencv2/imgproc.hpp"
|
|
|
@ -26,9 +37,10 @@ namespace fs = std::filesystem;
|
|
|
|
//sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json
|
|
|
|
//sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief struct necessary for comparison between 2 opencv points - when using std::map ; used to sort points according to X value
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//struct necessary for comparison between 2 opencv points - when using std::map
|
|
|
|
|
|
|
|
//used to sort points according to X value
|
|
|
|
|
|
|
|
struct ComparePoints
|
|
|
|
struct ComparePoints
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool operator () (const cv::Point& a, const cv::Point& b) const
|
|
|
|
bool operator () (const cv::Point& a, const cv::Point& b) const
|
|
|
@ -37,21 +49,30 @@ struct ComparePoints
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} CP;
|
|
|
|
} CP;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief class implemented as solution for the thesis providing stitching and stitching features
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
class PointBase {
|
|
|
|
class PointBase {
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
vector <Point2d> points; //all points - points are being removed as adjacencies are found
|
|
|
|
vector <Point2d> points; /**< all points - points are being removed as adjacencies are found */
|
|
|
|
vector <Point2d> doneVector; //points that have been successfully searched for adjacencies
|
|
|
|
vector <Point2d> doneVector; /**< points that have been successfully searched for adjacencies */
|
|
|
|
vector <Point2d> toDoVector; //points yet to be searched for adjacent points
|
|
|
|
vector <Point2d> toDoVector; /**< points yet to be searched for adjacent points*/
|
|
|
|
std::map<Point2d, string, ComparePoints> pathMap; //map for file paths - get the path of a file via pathMap[Point2d(x,y)]
|
|
|
|
std::map<Point2d, string, ComparePoints> pathMap; /**< map for file paths - get the path of a file via pathMap[Point2d(x,y)] */
|
|
|
|
|
|
|
|
|
|
|
|
double imgWidthDeg;
|
|
|
|
double imgWidthDeg; /**< image width in degress taken from file */
|
|
|
|
double imgHeightDeg;
|
|
|
|
double imgHeightDeg; /**< image height in sensor format */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//loaded points in pointbase are sorted according to X value
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief load the points from a database - necessary for the offline algorithm
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* loaded points in pointbase are sorted according to X value
|
|
|
|
|
|
|
|
* @param path - location where images and their jsons are stored in string format
|
|
|
|
|
|
|
|
* @return int - 0 if success, -1 if no points were loaded
|
|
|
|
|
|
|
|
*/
|
|
|
|
int load(string path)
|
|
|
|
int load(string path)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//std::string path = "../data/";
|
|
|
|
//std::string path = "../data/";
|
|
|
@ -97,7 +118,11 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief prints the points from the database into the terminal
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param which - if which is 0, the points vector is printed; 1 prints the complete contents of pathMap
|
|
|
|
|
|
|
|
*/
|
|
|
|
void printPoints(int which=0)
|
|
|
|
void printPoints(int which=0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (which==1) // prints current points vector
|
|
|
|
if (which==1) // prints current points vector
|
|
|
@ -128,7 +153,13 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief returns the path of a point specified by x and y values
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param x - x-value of the point
|
|
|
|
|
|
|
|
* @param y - y-value of the point
|
|
|
|
|
|
|
|
* @return string - path of the point
|
|
|
|
|
|
|
|
*/
|
|
|
|
string getPath(double x, double y)
|
|
|
|
string getPath(double x, double y)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
string path = pathMap[Point2d(x,y)];
|
|
|
|
string path = pathMap[Point2d(x,y)];
|
|
|
@ -143,8 +174,12 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//shows the location of loaded points on an images
|
|
|
|
|
|
|
|
//useful for debugging
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief shows the location of loaded points on an images
|
|
|
|
|
|
|
|
* useful for debugging
|
|
|
|
|
|
|
|
* images have to be loaded using the load() function
|
|
|
|
|
|
|
|
*/
|
|
|
|
void showPointImg()
|
|
|
|
void showPointImg()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Mat img(1200, 360, CV_8UC3, Scalar(0, 0, 0));
|
|
|
|
Mat img(1200, 360, CV_8UC3, Scalar(0, 0, 0));
|
|
|
@ -157,9 +192,13 @@ class PointBase {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*DESTRUCTIVE!! - removes found adj. points from points vector, adds them to the toBeDone vector
|
|
|
|
|
|
|
|
Searches for adjacent points to a given point
|
|
|
|
/**
|
|
|
|
Returns either empty vector, or a vector with the found adjacent points
|
|
|
|
* @brief DESTRUCTIVE!! - removes found adj. points from points vector, adds them to the toBeDone vector
|
|
|
|
|
|
|
|
* Searches for adjacent points to a given point
|
|
|
|
|
|
|
|
* Returns either empty vector, or a vector with the found adjacent points
|
|
|
|
|
|
|
|
* @param inputPoint - opencv Point2d of the searched point
|
|
|
|
|
|
|
|
* @return vector of <Point2d> - points of images which are adjacent to the inputPoint
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
vector<Point2d> getAdjacents(Point2d inputPoint)
|
|
|
|
vector<Point2d> getAdjacents(Point2d inputPoint)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -224,8 +263,13 @@ class PointBase {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//rotation function
|
|
|
|
/**
|
|
|
|
//https://stackoverflow.com/questions/22041699/rotate-an-image-without-cropping-in-opencv-in-c
|
|
|
|
* @brief rotation function
|
|
|
|
|
|
|
|
* https://stackoverflow.com/questions/22041699/rotate-an-image-without-cropping-in-opencv-in-c
|
|
|
|
|
|
|
|
* @param src - input image
|
|
|
|
|
|
|
|
* @param angle - angle in degrees
|
|
|
|
|
|
|
|
* @return rotated image
|
|
|
|
|
|
|
|
*/
|
|
|
|
Mat rotate(Mat src, double angle)
|
|
|
|
Mat rotate(Mat src, double angle)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
cv::Point2f center((src.cols-1)/2.0, (src.rows-1)/2.0);
|
|
|
|
cv::Point2f center((src.cols-1)/2.0, (src.rows-1)/2.0);
|
|
|
@ -245,10 +289,15 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//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
|
|
|
|
* @brief blends using distance transform
|
|
|
|
//showImg - bool, switch to enable showing of the new roi
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param roi original roi with 1 or more stitched images
|
|
|
|
|
|
|
|
* @param transformedRoi roi-sized! image with the new image in the appropriate location
|
|
|
|
|
|
|
|
* @param showImg bool, switch to enable showing of the new roi
|
|
|
|
|
|
|
|
* @return Mat - the blended image
|
|
|
|
|
|
|
|
*/
|
|
|
|
Mat dtBlend(Mat roi, Mat transformedRoi, bool showImg = false)
|
|
|
|
Mat dtBlend(Mat roi, Mat transformedRoi, bool showImg = false)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
@ -380,15 +429,14 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief blends using image pyramids transform
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param roi original roi with 1 or more stitched images
|
|
|
|
|
|
|
|
* @param transformedRoi roi-sized! image with the new image in the appropriate location
|
|
|
|
|
|
|
|
* @param showImg bool, switch to enable showing of the new roi
|
|
|
|
|
|
|
|
* @return Mat - the blended image
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
Mat pyramidBlend(Mat roi, Mat transformedRoi, bool showImg = false)
|
|
|
|
Mat pyramidBlend(Mat roi, Mat transformedRoi, bool showImg = false)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/*roi.convertTo(roi,CV_32F);
|
|
|
|
/*roi.convertTo(roi,CV_32F);
|
|
|
@ -494,12 +542,11 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/**
|
|
|
|
stitches images
|
|
|
|
* @brief stitches images using opencv pipeline
|
|
|
|
points have to be loaded in the pointBase first
|
|
|
|
* points have to be loaded in the pointBase first
|
|
|
|
uses public toDoVector, points
|
|
|
|
* saves the result image in current directory
|
|
|
|
BUG: not all adjacent images are used for stitching - OpenCV evaluates them as not appropriate for stitching
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
void stitchImgs()
|
|
|
|
void stitchImgs()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int imgIdx = 0;
|
|
|
|
int imgIdx = 0;
|
|
|
@ -636,6 +683,11 @@ class PointBase {
|
|
|
|
/*returns minimum and maximum X and Y values from pointbase
|
|
|
|
/*returns minimum and maximum X and Y values from pointbase
|
|
|
|
minX,maxX,minY,maxY
|
|
|
|
minX,maxX,minY,maxY
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief gets the values of the top right, left and bottom right left images in pointBase
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return vector, where the values are [minX,maxX,minY,maxY]
|
|
|
|
|
|
|
|
*/
|
|
|
|
std::vector <double> getEdgeValues()
|
|
|
|
std::vector <double> getEdgeValues()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
double minX=999;
|
|
|
|
double minX=999;
|
|
|
@ -661,6 +713,23 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief image stitching using SIFT
|
|
|
|
|
|
|
|
* saves the source image to the current directory
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param imgW source image width
|
|
|
|
|
|
|
|
* @param imgH source image height
|
|
|
|
|
|
|
|
*/
|
|
|
|
void cumdump(int imgW,int imgH)
|
|
|
|
void cumdump(int imgW,int imgH)
|
|
|
|
{ //sift takes too long if images are large, so we shrink them
|
|
|
|
{ //sift takes too long if images are large, so we shrink them
|
|
|
|
int imgWidth = imgW;
|
|
|
|
int imgWidth = imgW;
|
|
|
@ -1093,7 +1162,7 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
imwrite("result0GIOJSDFI.png", img);
|
|
|
|
imwrite("result.png", img);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1218,7 +1287,12 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief stitches images using pattern matching
|
|
|
|
|
|
|
|
* saves the source image to the current directory
|
|
|
|
|
|
|
|
* @param imgW width of the source images
|
|
|
|
|
|
|
|
* @param imgH height of the source images
|
|
|
|
|
|
|
|
*/
|
|
|
|
void patternMatchTry(int imgW,int imgH)
|
|
|
|
void patternMatchTry(int imgW,int imgH)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int imgWidth = imgW;
|
|
|
|
int imgWidth = imgW;
|
|
|
@ -1356,7 +1430,7 @@ class PointBase {
|
|
|
|
if (qIdx==0)
|
|
|
|
if (qIdx==0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
imgSmall.copyTo(img(cv::Rect((int)round(coords.x)*(int)(imgWidth/imgWidthDeg),(int)round(coords.y)*(int)(imgHeight/imgHeightDeg),imgSmall.cols, imgSmall.rows)));
|
|
|
|
imgSmall.copyTo(img(cv::Rect((int)round(coords.x)*(int)(imgWidth/imgWidthDeg),(int)round(coords.y)*(int)(imgHeight/imgHeightDeg),imgSmall.cols, imgSmall.rows)));
|
|
|
|
cout<<"DINGUS WAS PLACED \n";
|
|
|
|
cout<<"IMAGE WAS PLACED \n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
//default ROI location and size
|
|
|
|
//default ROI location and size
|
|
|
@ -1645,7 +1719,7 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
imwrite("result0GIOJSDFI.png", img);
|
|
|
|
imwrite("result.png", img);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1672,7 +1746,14 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief online image stitching using pattern matching
|
|
|
|
|
|
|
|
* saves the result image to the current directory
|
|
|
|
|
|
|
|
* do not load() any database previous to using this function
|
|
|
|
|
|
|
|
* @param imgW source image width
|
|
|
|
|
|
|
|
* @param imgH source image height
|
|
|
|
|
|
|
|
* @param path path to the images
|
|
|
|
|
|
|
|
*/
|
|
|
|
void onlineStitch(int imgW,int imgH, string path)
|
|
|
|
void onlineStitch(int imgW,int imgH, string path)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
@ -1909,7 +1990,7 @@ class PointBase {
|
|
|
|
imshow("Location of Images", dotImage);//Showing the circle//
|
|
|
|
imshow("Location of Images", dotImage);//Showing the circle//
|
|
|
|
//imshow("img",img);
|
|
|
|
//imshow("img",img);
|
|
|
|
waitKey(10);
|
|
|
|
waitKey(10);
|
|
|
|
imwrite("result0GIOJSDFI.png", img);
|
|
|
|
imwrite("result.png", img);
|
|
|
|
qIdx++;
|
|
|
|
qIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//string resultName = "result" + to_string(imgIdx) +".png";
|
|
|
|
//string resultName = "result" + to_string(imgIdx) +".png";
|
|
|
@ -1924,7 +2005,14 @@ class PointBase {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief online image stitching using SIFT
|
|
|
|
|
|
|
|
* saves the result image to the current directory
|
|
|
|
|
|
|
|
* do not load() any database previous to using this function
|
|
|
|
|
|
|
|
* @param imgW source image width
|
|
|
|
|
|
|
|
* @param imgH source image height
|
|
|
|
|
|
|
|
* @param path path to the images
|
|
|
|
|
|
|
|
*/
|
|
|
|
void onlineStitchSIFT(int imgW,int imgH, string path)
|
|
|
|
void onlineStitchSIFT(int imgW,int imgH, string path)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
@ -2192,7 +2280,7 @@ class PointBase {
|
|
|
|
imshow("Location of Images", dotImage);//Showing the circle//
|
|
|
|
imshow("Location of Images", dotImage);//Showing the circle//
|
|
|
|
//imshow("img",img);
|
|
|
|
//imshow("img",img);
|
|
|
|
waitKey(10);
|
|
|
|
waitKey(10);
|
|
|
|
imwrite("result0GIOJSDFI.png", img);
|
|
|
|
imwrite("result.png", img);
|
|
|
|
qIdx++;
|
|
|
|
qIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//string resultName = "result" + to_string(imgIdx) +".png";
|
|
|
|
//string resultName = "result" + to_string(imgIdx) +".png";
|
|
|
|