pull/2828/head
Vladyslav Selotkin 4 years ago
parent 5e44fce1f6
commit 3c4ea4e042
  1. 2
      modules/structured_light/include/opencv2/structured_light/slmono_calibration.hpp
  2. 7
      modules/structured_light/include/opencv2/structured_light/slmono_utils.hpp
  3. 6
      modules/structured_light/samples/calibrate_example.cpp
  4. 16
      modules/structured_light/samples/sl_example.cpp
  5. 67
      modules/structured_light/src/slmono.cpp
  6. 22
      modules/structured_light/src/slmono_calibration.cpp
  7. 34
      modules/structured_light/src/slmono_utils.cpp

@ -51,6 +51,8 @@ void fromMatToVector(InputArray pts, OutputArrayOfArrays v);
void loadCalibrationData(string filename, OutputArray cameraIntrinsic, OutputArray projectorIntrinsic, OutputArray cameraDistortion, OutputArray projectorDistortion, OutputArray rotation, OutputArray translation);
Point2f back(Point2f point, double fx, double fy, double ux, double uy);
void distortImage(InputArray input, InputArray camMat, InputArray dist, OutputArray output);
}

@ -35,6 +35,13 @@ namespace structured_light{
void savePointCloud(InputArray phase, string filename); //filter image from outliers and save as txt
void circshift(OutputArray out, InputArray in, int xdim, int ydim, bool isFftshift);
void createGrid(OutputArray output, Size size);
void wrapSin(InputArray img, OutputArray out);
void wrapCos(InputArray img, OutputArray out);
void Laplacian(InputArray img, InputArray grid, OutputArray out, int flag);
void computeDelta(InputArray img, InputArray grid, OutputArray out);
void fft2(InputArray in, OutputArray complexI);
}
}

@ -15,8 +15,8 @@ static const char* keys =
enum calibrationPattern{CHESSBOARD, CIRCLES_GRID, ASYMETRIC_CIRCLES_GRID};
int calibrate( int argc, char **argv )
{
int main( int argc, char **argv )
{
VideoCapture cap(CAP_PVAPI);
Mat frame;
@ -58,7 +58,7 @@ int calibrate( int argc, char **argv )
structured_light::createObjectPoints(tempCam, camSettings.patternSize,
camSettings.squareSize, camSettings.patternType);
structured_light::createProjectorObjectPoints(tempProj, projSettings.patternSize,
projSettings.squareSize, projSettings.patternType);

@ -21,7 +21,7 @@ void readImages(vector<string> refs_files, vector<string> imgs_files, OutputArra
vector<Mat>& refs_ = *(vector<Mat>*) refs.getObj();
vector<Mat>& imgs_ = *(vector<Mat>*) imgs.getObj();
for(auto i = 0; i < refs_files.size(); i++)
for(uint i = 0; i < refs_files.size(); i++)
{
auto img = imread(refs_files[i], IMREAD_COLOR);
cvtColor(img, img, COLOR_RGBA2GRAY);
@ -35,7 +35,7 @@ void readImages(vector<string> refs_files, vector<string> imgs_files, OutputArra
}
}
void captureImages(InputArrayOfArrays patterns, OutputArrayOfArrays refs, OutputArrayOfArrays imgs, bool isCaptureRefs)
void captureImages(InputArrayOfArrays patterns, OutputArrayOfArrays refs, OutputArrayOfArrays imgs, cv::Size projector_size, bool isCaptureRefs)
{
vector<Mat>& patterns_ = *(vector<Mat>*)patterns.getObj();
vector<Mat>& refs_ = *(vector<Mat>*)refs.getObj();
@ -54,7 +54,7 @@ void captureImages(InputArrayOfArrays patterns, OutputArrayOfArrays refs, Output
if (isCaptureRefs)
{
for(auto i = 0; i < patterns_.size(); i++)
for(uint i = 0; i < patterns_.size(); i++)
{
Mat frame;
cap >> frame;
@ -81,7 +81,7 @@ void captureImages(InputArrayOfArrays patterns, OutputArrayOfArrays refs, Output
imshow( "Display pattern", pause);
waitKey();
for(auto i = 0; i < patterns_.size(); i++)
for(uint i = 0; i < patterns_.size(); i++)
{
Mat frame;
cap >> frame;
@ -103,7 +103,7 @@ void captureImages(InputArrayOfArrays patterns, OutputArrayOfArrays refs, Output
}
}
int main()
int main( int argc, char **argv )
{
int imgNum = 4;
cv::Size projector_size = cv::Size(512, 512);
@ -112,16 +112,16 @@ int main()
structured_light::StructuredLightMono sl(projector_size, imgNum, 37, alg_type);
sl.generatePatterns(patterns, 0.3);
sl.generatePatterns(patterns, 0.3f);
captureImages(patterns, refs, imgs);
captureImages(patterns, refs, imgs, projector_size, true);
string filename = "../images/calibration_result.xml";
Mat cameraMatrix, projectorMatrix, cameraDistortion, projectorDistortion, rotation, translation;
structured_light::loadCalibrationData(filename, cameraMatrix, projectorMatrix, cameraDistortion, projectorDistortion, rotation, translation);
for (unsigned i = 0; i < refs.size(); i++)
for (uint i = 0; i < refs.size(); i++)
{
Mat undistored;
undistort(refs[i], undistored, cameraMatrix, cameraDistortion);

@ -5,35 +5,13 @@
namespace cv {
namespace structured_light {
//read reference images and object images from specified files
//void StructuredLightMono::readImages(vector<string> refs_files, vector<string> imgs_files, OutputArrayOfArrays refs, OutputArrayOfArrays imgs)
//{
// vector<Mat>& refs_ = *(vector<Mat>*) refs.getObj();
// vector<Mat>& imgs_ = *(vector<Mat>*) imgs.getObj();
//
// for(auto i = 0; i < refs_files.size(); i++)
// {
// auto img = imread(refs_files[i], IMREAD_COLOR);
// cvtColor(img, img, COLOR_RGBA2GRAY);
// img.convertTo(img, CV_32FC1, 1.f/255);
// refs_.push_back(img);
//
// img = imread(imgs_files[i], IMREAD_COLOR);
// cvtColor(img, img, COLOR_RGBA2GRAY);
// img.convertTo(img, CV_32FC1, 1.f/255);
// imgs_.push_back(img);
// }
//}
//main phase unwrapping function
void StructuredLightMono::unwrapPhase(InputOutputArrayOfArrays refs, InputOutputArrayOfArrays imgs, OutputArray out)
{
if (alg_type == "PCG")
{
computePhasePCG(refs, imgs, out);
}
}
else if (alg_type == "TPU")
{
computePhaseTPU(refs, imgs, out);
@ -42,17 +20,15 @@ void StructuredLightMono::unwrapPhase(InputOutputArrayOfArrays refs, InputOutput
//algorithm for shadow removing from images
void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutputArrayOfArrays imgs)
{
{
vector<Mat>& refs_ = *(vector<Mat>*)refs.getObj();
vector<Mat>& imgs_ = *(vector<Mat>*)imgs.getObj();
Size size = refs_[0].size();
Mat mean(size, CV_32FC1);
for( int i = 0; i < size.height; ++i )
{
for( int j = 0; j < size.width; ++j )
{
{
float average = 0;
for (int k = 0; k < imgs_.size(); k++)
{
@ -61,13 +37,11 @@ void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutp
mean.at<float>(i, j) = average/imgs_.size();
}
}
mean.convertTo(mean, CV_32FC1);
Mat shadowMask;
threshold(mean, shadowMask, 0.05, 1, 0);
for (int k = 0; k < imgs_.size(); k++)
{
{
multiply(shadowMask, refs_[k], refs_[k]);
multiply(shadowMask, imgs_[k], imgs_[k]);
}
@ -77,20 +51,17 @@ void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutp
//TPU algorithm requires low and high frequency patterns
void StructuredLightMono::generatePatterns(OutputArrayOfArrays patterns, float stripes_angle)
{
{
vector<Mat>& patterns_ = *(vector<Mat>*) patterns.getObj();
float phi = (float)projector_size.width/(float)stripes_num;
float delta = 2*(float)CV_PI/phi;
float shift = 2*(float)CV_PI/pattern_num;
Mat pattern(projector_size, CV_32FC1, Scalar(0));
for(auto k = 0; k < pattern_num; k++)
for(int k = 0; k < pattern_num; k++)
{
for( int i = 0; i < projector_size.height; ++i )
for(uint i = 0; i < projector_size.height; ++i )
{
for( int j = 0; j < projector_size.width; ++j )
for(uint j = 0; j < projector_size.width; ++j )
{
pattern.at<float>(i, j) = (cos((stripes_angle*i+(1-stripes_angle)*j)*delta+k*shift) + 1)/2;
}
@ -98,17 +69,15 @@ void StructuredLightMono::generatePatterns(OutputArrayOfArrays patterns, float s
Mat temp = pattern.clone();
patterns_.push_back(temp);
}
if (alg_type == "TPU")
{
{
phi = (float)projector_size.width;
delta = 2*(float)CV_PI/phi;
for(auto k = 0; k < pattern_num; k++)
for(int k = 0; k < pattern_num; k++)
{
for( int i = 0; i < projector_size.height; ++i )
for(uint i = 0; i < projector_size.height; ++i )
{
for( int j = 0; j < projector_size.width; ++j )
for(uint j = 0; j < projector_size.width; ++j )
{
pattern.at<float>(i, j) = (cos((stripes_angle*i+(1-stripes_angle)*j)*delta+k*shift) + 1)/2;
}
@ -124,10 +93,8 @@ void StructuredLightMono::computePhasePCG(InputOutputArrayOfArrays refs, InputOu
vector<Mat>& refs_ = *(vector<Mat>* ) refs.getObj();
Size size = refs_[0].size();
Mat wrapped = Mat(size, CV_32FC1);
Mat wrapped_ref = Mat(size, CV_32FC1);
removeShadows(refs, imgs);
computeAtanDiff(refs, wrapped_ref);
computeAtanDiff(imgs, wrapped);
@ -137,34 +104,26 @@ void StructuredLightMono::computePhasePCG(InputOutputArrayOfArrays refs, InputOu
//phase computation based on TPU algorithm
void StructuredLightMono::computePhaseTPU(InputOutputArrayOfArrays refs, InputOutputArrayOfArrays imgs, OutputArray out)
{
{
vector<Mat>& refs_ = *(vector<Mat>* ) refs.getObj();
vector<Mat>& imgs_ = *(vector<Mat>* ) imgs.getObj();
Size size = refs_[0].size();
removeShadows(refs, imgs);
int split = (int)(refs_.size()/2);
auto hf_refs = vector<Mat>(refs_.begin(), refs_.begin()+split);
auto lf_refs = vector<Mat>(refs_.begin()+split, refs_.end());
auto hf_phases = vector<Mat>(imgs_.begin(), imgs_.begin()+split);
auto lf_phases = vector<Mat>(imgs_.begin()+split, imgs_.end());
Mat _lf_ref_phase = Mat(size, CV_32FC1);
Mat _hf_ref_phase= Mat(size, CV_32FC1);
Mat _lf_phase = Mat(size, CV_32FC1);
Mat _hf_phase = Mat(size, CV_32FC1);
computeAtanDiff(lf_refs, _lf_ref_phase);
computeAtanDiff(hf_refs, _hf_ref_phase);
computeAtanDiff(lf_phases, _lf_phase);
computeAtanDiff(hf_phases, _hf_phase);
subtract(_lf_phase, _lf_ref_phase, _lf_phase);
subtract(_hf_phase, _hf_ref_phase, _hf_phase);
unwrapTPU(_lf_phase, _hf_phase, out, stripes_num);
}

@ -41,7 +41,7 @@ double calibrate(InputArrayOfArrays objPoints, InputArrayOfArrays imgPoints,
}
void createObjectPoints(InputArrayOfArrays patternCorners, Size patternSize, float squareSize, int patternType)
{
{
std::vector<Point3f>& patternCorners_ = *( std::vector<Point3f>* ) patternCorners.getObj();
switch( patternType )
{
@ -84,7 +84,7 @@ void createProjectorObjectPoints(InputArrayOfArrays patternCorners, Size pattern
void fromCamToWorld(InputArray cameraMatrix, InputArrayOfArrays rV, InputArrayOfArrays tV,
InputArrayOfArrays imgPoints, OutputArrayOfArrays worldPoints)
{
{
std::vector<std::vector<Point2f>>& imgPoints_ = *( std::vector< std::vector<Point2f> >* ) imgPoints.getObj();
std::vector<std::vector<Point3f>>& worldPoints_ = *( std::vector< std::vector<Point3f> >* ) worldPoints.getObj();
std::vector<Mat>& rV_ = *( std::vector<Mat>* ) rV.getObj();
@ -131,7 +131,7 @@ void fromCamToWorld(InputArray cameraMatrix, InputArrayOfArrays rV, InputArrayOf
void saveCalibrationResults( String path, InputArray camK, InputArray camDistCoeffs, InputArray projK, InputArray projDistCoeffs,
InputArray fundamental )
{
{
Mat& camK_ = *(Mat*) camK.getObj();
Mat& camDistCoeffs_ = *(Mat*) camDistCoeffs.getObj();
Mat& projK_ = *(Mat*) projK.getObj();
@ -147,9 +147,9 @@ void saveCalibrationResults( String path, InputArray camK, InputArray camDistCoe
fs.release();
}
void saveCalibrationData(String path, InputArrayOfArrays T1, InputArrayOfArrays T2, InputArrayOfArrays ptsProjCam,
void saveCalibrationData(String path, InputArrayOfArrays T1, InputArrayOfArrays T2, InputArrayOfArrays ptsProjCam,
InputArrayOfArrays ptsProjProj, InputArrayOfArrays ptsProjCamN, InputArrayOfArrays ptsProjProjN)
{
{
std::vector<Mat>& T1_ = *( std::vector<Mat>* ) T1.getObj();
std::vector<Mat>& T2_ = *( std::vector<Mat>* ) T2.getObj();
std::vector<Mat>& ptsProjCam_ = *( std::vector<Mat>* ) ptsProjCam.getObj();
@ -176,7 +176,7 @@ void saveCalibrationData(String path, InputArrayOfArrays T1, InputArrayOfArrays
}
void loadCalibrationData(string filename, OutputArray cameraIntrinsic, OutputArray projectorIntrinsic,
void loadCalibrationData(string filename, OutputArray cameraIntrinsic, OutputArray projectorIntrinsic,
OutputArray cameraDistortion, OutputArray projectorDistortion, OutputArray rotation, OutputArray translation)
{
Mat& cameraIntrinsic_ = *(Mat*) cameraIntrinsic.getObj();
@ -206,7 +206,7 @@ void loadCalibrationData(string filename, OutputArray cameraIntrinsic, OutputArr
}
void normalize( InputArray pts, const int& dim, InputOutputArray normpts, OutputArray T)
{
{
Mat& pts_ = *(Mat*) pts.getObj();
Mat& normpts_ = *(Mat*) normpts.getObj();
Mat& T_ = *(Mat*) T.getObj();
@ -253,7 +253,7 @@ void normalize( InputArray pts, const int& dim, InputOutputArray normpts, Output
}
void fromVectorToMat(InputArrayOfArrays v, OutputArray pts)
{
{
Mat& pts_ = *(Mat*) pts.getObj();
std::vector<Point2f>& v_ = *( std::vector<Point2f>* ) v.getObj();
@ -294,7 +294,7 @@ Point2f back(Point2f point, double fx, double fy, double ux, double uy)
}
void distortImage(InputArray input, InputArray camMat, InputArray distCoef, OutputArray output)
{
{
Mat& camMat_ = *(Mat*) camMat.getObj();
Mat& input_ = *(Mat*) input.getObj();
@ -315,11 +315,11 @@ void distortImage(InputArray input, InputArray camMat, InputArray distCoef, Outp
Mat mapx(cv::Size(input_.rows, input_.cols), CV_32FC1);
Mat mapy(cv::Size(input_.rows, input_.cols), CV_32FC1);
for (int i = 0; i < input_.rows; i++)
{
for (int j = 0; j < input_.cols; j++)
{
{
distortedPoints[i*input_.cols+j] = back(distortedPoints[i*input_.cols+j], fx, fy, ux, uy);
mapx.at<float>(j, i) = distortedPoints[i*input_.cols+j].x;
mapy.at<float>(j, i) = distortedPoints[i*input_.cols+j].y;

@ -4,7 +4,11 @@ namespace cv{
namespace structured_light{
//quadrand swapping for FFT
void circshift(Mat &out, const Mat in, int xdim, int ydim, bool isFftshift = true) {
void circshift(OutputArray out, InputArray in, int xdim, int ydim, bool isFftshift = true) {
Mat in_ = in.getMat();
Mat& out_ = *(Mat*) out.getObj();
if (isFftshift) {
int xshift = (xdim / 2);
int yshift = (ydim / 2);
@ -13,7 +17,7 @@ void circshift(Mat &out, const Mat in, int xdim, int ydim, bool isFftshift = tru
int ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++) {
int jj = (j + yshift) % ydim;
out.at<float>(ii * ydim + jj) = in.at<float>(i * ydim + j);
out_.at<float>(ii * ydim + jj) = in_.at<float>(i * ydim + j);
}
}
}
@ -25,7 +29,7 @@ void circshift(Mat &out, const Mat in, int xdim, int ydim, bool isFftshift = tru
int ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++) {
int jj = (j + yshift) % ydim;
out.at<float>(ii * ydim + jj) = in.at<float>(i * ydim + j);
out_.at<float>(ii * ydim + jj) = in_.at<float>(i * ydim + j);
}
}
}
@ -119,10 +123,10 @@ void Laplacian(InputArray img, InputArray grid, OutputArray out, int flag = 0) {
}
void computeDelta(InputArray img, InputArray grid, OutputArray out) {
Mat x1, x2;
Mat img_sin, img_cos;
wrapSin(img, img_sin);
wrapCos(img, img_cos);
@ -170,7 +174,7 @@ void unwrapPCG(InputArray img, OutputArray out, Size imgSize) {
}
void unwrapTPU(InputArray phase1, InputArray phase2, OutputArray out, int scale) {
Mat& phase1_ = *(Mat*) phase1.getObj();
Mat& phase2_ = *(Mat*) phase2.getObj();
@ -182,16 +186,20 @@ void unwrapTPU(InputArray phase1, InputArray phase2, OutputArray out, int scale)
add(phase1_, phase2_, out);
}
void fft2(const cv::Mat in, cv::Mat &complexI) {
void fft2(InputArray in, OutputArray complexI) {
Mat in_ = in.getMat();
Mat& complexI_ = *(Mat*) complexI.getObj();
Mat padded;
int m = getOptimalDFTSize(in.rows);
int n = getOptimalDFTSize(in.cols);
int m = getOptimalDFTSize(in_.rows);
int n = getOptimalDFTSize(in_.cols);
copyMakeBorder(in, padded, 0, m - in.rows, 0, n - in.cols,
BORDER_CONSTANT, Scalar::all(0));
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
merge(planes, 2, complexI);
dft(complexI, complexI);
merge(planes, 2, complexI_);
dft(complexI_, complexI_);
}
void lowPassFilter(InputArray image, OutputArray out, int filterSize) {
@ -205,7 +213,7 @@ void lowPassFilter(InputArray image, OutputArray out, int filterSize) {
fft2(greyMat, result);
Mat matrix_(Size(rows, cols), CV_64FC1);
circshift(matrix_, result, result.rows, result.cols, true);
Mat lowPass(Size(rows, cols), CV_64FC1, Scalar(0));
@ -222,7 +230,7 @@ void lowPassFilter(InputArray image, OutputArray out, int filterSize) {
}
void highPassFilter(InputArray image, OutputArray out, int filterSize) {
Mat& image_ = *(Mat*) image.getObj();
int rows = image_.rows;
int cols = image_.cols;

Loading…
Cancel
Save