add charuco point detection method
This commit is contained in:
229
unwrap.cpp
229
unwrap.cpp
@ -5,7 +5,6 @@
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <opencv2/features2d.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "matutils.h"
|
||||
@ -29,7 +28,7 @@ static std::vector< std::vector<cv::Point2f > > sortPointsIntoRows(std::vector<c
|
||||
Log(Log::DEBUG)<<"topLeft "<<topLeft.x<<' '<<topLeft.y;
|
||||
Log(Log::DEBUG)<<"bottomRight "<<bottomRight.x<<' '<<bottomRight.y;
|
||||
|
||||
float fuzz = (bottomRight.x-topLeft.x)*0.01f;
|
||||
float fuzz = (bottomRight.x-topLeft.x)*0.05f;
|
||||
|
||||
for(size_t i = 0; i < points.size(); ++i)
|
||||
{
|
||||
@ -352,115 +351,145 @@ static void generateRemapMaps(const DisplacmentMap& map, cv::Mat& xMat, cv::Mat&
|
||||
Log(Log::INFO)<<__func__<<": yMat \n"<<yMat;
|
||||
}
|
||||
|
||||
static std::vector<cv::Point2f> detectPoints(cv::Mat& image, const cv::Mat& mask,
|
||||
int blockSize = 5, int apature = 5, float detectorParameter = 0.01,
|
||||
float minSize = 7, bool verbose = false)
|
||||
static void generateRemapMaps(const std::vector<cv::Point2f>& points, const std::vector<cv::Point2i>& coordinates, cv::Mat& xMat, cv::Mat& yMat)
|
||||
{
|
||||
cv::Mat gray;
|
||||
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
|
||||
|
||||
//detect corners
|
||||
cv::Mat corners;
|
||||
cv::cornerHarris(gray, corners, blockSize, apature, detectorParameter);
|
||||
cv::normalize(corners, corners, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
|
||||
cv::convertScaleAbs( corners, corners );
|
||||
cv::threshold(corners, corners, 50, 255, cv::THRESH_BINARY);
|
||||
cv::Mat cornersMasked;
|
||||
if(mask.size == corners.size) corners.copyTo(cornersMasked, mask);
|
||||
else corners.copyTo(cornersMasked);
|
||||
|
||||
if(verbose)
|
||||
if(points.size() < 6 || coordinates.size() != points.size())
|
||||
{
|
||||
cv::imshow( "Viewer", cornersMasked );
|
||||
cv::waitKey(0);
|
||||
Log(Log::ERROR)<<__func__<<": at least 6 points are needed";
|
||||
return;
|
||||
}
|
||||
|
||||
//get middle of corners
|
||||
cv::SimpleBlobDetector::Params blobParams;
|
||||
blobParams.filterByArea = true;
|
||||
blobParams.minArea = minSize;
|
||||
blobParams.maxArea = 500;
|
||||
blobParams.filterByColor = false;
|
||||
blobParams.blobColor = 255;
|
||||
blobParams.filterByInertia = false;
|
||||
blobParams.filterByConvexity = false;
|
||||
cv::Ptr<cv::SimpleBlobDetector> blobDetector = cv::SimpleBlobDetector::create(blobParams);
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
blobDetector->detect(cornersMasked, keypoints);
|
||||
int xMin = std::numeric_limits<int>::max();
|
||||
int xMax = std::numeric_limits<int>::min();
|
||||
int yMin = std::numeric_limits<int>::max();
|
||||
int yMax = std::numeric_limits<int>::min();
|
||||
|
||||
std::vector<cv::Point2f> points;
|
||||
cv::KeyPoint::convert(keypoints, points);
|
||||
for(auto& point : coordinates)
|
||||
{
|
||||
Log(Log::DEBUG)<<"point: "<<point.x<<'x'<<point.y;
|
||||
|
||||
if(point.x > xMax) xMax = point.x;
|
||||
else if(point.x < xMin) xMin = point.x;
|
||||
if(point.y > yMax) yMax = point.y;
|
||||
else if(point.y < yMin) yMin = point.y;
|
||||
}
|
||||
|
||||
return points;
|
||||
size_t xGridSize = xMax-xMin+1;
|
||||
size_t yGridSize = yMax-yMin+1;
|
||||
xMat = cv::Mat::zeros(cv::Size(xGridSize, yGridSize), CV_32FC1);
|
||||
yMat = cv::Mat::zeros(cv::Size(xGridSize, yGridSize), CV_32FC1);
|
||||
|
||||
Log(Log::DEBUG)<<"Grid: "<<xGridSize<<'x'<<yGridSize;
|
||||
|
||||
for(int y = 0; y < xMat.rows; y++)
|
||||
{
|
||||
float* colx = xMat.ptr<float>(y);
|
||||
float* coly = yMat.ptr<float>(y);
|
||||
for(int x = 0; x < xMat.cols; x++)
|
||||
{
|
||||
colx[x] = -1;
|
||||
coly[x] = -1;
|
||||
for(size_t i = 0; i < coordinates.size(); ++i)
|
||||
{
|
||||
if(coordinates[i] == cv::Point2i(x+xMin,y+yMin))
|
||||
{
|
||||
colx[x] = points[i].x;
|
||||
coly[x] = points[i].y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Log(Log::DEBUG)<<__func__<<": xMat raw\n"<<xMat;
|
||||
removeSparseCollums(xMat);
|
||||
removeSparseCollums(yMat);
|
||||
Log(Log::DEBUG)<<__func__<<": xMat rejcted\n"<<xMat;
|
||||
fillMissing(xMat);
|
||||
Log(Log::DEBUG)<<__func__<<": xMat filled\n"<<xMat;
|
||||
interpolateMissing(xMat);
|
||||
Log(Log::DEBUG)<<__func__<<": yMat raw \n"<<yMat;
|
||||
interpolateMissing(yMat);
|
||||
Log(Log::INFO)<<__func__<<": xMat \n"<<xMat;
|
||||
Log(Log::INFO)<<__func__<<": yMat \n"<<yMat;
|
||||
}
|
||||
|
||||
bool createRemapMap(cv::Mat& image, const std::string& fileName, const cv::Mat& mask,
|
||||
int blockSize, int apature, float detectorParameter, float minSize,
|
||||
bool verbose)
|
||||
bool createRemapMap(cv::Mat& image, std::vector<cv::Point2f> points, const std::vector<cv::Point2i>& coordinates,
|
||||
const std::string& fileName, bool verbose)
|
||||
{
|
||||
std::vector<cv::Point2f > points = detectPoints(image, mask, blockSize, apature, detectorParameter, minSize, verbose);
|
||||
if(verbose) std::cout<<"Found "<<points.size()<<" points\n";
|
||||
if(points.size() < 8)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, insufficant points detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector< std::vector<cv::Point2f > > rows = sortPointsIntoRows(points);
|
||||
if(verbose) std::cout<<"Found "<<rows.size()<<" rows\n";
|
||||
if(rows.size() < 2)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, insufficant rows detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector< cv::RotatedRect > ellipses = fitEllipses(rows);
|
||||
if(verbose) Log(Log::INFO)<<"Found "<<ellipses.size()<<" ellipses. rows reduced to "<<rows.size();
|
||||
if(ellipses.size() < 3)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, insufficant ellipses detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::Mat pointsMat = cv::Mat::zeros(image.size(), CV_8UC3);
|
||||
drawRows(pointsMat, rows);
|
||||
drawEllipses(pointsMat, ellipses);
|
||||
cv::imshow( "Viewer", pointsMat );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
sanityCheckElipses(rows, ellipses);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::Mat pointsMat = cv::Mat::zeros(image.size(), CV_8UC3);
|
||||
drawRows(pointsMat, rows);
|
||||
drawEllipses(pointsMat, ellipses);
|
||||
cv::imshow( "Viewer", pointsMat );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
DisplacmentMap dispMap = calcDisplacementMap(rows, ellipses);
|
||||
if(dispMap.destination.size() < 2)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, unable to calculate destination points";
|
||||
return false;
|
||||
}
|
||||
|
||||
cv::Mat dispPointsDest = cv::Mat::zeros(cv::Size(cv::Size(1000,1000)), CV_8UC3);
|
||||
drawRows(dispPointsDest, dispMap.destination);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::imshow( "Viewer", dispPointsDest );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
cv::Mat xMat;
|
||||
cv::Mat yMat;
|
||||
generateRemapMaps(dispMap, xMat, yMat);
|
||||
|
||||
if(coordinates.empty())
|
||||
{
|
||||
std::vector< std::vector<cv::Point2f > > rows = sortPointsIntoRows(points);
|
||||
Log(Log::INFO)<<"Found "<<rows.size()<<" rows";
|
||||
if(rows.size() < 2)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, insufficant rows detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::Mat pointsMat = cv::Mat::zeros(image.size(), CV_8UC3);
|
||||
drawRows(pointsMat, rows);
|
||||
cv::imshow( "Viewer", pointsMat );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
std::vector< cv::RotatedRect > ellipses = fitEllipses(rows);
|
||||
Log(Log::INFO)<<"Found "<<ellipses.size()<<" ellipses. rows reduced to "<<rows.size();
|
||||
if(ellipses.size() < 3)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, insufficant ellipses detected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::Mat pointsMat = cv::Mat::zeros(image.size(), CV_8UC3);
|
||||
drawRows(pointsMat, rows);
|
||||
drawEllipses(pointsMat, ellipses);
|
||||
cv::imshow( "Viewer", pointsMat );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
sanityCheckElipses(rows, ellipses);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::Mat pointsMat = cv::Mat::zeros(image.size(), CV_8UC3);
|
||||
drawRows(pointsMat, rows);
|
||||
drawEllipses(pointsMat, ellipses);
|
||||
cv::imshow( "Viewer", pointsMat );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
|
||||
DisplacmentMap dispMap = calcDisplacementMap(rows, ellipses);
|
||||
if(dispMap.destination.size() < 2)
|
||||
{
|
||||
Log(Log::ERROR)<<"Error creating map, unable to calculate destination points";
|
||||
return false;
|
||||
}
|
||||
|
||||
cv::Mat dispPointsDest = cv::Mat::zeros(cv::Size(cv::Size(1000,1000)), CV_8UC3);
|
||||
drawRows(dispPointsDest, dispMap.destination);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
cv::imshow( "Viewer", dispPointsDest );
|
||||
cv::waitKey(0);
|
||||
}
|
||||
generateRemapMaps(dispMap, xMat, yMat);
|
||||
}
|
||||
else
|
||||
{
|
||||
generateRemapMaps(points, coordinates, xMat, yMat);
|
||||
}
|
||||
|
||||
sanityCheckMap(xMat, 0, image.cols-1, -1, -1);
|
||||
sanityCheckMap(yMat, 0, image.rows-1, -1, -1);
|
||||
fillMissing(xMat);
|
||||
@ -525,7 +554,7 @@ void applyRemap(cv::Mat& image, cv::Mat& out, const cv::Mat& xmap, const cv::Mat
|
||||
cv::Rect roi;
|
||||
cv::Mat xMapRed;
|
||||
cv::Mat yMapRed;
|
||||
if(findDeadSpace(xMapResized, roi))
|
||||
if(!findDeadSpace(xMapResized, roi))
|
||||
{
|
||||
xMapRed = xMapResized(roi);
|
||||
yMapRed = yMapResized(roi);
|
||||
|
Reference in New Issue
Block a user