diff --git a/src/argpopt.h b/src/argpopt.h index 7a1828e..1a40e30 100644 --- a/src/argpopt.h +++ b/src/argpopt.h @@ -35,13 +35,12 @@ 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 = ""; static char doc[] = "Program to determine the lubricant thikness on a curved surface.\n\ -Possible operations: apply create curve mkcurve mkboard show"; +Possible operations: apply create curve mkcurve mkboard"; static char args_doc[] = "[OPERATION] IMAGE1 IMAGE2 ..."; static struct argp_option options[] = @@ -57,7 +56,6 @@ 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 } }; @@ -80,7 +78,7 @@ error_t parse_opt (int key, char *arg, struct argp_state *state) config->norm.assign(arg); break; case 's': - config->minSize=strtod(arg, nullptr); + config->minSize=atol(arg); break; case 'r': config->harris = true; @@ -100,9 +98,6 @@ 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; diff --git a/src/charuco.cpp b/src/charuco.cpp index cd58672..14f8b2b 100644 --- a/src/charuco.cpp +++ b/src/charuco.cpp @@ -20,76 +20,19 @@ #include "uvosunwrap/charuco.h" #include #include -#include "uvosunwrap/log.h" + +static constexpr unsigned int X_BOARD_SIZE = 18; +static constexpr unsigned int Y_BOARD_SIZE = 10; + void createCharucoBoard(unsigned int size, const std::string& fileName) { cv::Ptr board = 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; - 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& detections) -{ - int xMin = std::numeric_limits::max(); - int xMax = std::numeric_limits::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(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 "<draw(cv::Size((size*18)/10, size), charucoImage, 0, 1); + cv::imwrite(fileName, charucoImage); } std::vector detectCharucoPoints(cv::Mat image, bool verbose) @@ -143,8 +86,6 @@ std::vector detectCharucoPoints(cv::Mat image, bool verbose) detections.push_back(DetectedPoint(charucoCorners[i], coordiante)); } - seamAjust(detections); - return detections; } return std::vector(); diff --git a/src/main.cpp b/src/main.cpp index e61d8bd..3ec1c41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,7 +42,6 @@ enum { APPLY_MAP, APPLY_CURVE, CREATE_CURVE, - SHOW_IMAGE, EXIT }; @@ -60,8 +59,6 @@ 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; @@ -95,7 +92,7 @@ cv::Mat openImageYml(char* fileName) cv::FileStorage matf(fileName, cv::FileStorage::READ); matf["image"]>>image; - if(matf.isOpened() && !image.data) + if(matf.isOpened() && (!image.data || image.type() != CV_32FC1)) { Log(Log::WARN)< loadImages(char** fileNames) cv::Mat tmpImage; const std::string str(fileNames[i]); if(str.find(".mat") != std::string::npos) - { - Log(Log::DEBUG)<<__func__<<": "< loadImages(char** fileNames) int perfromOperation(int operation, char** fileNames, const Config& config) { std::vector inImages; - if(operation == CREATE_MAP || operation == APPLY_MAP || operation == APPLY_CURVE || operation == SHOW_IMAGE) + if(operation == CREATE_MAP || operation == APPLY_MAP || operation == APPLY_CURVE) { inImages = loadImages(fileNames); @@ -152,7 +143,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*X_BOARD_SIZE, fileName); + createCharucoBoard(config.size*14, fileName); Log(Log::INFO)<<"Exported charuco map of size "<>curve; + fs["curve"]>>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) + cvtColor(inImages[0], inImages[0], cv::COLOR_BGR2GRAY); 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"<(y); + for(int x = 0; x < mat.cols; ++x) { - if(mat.at(y,x) < 0) + if(col[x] < 0 && col[x] > -2) { - int closestA = -1; - int closestB = -1; - int dist = std::numeric_limits::max(); - for(int i = 0; i < mat.rows; i++) + if(y > 0 && mat.at(y-1,x) >= 0) { - if(i != closestA && mat.at(i,x) >= 0 && abs(i-y) <= dist) - { - closestB = closestA; - closestA = i; - dist = abs(i-y); - } + col[x] = mat.at(y-1,x); + finished = false; } - if(closestA < 0 || closestB < 0) + else if(y < mat.rows-1 && mat.at(y+1,x) >= 0) { - closestA = -1; - closestB = -1; - dist = std::numeric_limits::max(); - for(int i = mat.rows-1; i >= 0; --i) - { - if(i != closestA && mat.at(i,x) >= 0 && abs(i-y) <= dist) - { - closestB = closestA; - closestA = i; - dist = abs(i-y); - } - } + col[x] = mat.at(y+1,x); + finished = false; } - float slope = (mat.at(closestB,x) - mat.at(closestA,x))/(closestB-closestA); - mat.at(y,x) = mat.at(closestA,x) - (closestA-y)*slope; + if(col[x] > 0 && ((x+1 < mat.cols && col[x] > col[x+1]) || (x > 0 && col[x] < col[x-1]))) + col[x] = -2; } } } + if(!finished) fillMissing(mat); } bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi) @@ -301,25 +287,66 @@ bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi) return true; } -void removeSparseCols(cv::Mat& mat, float reject, bool front) +bool deleteEmptyCols(cv::Mat& mat) +{ + assert(mat.type() == CV_32FC1); + + std::vector 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(x,y) > 0) + { + empty = false; + break; + } + } + + if(!empty) + cols.push_back(x); + } + + if(mat.cols < static_cast(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) { assert(mat.type() == CV_32FC1); int count = 0; for(int y = 0; y < mat.rows; ++y) { - if((front && mat.at(y,0) >= 0) || (!front && mat.at(y,mat.cols-1) >= 0)) - ++count; + if(front && mat.at(y,0) >= 0) ++count; + else if(mat.at(y,mat.cols-1) >= 0) ++count; } cv::Rect roi; - bool rej = (count < mat.rows*reject); + bool rej = (count < mat.rows/2); roi.x=front ? rej : 0; roi.y=0; roi.width = mat.cols - rej; roi.height = mat.rows; mat = mat(roi); if(rej) - removeSparseCols(mat, reject, front); + removeSparseCols(mat, front); } static float linInterpolate(float A, float B, float x) diff --git a/src/matutils.h b/src/matutils.h index 6020967..3e96024 100644 --- a/src/matutils.h +++ b/src/matutils.h @@ -37,13 +37,15 @@ bool findClosest(size_t& index, const cv::Point2f point, const std::vector& in, std::vector& outliers, float criticalValue); -void interpolateMissingOnX(cv::Mat& mat); +void interpolateMissing(cv::Mat& mat); -void interpolateMissingOnY(cv::Mat& mat); +void fillMissing(cv::Mat& mat); bool findDeadSpace(const cv::Mat& mat, cv::Rect& roi); -void removeSparseCols(cv::Mat& mat, float reject, bool front); +bool deleteEmptyCols(cv::Mat& mat); + +void removeSparseCols(cv::Mat& mat, bool front); bool bilinearResize(const cv::Mat& inImage, cv::Mat& outImage, cv::Size size); diff --git a/src/unwrap.cpp b/src/unwrap.cpp index 3b7b113..707ba5d 100644 --- a/src/unwrap.cpp +++ b/src/unwrap.cpp @@ -66,7 +66,7 @@ static void sortIntoRemapMaps(const std::vector& points, cv::Mat& xMat = -1; yMat = -1; - Log(Log::DEBUG)<<__func__<<"Grid: "<(y); - const float* anglex = angleMat.ptr(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<(y,x), yMat.at(y,x)); - cv::Point2f pB(xMat.at(y,x+1), yMat.at(y,x+1)); - cv::Point2f pC(xMat.at(y+1,x), yMat.at(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(y,x), yMat.at(y,x)); - cv::Point2f pB(xMat.at(y,x+1), yMat.at(y,x+1)); - cv::Point2f pC(xMat.at(y+1,x), yMat.at(y+1,x)); - double normX = cv::norm(pA-pB); - double normY = cv::norm(pA-pC); - - greatestAngle.at(y,x) = 1-(std::min(normX, normY)/max); - - if(y == 0) - Log(Log::DEBUG)<(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); @@ -261,10 +198,10 @@ cv::Mat simpleStich(const std::vector& images) if(topLeft.y > image.origin.y) topLeft.y = image.origin.y; - Log(Log::DEBUG)<<__func__<<"image: "<& images) cv::Mat stich(std::vector& 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 "< #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 detectCharucoPoints(cv::Mat image, bool verbose = true); diff --git a/src/uvosunwrap/unwrap.h b/src/uvosunwrap/unwrap.h index 185abbf..0bcc383 100644 --- a/src/uvosunwrap/unwrap.h +++ b/src/uvosunwrap/unwrap.h @@ -25,7 +25,6 @@ struct RemapedImage { cv::Mat image; - cv::Mat angle; cv::Point2i origin; }; @@ -45,7 +44,5 @@ bool createRemapMap(const cv::Mat& image, RemapMap& out, const std::vector& images, bool seamAdjust = false); cv::Mat simpleStich(const std::vector& images);