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