mirror of
https://github.com/debnarpavol/spajanie_snimkov_uprava_jasu.git
synced 2025-07-03 09:07:20 +02:00
added doxygen comments, cleaned up a little
This commit is contained in:
@ -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,11 +542,10 @@ 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()
|
||||||
{
|
{
|
||||||
@ -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";
|
||||||
|
42
src/test.cpp
42
src/test.cpp
@ -1,3 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @file pointbase.cpp
|
||||||
|
* @author Bc. Pavol Debnár
|
||||||
|
* This is the test file with sample usage of 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"
|
||||||
@ -37,15 +46,26 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////
|
||||||
|
//offline stitching
|
||||||
|
|
||||||
//test pointbase load
|
//test pointbase load
|
||||||
PointBase pb;
|
PointBase pb;
|
||||||
|
pb.load("../155/2022-11-15_07-18-56/snapshots/");
|
||||||
|
pb.patternMatchTry(770,605);
|
||||||
|
pb.cumdump(770,605);
|
||||||
|
|
||||||
|
/*
|
||||||
|
here are sample inputs
|
||||||
|
|
||||||
|
|
||||||
//pb.load("../data/");
|
//pb.load("../data/");
|
||||||
//120/2022-11-15_09-35-09
|
//120/2022-11-15_09-35-09
|
||||||
//155/2022-11-15_07-18-56
|
//155/2022-11-15_07-18-56
|
||||||
//2/2022-10-13_13-33-22
|
//2/2022-10-13_13-33-22
|
||||||
//v
|
//v
|
||||||
//pb.load("../1/2022-10-13_11-50-12/snapshots/");
|
//pb.load("../1/2022-10-13_11-50-12/snapshots/");
|
||||||
pb.load("../155/2022-11-15_07-18-56/snapshots/");
|
*/
|
||||||
|
|
||||||
//test print all point info
|
//test print all point info
|
||||||
//pb.printPoints(0);
|
//pb.printPoints(0);
|
||||||
@ -55,24 +75,16 @@ int main(int argc, char** argv)
|
|||||||
x: 206.5;
|
x: 206.5;
|
||||||
y: 1051;
|
y: 1051;
|
||||||
*/
|
*/
|
||||||
cout << pb.getPath(206.500,1051.00) << '\n';
|
//cout << pb.getPath(206.500,1051.00) << '\n';
|
||||||
|
|
||||||
//pb.showPointImg();
|
//pb.showPointImg();
|
||||||
|
|
||||||
/*
|
|
||||||
vector<Point2d> res = pb.getAdjacents(Point2d(75.1,3220.80));
|
|
||||||
for (Point2d p :res)
|
|
||||||
{
|
|
||||||
cout << "x: " << p.x << std::endl;
|
|
||||||
cout << "y: " << p.y << std::endl;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//pb.stitchImgs();
|
/////////////////////////////////////////////////////
|
||||||
//cout <<"IMG HEIGHT:" << pb.imgHeightDeg <<"\n";
|
//online stitching
|
||||||
//cout <<"IMG WIDTH DEG:" << pb.imgWidthDeg <<"\n";
|
/////////////////////////////////////////////////////
|
||||||
//pb.cumdump(770,605);
|
|
||||||
pb.patternMatchTry(770,605);
|
//PointBase pb;
|
||||||
//pb.onlineStitchSIFT(1280,720,"online/");
|
//pb.onlineStitchSIFT(1280,720,"online/");
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user