add support for loading yml images
This commit is contained in:
@ -27,6 +27,7 @@ struct Config
|
|||||||
std::string output = "";
|
std::string output = "";
|
||||||
std::string norm = "";
|
std::string norm = "";
|
||||||
std::string bg = "";
|
std::string bg = "";
|
||||||
|
std::string curve = "";
|
||||||
bool harris = false;
|
bool harris = false;
|
||||||
float minSize = 7;
|
float minSize = 7;
|
||||||
unsigned int size = 50;
|
unsigned int size = 50;
|
||||||
@ -38,8 +39,9 @@ struct Config
|
|||||||
|
|
||||||
const char *argp_program_version = "0.2";
|
const char *argp_program_version = "0.2";
|
||||||
const char *argp_program_bug_address = "<carl@uvos.xyz>";
|
const char *argp_program_bug_address = "<carl@uvos.xyz>";
|
||||||
static char doc[] = "Program to determine the lubricant thikness on a curved surface";
|
static char doc[] = "Program to determine the lubricant thikness on a curved surface.\n\
|
||||||
static char args_doc[] = "";
|
Possible operations: apply create curve mkcurve mkboard";
|
||||||
|
static char args_doc[] = "[OPERATION] IMAGE1 IMAGE2 ...";
|
||||||
|
|
||||||
static struct argp_option options[] =
|
static struct argp_option options[] =
|
||||||
{
|
{
|
||||||
@ -53,6 +55,7 @@ static struct argp_option options[] =
|
|||||||
{"output", 'o', "File Name", 0, "output file name" },
|
{"output", 'o', "File Name", 0, "output file name" },
|
||||||
{"interactive", 'i', 0, 0, "interactivly process multiple commands" },
|
{"interactive", 'i', 0, 0, "interactivly process multiple commands" },
|
||||||
{"simpe-stich", 'a', 0, 0, "Use non blending sticher" },
|
{"simpe-stich", 'a', 0, 0, "Use non blending sticher" },
|
||||||
|
{"curve", 'c', "File Name", 0, "curve file name" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,6 +95,9 @@ error_t parse_opt (int key, char *arg, struct argp_state *state)
|
|||||||
case 'o':
|
case 'o':
|
||||||
config->output.assign(arg);
|
config->output.assign(arg);
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
config->curve.assign(arg);
|
||||||
|
break;
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
config->commandsFiles = &state->argv[state->next-1];
|
config->commandsFiles = &state->argv[state->next-1];
|
||||||
state->next = state->argc;
|
state->next = state->argc;
|
||||||
|
@ -61,4 +61,4 @@ std::string Log::getLabel(Level level)
|
|||||||
|
|
||||||
bool Log::headers = false;
|
bool Log::headers = false;
|
||||||
Log::Level Log::level = WARN;
|
Log::Level Log::level = WARN;
|
||||||
bool Log::endline = false;
|
bool Log::endline = true;
|
||||||
|
122
src/main.cpp
122
src/main.cpp
@ -32,6 +32,7 @@
|
|||||||
#include "uvosunwrap/log.h"
|
#include "uvosunwrap/log.h"
|
||||||
#include "uvosunwrap/charuco.h"
|
#include "uvosunwrap/charuco.h"
|
||||||
#include "uvosunwrap/harris.h"
|
#include "uvosunwrap/harris.h"
|
||||||
|
#include "uvosunwrap/curve.h"
|
||||||
|
|
||||||
#define IMREAD_SIZE pow(2, 20)
|
#define IMREAD_SIZE pow(2, 20)
|
||||||
|
|
||||||
@ -39,6 +40,8 @@ enum {
|
|||||||
CREATE_CHARUCO,
|
CREATE_CHARUCO,
|
||||||
CREATE_MAP,
|
CREATE_MAP,
|
||||||
APPLY_MAP,
|
APPLY_MAP,
|
||||||
|
APPLY_CURVE,
|
||||||
|
CREATE_CURVE,
|
||||||
EXIT
|
EXIT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,23 +53,24 @@ int selectOperation(char** opt)
|
|||||||
return CREATE_MAP;
|
return CREATE_MAP;
|
||||||
else if(strcmp(opt[0], "apply" ) == 0)
|
else if(strcmp(opt[0], "apply" ) == 0)
|
||||||
return APPLY_MAP;
|
return APPLY_MAP;
|
||||||
else if(strcmp(opt[0], "makeboard" ) == 0)
|
else if(strcmp(opt[0], "curve" ) == 0)
|
||||||
|
return APPLY_CURVE;
|
||||||
|
else if(strcmp(opt[0], "mkcurve" ) == 0)
|
||||||
|
return CREATE_CURVE;
|
||||||
|
else if(strcmp(opt[0], "mkboard" ) == 0)
|
||||||
return CREATE_CHARUCO;
|
return CREATE_CHARUCO;
|
||||||
else if(strcmp(opt[0], "exit" ) == 0)
|
else if(strcmp(opt[0], "exit" ) == 0)
|
||||||
return EXIT;
|
return EXIT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<cv::Mat> loadImages(char** fileNames)
|
cv::Mat openImageImg(char* fileName)
|
||||||
{
|
{
|
||||||
std::vector<cv::Mat> images;
|
int fd = open(fileName, O_RDONLY);
|
||||||
for(size_t i = 0; fileNames[i]; ++i)
|
|
||||||
{
|
|
||||||
int fd = open(fileNames[i], O_RDONLY);
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
{
|
{
|
||||||
Log(Log::WARN)<<"could not open "<<fileNames[i]<< "ignoreing";
|
Log(Log::WARN)<<"could not open "<<fileName<< "ignoreing";
|
||||||
continue;
|
return cv::Mat();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
@ -78,8 +82,42 @@ std::vector<cv::Mat> loadImages(char** fileNames)
|
|||||||
buffer.resize(pos+IMREAD_SIZE);
|
buffer.resize(pos+IMREAD_SIZE);
|
||||||
Log(Log::WARN)<<pos<<" "<<IMREAD_SIZE;
|
Log(Log::WARN)<<pos<<" "<<IMREAD_SIZE;
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
|
return cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
cv::Mat tmpImage = cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
|
cv::Mat openImageYml(char* fileName)
|
||||||
|
{
|
||||||
|
cv::Mat image;
|
||||||
|
cv::FileStorage matf(fileName, cv::FileStorage::READ);
|
||||||
|
matf["image"]>>image;
|
||||||
|
|
||||||
|
if(matf.isOpened() && (!image.data || image.type() != CV_32FC1))
|
||||||
|
{
|
||||||
|
Log(Log::WARN)<<fileName<<" dose not contain a valid image";
|
||||||
|
matf.release();
|
||||||
|
return cv::Mat();
|
||||||
|
}
|
||||||
|
else if(!image.data)
|
||||||
|
{
|
||||||
|
Log(Log::WARN)<<"could not open "<<fileName<< "ignoreing";
|
||||||
|
matf.release();
|
||||||
|
return cv::Mat();
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<cv::Mat> loadImages(char** fileNames)
|
||||||
|
{
|
||||||
|
std::vector<cv::Mat> images;
|
||||||
|
for(size_t i = 0; fileNames[i]; ++i)
|
||||||
|
{
|
||||||
|
cv::Mat tmpImage;
|
||||||
|
const std::string str(fileNames[i]);
|
||||||
|
if(str.find(".mat") != std::string::npos)
|
||||||
|
openImageYml(fileNames[i]);
|
||||||
|
else
|
||||||
|
tmpImage = openImageImg(fileNames[i]);
|
||||||
if(tmpImage.data)
|
if(tmpImage.data)
|
||||||
images.push_back(tmpImage);
|
images.push_back(tmpImage);
|
||||||
else
|
else
|
||||||
@ -91,7 +129,7 @@ std::vector<cv::Mat> loadImages(char** fileNames)
|
|||||||
int perfromOperation(int operation, char** fileNames, const Config& config)
|
int perfromOperation(int operation, char** fileNames, const Config& config)
|
||||||
{
|
{
|
||||||
std::vector<cv::Mat> inImages;
|
std::vector<cv::Mat> inImages;
|
||||||
if(operation == CREATE_MAP || operation == APPLY_MAP)
|
if(operation == CREATE_MAP || operation == APPLY_MAP || operation == APPLY_CURVE)
|
||||||
{
|
{
|
||||||
inImages = loadImages(fileNames);
|
inImages = loadImages(fileNames);
|
||||||
|
|
||||||
@ -213,6 +251,69 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||||||
|
|
||||||
cv::imwrite(!config.output.empty() ? config.output : "out.png", out);
|
cv::imwrite(!config.output.empty() ? config.output : "out.png", out);
|
||||||
}
|
}
|
||||||
|
else if(operation == APPLY_CURVE)
|
||||||
|
{
|
||||||
|
if(config.curve.empty())
|
||||||
|
{
|
||||||
|
Log(Log::INFO)<<"a curve must be supplied";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::FileStorage fs(config.curve, cv::FileStorage::READ);
|
||||||
|
cv::Mat curve;
|
||||||
|
fs["curve"]>>curve;
|
||||||
|
if(!curve.data || curve.type() != CV_32FC1 || curve.rows != 2 || curve.cols < 3)
|
||||||
|
{
|
||||||
|
Log(Log::INFO)<<"invalid curve";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cvtColor(inImages[0], inImages[0], cv::COLOR_BGR2GRAY);
|
||||||
|
inImages[0].convertTo(inImages[0], CV_32F);
|
||||||
|
|
||||||
|
applyCurve(inImages[0], curve);
|
||||||
|
}
|
||||||
|
else if(operation == CREATE_CURVE)
|
||||||
|
{
|
||||||
|
cv::Mat curve = cv::Mat::zeros(2, 10, CV_32FC1);
|
||||||
|
float* keys = curve.ptr<float>(0);
|
||||||
|
float* values = curve.ptr<float>(1);
|
||||||
|
std::cout<<"Please type 10 coordinate pairs\n";
|
||||||
|
for(int i = 0; i < curve.cols; ++i)
|
||||||
|
{
|
||||||
|
std::cout<<i<<"> ";
|
||||||
|
double key;
|
||||||
|
double value;
|
||||||
|
|
||||||
|
std::cin>>key;
|
||||||
|
if(std::cin.fail())
|
||||||
|
{
|
||||||
|
std::cin.clear();
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::cin>>value;
|
||||||
|
if(std::cin.fail())
|
||||||
|
{
|
||||||
|
std::cin.clear();
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
keys[i] = key;
|
||||||
|
values[i] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < curve.cols; ++i)
|
||||||
|
std::cout<<keys[i]<<' '<<values[i]<<'\n';
|
||||||
|
|
||||||
|
cv::FileStorage fs(!config.output.empty() ? config.output : "curve.mat", cv::FileStorage::WRITE);
|
||||||
|
fs<<"curve"<<curve;
|
||||||
|
fs.release();
|
||||||
|
|
||||||
|
std::cout<<"Curve saved to "<<(!config.output.empty() ? config.output : "curve.mat")<<'\n';
|
||||||
|
}
|
||||||
else if(operation == EXIT)
|
else if(operation == EXIT)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -244,6 +345,7 @@ int main(int argc, char* argv[])
|
|||||||
if(operation < 0)
|
if(operation < 0)
|
||||||
{
|
{
|
||||||
Log(Log::ERROR)<<"An operation must be selected";
|
Log(Log::ERROR)<<"An operation must be selected";
|
||||||
|
Log(Log::INFO)<<"Possible operations: apply create curve mkcurve mkboard";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ret = perfromOperation(operation, config.commandsFiles+1, config);
|
ret = perfromOperation(operation, config.commandsFiles+1, config);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "matutils.h"
|
#include "matutils.h"
|
||||||
#include "drawing.h"
|
#include "drawing.h"
|
||||||
@ -186,8 +187,11 @@ cv::Mat simpleStich(const std::vector<RemapedImage>& images)
|
|||||||
{
|
{
|
||||||
if(images.size() < 1)
|
if(images.size() < 1)
|
||||||
return cv::Mat();
|
return cv::Mat();
|
||||||
|
else if(images.size() == 1)
|
||||||
|
return images[0].image;
|
||||||
|
|
||||||
cv::Size outputSize(0,0);
|
cv::Size outputSize(0,0);
|
||||||
|
cv::Point2i topLeft(std::numeric_limits<int>::max(),std::numeric_limits<int>::max());
|
||||||
for(auto& image : images)
|
for(auto& image : images)
|
||||||
{
|
{
|
||||||
if(outputSize.width < image.image.cols+image.origin.x)
|
if(outputSize.width < image.image.cols+image.origin.x)
|
||||||
@ -195,6 +199,11 @@ cv::Mat simpleStich(const std::vector<RemapedImage>& images)
|
|||||||
if(outputSize.height < image.image.rows+image.origin.y)
|
if(outputSize.height < image.image.rows+image.origin.y)
|
||||||
outputSize.height = image.image.rows+image.origin.y;
|
outputSize.height = image.image.rows+image.origin.y;
|
||||||
|
|
||||||
|
if(topLeft.x > image.origin.x)
|
||||||
|
topLeft.x = image.origin.x;
|
||||||
|
if(topLeft.y > image.origin.y)
|
||||||
|
topLeft.y = image.origin.y;
|
||||||
|
|
||||||
Log(Log::DEBUG)<<"image: "<<image.image.rows<<'x'<<image.image.cols<<" at "<<image.origin.x<<'x'<<image.origin.y;
|
Log(Log::DEBUG)<<"image: "<<image.image.rows<<'x'<<image.image.cols<<" at "<<image.origin.x<<'x'<<image.origin.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +217,10 @@ cv::Mat simpleStich(const std::vector<RemapedImage>& images)
|
|||||||
image.image.copyTo(out(roi));
|
image.image.copyTo(out(roi));
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
outputSize.width -= topLeft.x;
|
||||||
|
outputSize.height -= topLeft.y;
|
||||||
|
|
||||||
|
return out(cv::Rect(topLeft, outputSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat stich(const std::vector<RemapedImage>& images, bool seamAdjust)
|
cv::Mat stich(const std::vector<RemapedImage>& images, bool seamAdjust)
|
||||||
|
Reference in New Issue
Block a user