Compare commits
10 commits
8b643b03d3
...
0f5ae63b75
Author | SHA1 | Date | |
---|---|---|---|
|
0f5ae63b75 | ||
|
d658c0e593 | ||
|
83223788da | ||
|
7682906fb8 | ||
|
55ef1ee471 | ||
|
b5107bfc5a | ||
|
f2d5a905e8 | ||
|
6fa7e9eb9d | ||
|
f3d2a19781 | ||
|
2e3d0d2938 |
|
@ -35,12 +35,13 @@ struct Config
|
|||
bool quiet = false;
|
||||
bool interactive = false;
|
||||
bool simpleStich = false;
|
||||
float kFactor = 0;
|
||||
};
|
||||
|
||||
const char *argp_program_version = "0.2";
|
||||
const char *argp_program_bug_address = "<carl@uvos.xyz>";
|
||||
static char doc[] = "Program to determine the lubricant thikness on a curved surface.\n\
|
||||
Possible operations: apply create curve mkcurve mkboard";
|
||||
Possible operations: apply create curve mkcurve mkboard show";
|
||||
static char args_doc[] = "[OPERATION] IMAGE1 IMAGE2 ...";
|
||||
|
||||
static struct argp_option options[] =
|
||||
|
@ -56,6 +57,7 @@ static struct argp_option options[] =
|
|||
{"interactive", 'i', 0, 0, "interactivly process multiple commands" },
|
||||
{"simpe-stich", 'a', 0, 0, "Use non blending sticher" },
|
||||
{"curve", 'c', "File Name", 0, "curve file name" },
|
||||
{"kfactor", 'k', "Value", 0, "set the kfactor" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -78,7 +80,7 @@ error_t parse_opt (int key, char *arg, struct argp_state *state)
|
|||
config->norm.assign(arg);
|
||||
break;
|
||||
case 's':
|
||||
config->minSize=atol(arg);
|
||||
config->minSize=strtod(arg, nullptr);
|
||||
break;
|
||||
case 'r':
|
||||
config->harris = true;
|
||||
|
@ -98,6 +100,9 @@ error_t parse_opt (int key, char *arg, struct argp_state *state)
|
|||
case 'c':
|
||||
config->curve.assign(arg);
|
||||
break;
|
||||
case 'k':
|
||||
config->kFactor=strtod(arg, nullptr);
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
config->commandsFiles = &state->argv[state->next-1];
|
||||
state->next = state->argc;
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
#include "uvosunwrap/charuco.h"
|
||||
#include <opencv2/aruco/charuco.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
static constexpr unsigned int X_BOARD_SIZE = 18;
|
||||
static constexpr unsigned int Y_BOARD_SIZE = 10;
|
||||
|
||||
#include "uvosunwrap/log.h"
|
||||
|
||||
void createCharucoBoard(unsigned int size, const std::string& fileName)
|
||||
{
|
||||
|
@ -31,8 +28,68 @@ void createCharucoBoard(unsigned int size, const std::string& fileName)
|
|||
cv::aruco::CharucoBoard::create(X_BOARD_SIZE, Y_BOARD_SIZE, 0.03f, 0.02f,
|
||||
cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_250 ));
|
||||
cv::Mat charucoImage;
|
||||
board->draw(cv::Size((size*18)/10, size), charucoImage, 0, 1);
|
||||
cv::imwrite(fileName, charucoImage);
|
||||
double cellSize = size/(double)Y_BOARD_SIZE;
|
||||
board->draw(cv::Size((size*X_BOARD_SIZE)/Y_BOARD_SIZE, size), charucoImage, 0, 1);
|
||||
cv::Mat charucoImageWithBorder =
|
||||
cv::Mat::zeros(cv::Size(cellSize*(X_BOARD_SIZE+1), cellSize*(Y_BOARD_SIZE+2)), CV_8UC1);
|
||||
cv::Rect roi(cellSize, cellSize, charucoImage.cols, charucoImage.rows);
|
||||
charucoImage.copyTo(charucoImageWithBorder(roi));
|
||||
cv::imwrite(fileName, charucoImageWithBorder);
|
||||
}
|
||||
|
||||
static void seamAjust(std::vector<DetectedPoint>& detections)
|
||||
{
|
||||
int xMin = std::numeric_limits<int>::max();
|
||||
int xMax = std::numeric_limits<int>::min();
|
||||
|
||||
for(auto& point : detections)
|
||||
{
|
||||
if(point.coordinate.x > xMax)
|
||||
xMax = point.coordinate.x;
|
||||
else if(point.coordinate.x < xMin)
|
||||
xMin = point.coordinate.x;
|
||||
}
|
||||
|
||||
if(xMax - xMin < static_cast<int>(X_BOARD_SIZE/2))
|
||||
return;
|
||||
|
||||
Log(Log::DEBUG)<<"Image contains seam";
|
||||
|
||||
int rightMostPoint = 0;
|
||||
bool extantCol[X_BOARD_SIZE] = {0};
|
||||
for(auto& point : detections)
|
||||
{
|
||||
if(!extantCol[point.coordinate.x])
|
||||
extantCol[point.coordinate.x] = true;
|
||||
if(point.coordinate.x > rightMostPoint)
|
||||
rightMostPoint = point.coordinate.x;
|
||||
}
|
||||
|
||||
int leftCoordinate = 0;
|
||||
int maxDeadrange = 0;
|
||||
int deadRange = 0;
|
||||
for(unsigned int i = 0; i < X_BOARD_SIZE-1; ++i)
|
||||
{
|
||||
if(!extantCol[i])
|
||||
{
|
||||
++deadRange;
|
||||
if(extantCol[i+1] && maxDeadrange < deadRange)
|
||||
{
|
||||
leftCoordinate = i+1;
|
||||
maxDeadrange = deadRange;
|
||||
deadRange = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log(Log::DEBUG)<<"Left coordinate before seam "<<leftCoordinate
|
||||
<<" right most "<<rightMostPoint;
|
||||
|
||||
for(auto& point : detections)
|
||||
{
|
||||
if(point.coordinate.x < leftCoordinate)
|
||||
point.coordinate.x = point.coordinate.x + rightMostPoint + 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DetectedPoint> detectCharucoPoints(cv::Mat image, bool verbose)
|
||||
|
@ -86,6 +143,8 @@ std::vector<DetectedPoint> detectCharucoPoints(cv::Mat image, bool verbose)
|
|||
detections.push_back(DetectedPoint(charucoCorners[i], coordiante));
|
||||
}
|
||||
|
||||
seamAjust(detections);
|
||||
|
||||
return detections;
|
||||
}
|
||||
return std::vector<DetectedPoint>();
|
||||
|
|
49
src/main.cpp
49
src/main.cpp
|
@ -42,6 +42,7 @@ enum {
|
|||
APPLY_MAP,
|
||||
APPLY_CURVE,
|
||||
CREATE_CURVE,
|
||||
SHOW_IMAGE,
|
||||
EXIT
|
||||
};
|
||||
|
||||
|
@ -59,6 +60,8 @@ int selectOperation(char** opt)
|
|||
return CREATE_CURVE;
|
||||
else if(strcmp(opt[0], "mkboard" ) == 0)
|
||||
return CREATE_CHARUCO;
|
||||
else if(strcmp(opt[0], "show" ) == 0)
|
||||
return SHOW_IMAGE;
|
||||
else if(strcmp(opt[0], "exit" ) == 0)
|
||||
return EXIT;
|
||||
return -1;
|
||||
|
@ -92,7 +95,7 @@ cv::Mat openImageYml(char* fileName)
|
|||
cv::FileStorage matf(fileName, cv::FileStorage::READ);
|
||||
matf["image"]>>image;
|
||||
|
||||
if(matf.isOpened() && (!image.data || image.type() != CV_32FC1))
|
||||
if(matf.isOpened() && !image.data)
|
||||
{
|
||||
Log(Log::WARN)<<fileName<<" dose not contain a valid image";
|
||||
matf.release();
|
||||
|
@ -115,13 +118,19 @@ std::vector<cv::Mat> loadImages(char** fileNames)
|
|||
cv::Mat tmpImage;
|
||||
const std::string str(fileNames[i]);
|
||||
if(str.find(".mat") != std::string::npos)
|
||||
openImageYml(fileNames[i]);
|
||||
{
|
||||
Log(Log::DEBUG)<<__func__<<": "<<fileNames[i]<<" as YAML image";
|
||||
tmpImage = openImageYml(fileNames[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(Log::DEBUG)<<__func__<<": "<<fileNames[i]<<" as png image";
|
||||
tmpImage = openImageImg(fileNames[i]);
|
||||
}
|
||||
if(tmpImage.data)
|
||||
images.push_back(tmpImage);
|
||||
else
|
||||
Log(Log::WARN)<<"can not read image "<<i<<" from "<<fileNames[i]<<'\n';
|
||||
Log(Log::WARN)<<"can not read image "<<i<<" from "<<fileNames[i];
|
||||
}
|
||||
return images;
|
||||
}
|
||||
|
@ -129,7 +138,7 @@ std::vector<cv::Mat> loadImages(char** fileNames)
|
|||
int perfromOperation(int operation, char** fileNames, const Config& config)
|
||||
{
|
||||
std::vector<cv::Mat> inImages;
|
||||
if(operation == CREATE_MAP || operation == APPLY_MAP || operation == APPLY_CURVE)
|
||||
if(operation == CREATE_MAP || operation == APPLY_MAP || operation == APPLY_CURVE || operation == SHOW_IMAGE)
|
||||
{
|
||||
inImages = loadImages(fileNames);
|
||||
|
||||
|
@ -143,7 +152,7 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||
if(operation == CREATE_CHARUCO)
|
||||
{
|
||||
std::string fileName = config.output.empty() ? "out.png" : config.output;
|
||||
createCharucoBoard(config.size*14, fileName);
|
||||
createCharucoBoard(config.size*X_BOARD_SIZE, fileName);
|
||||
Log(Log::INFO)<<"Exported charuco map of size "<<config.size*14<<" to "<<fileName;
|
||||
return 0;
|
||||
}
|
||||
|
@ -202,7 +211,10 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||
map.outputCellSize = config.size;
|
||||
|
||||
if(!map.xMat.data)
|
||||
{
|
||||
Log(Log::ERROR)<<"could not load remap map from "<<std::string(fileNames[i])+".mat";
|
||||
return -1;
|
||||
}
|
||||
|
||||
RemapedImage norm;
|
||||
if(!config.norm.empty())
|
||||
|
@ -226,6 +238,15 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||
Log(Log::INFO)<<"Normalizeing image";
|
||||
if(norm.image.data) normalize(remaped.image, norm.image);
|
||||
|
||||
if(config.verbose)
|
||||
{
|
||||
cv::imshow( "Viewer", remaped.image );
|
||||
cv::waitKey(0);
|
||||
cv::imshow( "Viewer", remaped.angle);
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
applyKfactor(remaped.image, remaped.angle, config.kFactor);
|
||||
if(config.verbose)
|
||||
{
|
||||
cv::imshow("Viewer", remaped.image );
|
||||
|
@ -261,17 +282,23 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||
|
||||
cv::FileStorage fs(config.curve, cv::FileStorage::READ);
|
||||
cv::Mat curve;
|
||||
fs["curve"]>>curve;
|
||||
fs["cal"]>>curve;
|
||||
if(!curve.data || curve.type() != CV_32FC1 || curve.rows != 2 || curve.cols < 3)
|
||||
{
|
||||
Log(Log::INFO)<<"invalid curve";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(inImages[0].channels() > 1)
|
||||
cvtColor(inImages[0], inImages[0], cv::COLOR_BGR2GRAY);
|
||||
if(inImages[0].type() != CV_32FC1)
|
||||
inImages[0].convertTo(inImages[0], CV_32F);
|
||||
|
||||
Log(Log::DEBUG)<<"applyCurve";
|
||||
applyCurve(inImages[0], curve);
|
||||
cv::FileStorage fsO("out.mat", cv::FileStorage::WRITE);
|
||||
fsO<<"image"<<inImages[0];
|
||||
fsO.release();
|
||||
}
|
||||
else if(operation == CREATE_CURVE)
|
||||
{
|
||||
|
@ -323,6 +350,16 @@ int perfromOperation(int operation, char** fileNames, const Config& config)
|
|||
|
||||
std::cout<<"Curve saved to "<<(!config.output.empty() ? config.output : "curve.mat")<<'\n';
|
||||
}
|
||||
else if(operation == SHOW_IMAGE)
|
||||
{
|
||||
cv::namedWindow("Show Image", cv::WINDOW_NORMAL );
|
||||
for(size_t i = 0; i < inImages.size(); ++i)
|
||||
{
|
||||
cv::imshow("Show Image", inImages[i]);
|
||||
cv::waitKey(0);
|
||||
}
|
||||
cv::destroyWindow("Show Image");
|
||||
}
|
||||
else if(operation == EXIT)
|
||||
return -1;
|
||||
return 0;
|
||||
|
|
|
@ -178,7 +178,7 @@ bool findClosest(size_t& index, const cv::Point2f point, const std::vector<cv::P
|
|||
return found;
|
||||
}
|
||||
|
||||
void interpolateMissing(cv::Mat& mat)
|
||||
void interpolateMissingOnX(cv::Mat& mat)
|
||||
{
|
||||
assert(mat.type() == CV_32FC1);
|
||||
|
||||
|
@ -223,34 +223,48 @@ void interpolateMissing(cv::Mat& mat)
|
|||
}
|
||||
}
|
||||
|
||||
void fillMissing(cv::Mat& mat)
|
||||
void interpolateMissingOnY(cv::Mat& mat)
|
||||
{
|
||||
assert(mat.type() == CV_32FC1);
|
||||
|
||||
bool finished = true;
|
||||
for(int y = 0; y < mat.rows; y++)
|
||||
{
|
||||
float* col = mat.ptr<float>(y);
|
||||
for(int x = 0; x < mat.cols; ++x)
|
||||
{
|
||||
if(col[x] < 0 && col[x] > -2)
|
||||
for(int y = 0; y < mat.rows; y++)
|
||||
{
|
||||
if(y > 0 && mat.at<float>(y-1,x) >= 0)
|
||||
if(mat.at<float>(y,x) < 0)
|
||||
{
|
||||
col[x] = mat.at<float>(y-1,x);
|
||||
finished = false;
|
||||
}
|
||||
else if(y < mat.rows-1 && mat.at<float>(y+1,x) >= 0)
|
||||
int closestA = -1;
|
||||
int closestB = -1;
|
||||
int dist = std::numeric_limits<int>::max();
|
||||
for(int i = 0; i < mat.rows; i++)
|
||||
{
|
||||
col[x] = mat.at<float>(y+1,x);
|
||||
finished = false;
|
||||
if(i != closestA && mat.at<float>(i,x) >= 0 && abs(i-y) <= dist)
|
||||
{
|
||||
closestB = closestA;
|
||||
closestA = i;
|
||||
dist = abs(i-y);
|
||||
}
|
||||
if(col[x] > 0 && ((x+1 < mat.cols && col[x] > col[x+1]) || (x > 0 && col[x] < col[x-1])))
|
||||
col[x] = -2;
|
||||
}
|
||||
if(closestA < 0 || closestB < 0)
|
||||
{
|
||||
closestA = -1;
|
||||
closestB = -1;
|
||||
dist = std::numeric_limits<int>::max();
|
||||
for(int i = mat.rows-1; i >= 0; --i)
|
||||
{
|
||||
if(i != closestA && mat.at<float>(i,x) >= 0 && abs(i-y) <= dist)
|
||||
{
|
||||
closestB = closestA;
|
||||
closestA = i;
|
||||
dist = abs(i-y);
|
||||
}
|
||||
}
|
||||
}
|
||||
float slope = (mat.at<float>(closestB,x) - mat.at<float>(closestA,x))/(closestB-closestA);
|
||||
mat.at<float>(y,x) = mat.at<float>(closestA,x) - (closestA-y)*slope;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!finished) fillMissing(mat);
|
||||
}
|
||||
|
||||
bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi)
|
||||
|
@ -287,66 +301,25 @@ bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool deleteEmptyCols(cv::Mat& mat)
|
||||
{
|
||||
assert(mat.type() == CV_32FC1);
|
||||
|
||||
std::vector<size_t> cols;
|
||||
cols.reserve(mat.cols);
|
||||
|
||||
for(int x = 0; x < mat.cols; x++)
|
||||
{
|
||||
bool empty = true;
|
||||
for(int y = 0; y < mat.rows; y++)
|
||||
{
|
||||
if(mat.at<float>(x,y) > 0)
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty)
|
||||
cols.push_back(x);
|
||||
}
|
||||
|
||||
if(mat.cols < static_cast<long int>(cols.size()))
|
||||
{
|
||||
cv::Mat tmp(cv::Size(cols.size(), mat.rows), CV_32FC1);
|
||||
|
||||
for(auto& col : cols)
|
||||
{
|
||||
cv::Rect roi(cv::Point2i(col, 0), cv::Size(1, mat.rows));
|
||||
mat.copyTo(tmp(roi));
|
||||
}
|
||||
mat.release();
|
||||
mat = tmp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void removeSparseCols(cv::Mat& mat, bool front)
|
||||
void removeSparseCols(cv::Mat& mat, float reject, bool front)
|
||||
{
|
||||
assert(mat.type() == CV_32FC1);
|
||||
|
||||
int count = 0;
|
||||
for(int y = 0; y < mat.rows; ++y)
|
||||
{
|
||||
if(front && mat.at<float>(y,0) >= 0) ++count;
|
||||
else if(mat.at<float>(y,mat.cols-1) >= 0) ++count;
|
||||
if((front && mat.at<float>(y,0) >= 0) || (!front && mat.at<float>(y,mat.cols-1) >= 0))
|
||||
++count;
|
||||
}
|
||||
cv::Rect roi;
|
||||
bool rej = (count < mat.rows/2);
|
||||
bool rej = (count < mat.rows*reject);
|
||||
roi.x=front ? rej : 0;
|
||||
roi.y=0;
|
||||
roi.width = mat.cols - rej;
|
||||
roi.height = mat.rows;
|
||||
mat = mat(roi);
|
||||
if(rej)
|
||||
removeSparseCols(mat, front);
|
||||
removeSparseCols(mat, reject, front);
|
||||
}
|
||||
|
||||
static float linInterpolate(float A, float B, float x)
|
||||
|
|
|
@ -37,15 +37,13 @@ bool findClosest(size_t& index, const cv::Point2f point, const std::vector<cv::P
|
|||
|
||||
void thompsonTauTest(const std::vector<float>& in, std::vector<size_t>& outliers, float criticalValue);
|
||||
|
||||
void interpolateMissing(cv::Mat& mat);
|
||||
void interpolateMissingOnX(cv::Mat& mat);
|
||||
|
||||
void fillMissing(cv::Mat& mat);
|
||||
void interpolateMissingOnY(cv::Mat& mat);
|
||||
|
||||
bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi);
|
||||
|
||||
bool deleteEmptyCols(cv::Mat& mat);
|
||||
|
||||
void removeSparseCols(cv::Mat& mat, bool front);
|
||||
void removeSparseCols(cv::Mat& mat, float reject, bool front);
|
||||
|
||||
bool bilinearResize(const cv::Mat& inImage, cv::Mat& outImage, cv::Size size);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ static void sortIntoRemapMaps(const std::vector<DetectedPoint>& points, cv::Mat&
|
|||
xMat = -1;
|
||||
yMat = -1;
|
||||
|
||||
Log(Log::DEBUG)<<"Grid: "<<xGridSize<<'x'<<yGridSize;
|
||||
Log(Log::DEBUG)<<__func__<<"Grid: "<<xGridSize<<'x'<<yGridSize;
|
||||
|
||||
for(int y = 0; y < xMat.rows; y++)
|
||||
{
|
||||
|
@ -97,22 +97,20 @@ bool createRemapMap(const cv::Mat& image, RemapMap& out, const std::vector<Detec
|
|||
Log(Log::DEBUG)<<__func__<<": xMat raw\n"<<out.xMat;
|
||||
|
||||
int cols = out.xMat.cols;
|
||||
removeSparseCols(out.xMat, true);
|
||||
removeSparseCols(out.xMat, 0.75,true);
|
||||
out.topLeftCoordinate.x += cols-out.xMat.cols;
|
||||
removeSparseCols(out.xMat, false);
|
||||
removeSparseCols(out.yMat, true);
|
||||
removeSparseCols(out.yMat, false);
|
||||
removeSparseCols(out.xMat, 0.75, false);
|
||||
removeSparseCols(out.yMat, 0.75, true);
|
||||
removeSparseCols(out.yMat, 0.75, false);
|
||||
Log(Log::DEBUG)<<__func__<<": xMat rejcted\n"<<out.xMat;
|
||||
fillMissing(out.xMat);
|
||||
Log(Log::DEBUG)<<__func__<<": xMat filled\n"<<out.xMat;
|
||||
interpolateMissing(out.xMat);
|
||||
interpolateMissing(out.yMat);
|
||||
interpolateMissingOnY(out.xMat);
|
||||
interpolateMissingOnY(out.yMat);
|
||||
|
||||
sanityCheckMap(out.xMat, 0, image.cols-1, -1, -1);
|
||||
sanityCheckMap(out.yMat, 0, image.rows-1, -1, -1);
|
||||
fillMissing(out.xMat);
|
||||
interpolateMissing(out.xMat);
|
||||
interpolateMissing(out.yMat);
|
||||
interpolateMissingOnY(out.xMat);
|
||||
interpolateMissingOnY(out.yMat);
|
||||
sanityCheckMap(out.xMat, 0, image.cols-1, 0, image.cols-1);
|
||||
sanityCheckMap(out.yMat, 0, image.rows-1, 0, image.rows-1);
|
||||
|
||||
|
@ -159,17 +157,82 @@ RemapMap loadRemapMap(const std::string& fileName)
|
|||
return map;
|
||||
}
|
||||
|
||||
void applyKfactor(cv::Mat& image, const cv::Mat& angleMat, float kFactor)
|
||||
{
|
||||
assert(image.type() == CV_8UC1 && angleMat.type() == CV_32FC1);
|
||||
for(int y = 0; y < image.rows; y++)
|
||||
{
|
||||
uint8_t* colx = image.ptr<uint8_t>(y);
|
||||
const float* anglex = angleMat.ptr<float>(y);
|
||||
for(int x = 0; x < image.cols; x++)
|
||||
{
|
||||
int value = colx[x]*(1-(anglex[x]*kFactor));
|
||||
if(value < 0)
|
||||
value = 0;
|
||||
else if(value > 255)
|
||||
value = 255;
|
||||
colx[x] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void generateAngleMats(const cv::Mat& xMat, const cv::Mat& yMat, cv::Mat& greatestAngle)
|
||||
{
|
||||
std::cout<<xMat<<std::endl;
|
||||
greatestAngle.create(xMat.rows-1, xMat.cols-1, CV_32FC1);
|
||||
double max = 0;
|
||||
for(int y = 0; y < xMat.rows-1; y++)
|
||||
{
|
||||
for(int x = 0; x < xMat.cols-1; x++)
|
||||
{
|
||||
cv::Point2f pA(xMat.at<float>(y,x), yMat.at<float>(y,x));
|
||||
cv::Point2f pB(xMat.at<float>(y,x+1), yMat.at<float>(y,x+1));
|
||||
cv::Point2f pC(xMat.at<float>(y+1,x), yMat.at<float>(y+1,x));
|
||||
double normX = cv::norm(pA-pB);
|
||||
double normY = cv::norm(pA-pC);
|
||||
|
||||
if(normX > max)
|
||||
max = normX;
|
||||
if(normY > max)
|
||||
max = normY;
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < xMat.rows-1; y++)
|
||||
{
|
||||
for(int x = 0; x < xMat.cols-1; x++)
|
||||
{
|
||||
cv::Point2f pA(xMat.at<float>(y,x), yMat.at<float>(y,x));
|
||||
cv::Point2f pB(xMat.at<float>(y,x+1), yMat.at<float>(y,x+1));
|
||||
cv::Point2f pC(xMat.at<float>(y+1,x), yMat.at<float>(y+1,x));
|
||||
double normX = cv::norm(pA-pB);
|
||||
double normY = cv::norm(pA-pC);
|
||||
|
||||
greatestAngle.at<float>(y,x) = 1-(std::min(normX, normY)/max);
|
||||
|
||||
if(y == 0)
|
||||
Log(Log::DEBUG)<<greatestAngle.at<float>(y,x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemapedImage applyRemap(const cv::Mat& image, const RemapMap &map)
|
||||
{
|
||||
RemapedImage out;
|
||||
cv::Mat xMapResized;
|
||||
cv::Mat yMapResized;
|
||||
const cv::Size outputSize(map.outputCellSize*map.xMat.cols,map.outputCellSize*map.xMat.rows);
|
||||
cv::Rect noBorderRoi(map.outputCellSize/2, map.outputCellSize/2,
|
||||
outputSize.width-map.outputCellSize, outputSize.height-map.outputCellSize);
|
||||
|
||||
generateAngleMats(map.xMat, map.yMat, out.angle);
|
||||
cv::Mat angleResized;
|
||||
cv::resize(out.angle, angleResized, outputSize, cv::INTER_LINEAR);
|
||||
out.angle = angleResized(noBorderRoi);
|
||||
|
||||
cv::resize(map.xMat, xMapResized, outputSize, cv::INTER_LINEAR);
|
||||
cv::resize(map.yMat, yMapResized, outputSize, cv::INTER_LINEAR);
|
||||
cv::Rect noBorderRoi(map.outputCellSize/2, map.outputCellSize/2,
|
||||
outputSize.width-map.outputCellSize, outputSize.height-map.outputCellSize);
|
||||
|
||||
cv::Mat xMapRed = xMapResized(noBorderRoi);
|
||||
cv::Mat yMapRed = yMapResized(noBorderRoi);
|
||||
cv::remap(image, out.image, xMapRed, yMapRed, cv::INTER_LINEAR);
|
||||
|
@ -198,10 +261,10 @@ cv::Mat simpleStich(const std::vector<RemapedImage>& images)
|
|||
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)<<__func__<<"image: "<<image.image.rows<<'x'<<image.image.cols<<" at "<<image.origin.x<<'x'<<image.origin.y;
|
||||
}
|
||||
|
||||
Log(Log::DEBUG)<<"outputSize: "<<outputSize;
|
||||
Log(Log::DEBUG)<<__func__<<"outputSize: "<<outputSize;
|
||||
|
||||
cv::Mat out(outputSize, images[0].image.type(), cv::Scalar::all(0));
|
||||
|
||||
|
@ -219,9 +282,13 @@ cv::Mat simpleStich(const std::vector<RemapedImage>& images)
|
|||
|
||||
cv::Mat stich(std::vector<RemapedImage>& images, bool seamAdjust)
|
||||
{
|
||||
assert(images.size() > 0);
|
||||
|
||||
for(auto& image : images)
|
||||
assert(image.image.type() == CV_8UC3 || image.image.type() == CV_8UC1);
|
||||
|
||||
Log(Log::DEBUG)<<__func__<<" got "<<images.size()<<" of type "<<images[0].image.type()<<" size "<<images[0].image.size();
|
||||
|
||||
for(auto& image : images)
|
||||
{
|
||||
if(image.image.type() == CV_8UC1)
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <opencv2/core/ocl.hpp>
|
||||
#include "detectedpoint.h"
|
||||
|
||||
static constexpr unsigned int X_BOARD_SIZE = 20;
|
||||
static constexpr unsigned int Y_BOARD_SIZE = 12;
|
||||
|
||||
void createCharucoBoard(unsigned int size, const std::string& fileName);
|
||||
|
||||
std::vector<DetectedPoint> detectCharucoPoints(cv::Mat image, bool verbose = true);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
struct RemapedImage
|
||||
{
|
||||
cv::Mat image;
|
||||
cv::Mat angle;
|
||||
cv::Point2i origin;
|
||||
};
|
||||
|
||||
|
@ -44,5 +45,7 @@ bool createRemapMap(const cv::Mat& image, RemapMap& out, const std::vector<Detec
|
|||
|
||||
RemapedImage applyRemap(const cv::Mat& image, const RemapMap &map);
|
||||
|
||||
void applyKfactor(cv::Mat& image ,const cv::Mat& angleMat, float kFactor);
|
||||
|
||||
cv::Mat stich(std::vector<RemapedImage>& images, bool seamAdjust = false);
|
||||
cv::Mat simpleStich(const std::vector<RemapedImage>& images);
|
||||
|
|
Loading…
Reference in a new issue