parent
527e38b63d
commit
3809ee552f
@ -1,3 +1,24 @@
|
|||||||
# DP - Spájanie snímkov + úprava jasu
|
# Stitching Barrel Surface Images and Correcting Their Brightness - Master's Thesis
|
||||||
|
|
||||||
verzia opencv: 4.5.2
|
|
||||||
|
##### Prerequisites
|
||||||
|
OpenCV version: 4.5.2
|
||||||
|
https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html
|
||||||
|
|
||||||
|
C++17
|
||||||
|
|
||||||
|
jsoncpp
|
||||||
|
```sh
|
||||||
|
sudo apt install libjsoncpp-dev
|
||||||
|
sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Files
|
||||||
|
test-stitch.cpp - OpenCV tutorial file for stitching
|
||||||
|
test-kmeans.cpp - OpenCV tutorial file for K-Means alg.
|
||||||
|
pointbase.cpp - Structure for organizing points representing images
|
||||||
|
test.cpp - General functionality tests - for proper function, folder containing images+json files is required on the same level as src
|
||||||
|
makefile
|
||||||
|
|
||||||
|
##### Compilation
|
||||||
|
Compile using make
|
@ -0,0 +1,8 @@
|
|||||||
|
test:
|
||||||
|
g++ -std=c++17 -o test test.cpp -ljsoncpp `pkg-config opencv --cflags --libs`
|
||||||
|
g++ -o test-stitch test-stitch.cpp `pkg-config opencv --cflags --libs`
|
||||||
|
g++ -o test-kmeans test-kmeans.cpp `pkg-config opencv --cflags --libs`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,119 @@
|
|||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
//C++17
|
||||||
|
//sudo apt install libjsoncpp-dev
|
||||||
|
//sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//struct necessary for comparison between 2 opencv points - when using std::map
|
||||||
|
//used to sort points according to X value
|
||||||
|
struct ComparePoints
|
||||||
|
{
|
||||||
|
bool operator () (const cv::Point& a, const cv::Point& b) const
|
||||||
|
{
|
||||||
|
return (a.x < b.x) || (a.x == b.x && a.y < b.y);
|
||||||
|
}
|
||||||
|
} CP;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PointBase {
|
||||||
|
public:
|
||||||
|
vector <Point2d> points;
|
||||||
|
vector <Point2d> doneVector;
|
||||||
|
std::map<Point2d, string, ComparePoints> pathMap;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//loaded points in pointbase are sorted according to X value
|
||||||
|
int load(string path)
|
||||||
|
{
|
||||||
|
//std::string path = "../data/";
|
||||||
|
for (const auto & entry : fs::directory_iterator(path))
|
||||||
|
{
|
||||||
|
string filePath = entry.path();
|
||||||
|
//cout << filePath.find(".json") << std::endl;
|
||||||
|
if (filePath.find(".json") != string::npos)
|
||||||
|
{
|
||||||
|
//std::cout << filePath << std::endl;
|
||||||
|
std::ifstream coord_file(filePath, std::ifstream::binary);
|
||||||
|
Json::Value coords;
|
||||||
|
|
||||||
|
coord_file >> coords;
|
||||||
|
//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());
|
||||||
|
pathMap[newPoint] = filePath;
|
||||||
|
points.push_back(newPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.empty()) {
|
||||||
|
cout << "No points detected, check path \n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sort(points.begin(),points.end(),CP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printPoints(int which=0)
|
||||||
|
{
|
||||||
|
if (which==1) // prints current points vector
|
||||||
|
{
|
||||||
|
for(int i =0; i<points.size(); i++)
|
||||||
|
{
|
||||||
|
cout << "point " << i <<'\n';
|
||||||
|
cout << "x: " << points[i].x << '\n';
|
||||||
|
cout << "y: " << points[i].y << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (which==0) // prints Contents of pointBase
|
||||||
|
{
|
||||||
|
for (const auto& [point, path] : pathMap)
|
||||||
|
{
|
||||||
|
std::cout << "path: " << path<< "; \n";
|
||||||
|
std::cout << "x: " << point.x << "; \n";
|
||||||
|
std::cout << "y: " << point.y << "; \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string getPath(double x, double y)
|
||||||
|
{
|
||||||
|
string path = pathMap[Point2d(x,y)];
|
||||||
|
return(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//shows the location of loaded points on an images
|
||||||
|
//useful for debugging
|
||||||
|
void showPointImg()
|
||||||
|
{
|
||||||
|
Mat img(1200, 360, CV_8UC3, Scalar(0, 0, 0));
|
||||||
|
for(int i =0; i<points.size(); i++)
|
||||||
|
{
|
||||||
|
circle(img, Point2d(points[i].x, (points[i].y)/10),3, Scalar(255, 0, 0), 3);
|
||||||
|
}
|
||||||
|
imshow("Location of Images", img);//Showing the circle//
|
||||||
|
waitKey(0);//Waiting for Keystroke//
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,71 @@
|
|||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
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<Point2f> 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<int>(i);
|
||||||
|
Point ipt = points.at<Point2f>(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;
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
// CPP program to Stitch
|
||||||
|
// input images (panorama) using OpenCV
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
// 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<Mat> 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 = 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;
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
#include "opencv2/highgui.hpp"
|
||||||
|
#include "opencv2/core.hpp"
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include "pointbase.cpp"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
//C++17
|
||||||
|
//sudo apt install libjsoncpp-dev
|
||||||
|
//sudo ln -s /usr/include/jsoncpp/json/ /usr/include/json
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
/* //print point values manually
|
||||||
|
std::string path = "../data/";
|
||||||
|
for (const auto & entry : fs::directory_iterator(path))
|
||||||
|
{
|
||||||
|
string filePath = entry.path();
|
||||||
|
//cout << filePath.find(".json") << std::endl;
|
||||||
|
if (filePath.find(".json") != string::npos)
|
||||||
|
{
|
||||||
|
std::cout << filePath << std::endl;
|
||||||
|
std::ifstream coord_file(filePath, std::ifstream::binary);
|
||||||
|
Json::Value coords;
|
||||||
|
|
||||||
|
coord_file >> coords;
|
||||||
|
cout << "x: " << coords["depthPos"]["x"].asDouble() << std::endl;
|
||||||
|
cout << "y: " << coords["depthPos"]["y"].asDouble() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//test pointbase load
|
||||||
|
PointBase pb;
|
||||||
|
pb.load("../data/");
|
||||||
|
|
||||||
|
//test print all point info
|
||||||
|
pb.printPoints(1);
|
||||||
|
|
||||||
|
/* test get path
|
||||||
|
path: ../data/0000044.json;
|
||||||
|
x: 206.5;
|
||||||
|
y: 1051;
|
||||||
|
*/
|
||||||
|
cout << pb.getPath(206.500,1051.00) << '\n';
|
||||||
|
|
||||||
|
pb.showPointImg();
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue