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. 2
      modules/structured_light/samples/calibrate_example.cpp
  4. 16
      modules/structured_light/samples/sl_example.cpp
  5. 53
      modules/structured_light/src/slmono.cpp
  6. 24
      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); 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); 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 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,7 +15,7 @@ static const char* keys =
enum calibrationPattern{CHESSBOARD, CIRCLES_GRID, ASYMETRIC_CIRCLES_GRID}; enum calibrationPattern{CHESSBOARD, CIRCLES_GRID, ASYMETRIC_CIRCLES_GRID};
int calibrate( int argc, char **argv ) int main( int argc, char **argv )
{ {
VideoCapture cap(CAP_PVAPI); VideoCapture cap(CAP_PVAPI);
Mat frame; Mat frame;

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

@ -5,28 +5,6 @@
namespace cv { namespace cv {
namespace structured_light { 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 //main phase unwrapping function
void StructuredLightMono::unwrapPhase(InputOutputArrayOfArrays refs, InputOutputArrayOfArrays imgs, OutputArray out) void StructuredLightMono::unwrapPhase(InputOutputArrayOfArrays refs, InputOutputArrayOfArrays imgs, OutputArray out)
{ {
@ -46,9 +24,7 @@ void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutp
vector<Mat>& refs_ = *(vector<Mat>*)refs.getObj(); vector<Mat>& refs_ = *(vector<Mat>*)refs.getObj();
vector<Mat>& imgs_ = *(vector<Mat>*)imgs.getObj(); vector<Mat>& imgs_ = *(vector<Mat>*)imgs.getObj();
Size size = refs_[0].size(); Size size = refs_[0].size();
Mat mean(size, CV_32FC1); Mat mean(size, CV_32FC1);
for( int i = 0; i < size.height; ++i ) for( int i = 0; i < size.height; ++i )
{ {
for( int j = 0; j < size.width; ++j ) for( int j = 0; j < size.width; ++j )
@ -61,11 +37,9 @@ void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutp
mean.at<float>(i, j) = average/imgs_.size(); mean.at<float>(i, j) = average/imgs_.size();
} }
} }
mean.convertTo(mean, CV_32FC1); mean.convertTo(mean, CV_32FC1);
Mat shadowMask; Mat shadowMask;
threshold(mean, shadowMask, 0.05, 1, 0); threshold(mean, shadowMask, 0.05, 1, 0);
for (int k = 0; k < imgs_.size(); k++) for (int k = 0; k < imgs_.size(); k++)
{ {
multiply(shadowMask, refs_[k], refs_[k]); multiply(shadowMask, refs_[k], refs_[k]);
@ -79,18 +53,15 @@ void StructuredLightMono::removeShadows(InputOutputArrayOfArrays refs, InputOutp
void StructuredLightMono::generatePatterns(OutputArrayOfArrays patterns, float stripes_angle) void StructuredLightMono::generatePatterns(OutputArrayOfArrays patterns, float stripes_angle)
{ {
vector<Mat>& patterns_ = *(vector<Mat>*) patterns.getObj(); vector<Mat>& patterns_ = *(vector<Mat>*) patterns.getObj();
float phi = (float)projector_size.width/(float)stripes_num; float phi = (float)projector_size.width/(float)stripes_num;
float delta = 2*(float)CV_PI/phi; float delta = 2*(float)CV_PI/phi;
float shift = 2*(float)CV_PI/pattern_num; float shift = 2*(float)CV_PI/pattern_num;
Mat pattern(projector_size, CV_32FC1, Scalar(0)); Mat pattern(projector_size, CV_32FC1, Scalar(0));
for(int k = 0; k < pattern_num; k++)
for(auto 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; 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(); Mat temp = pattern.clone();
patterns_.push_back(temp); patterns_.push_back(temp);
} }
if (alg_type == "TPU") if (alg_type == "TPU")
{ {
phi = (float)projector_size.width; phi = (float)projector_size.width;
delta = 2*(float)CV_PI/phi; delta = 2*(float)CV_PI/phi;
for(int k = 0; k < pattern_num; k++)
for(auto 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; 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(); vector<Mat>& refs_ = *(vector<Mat>* ) refs.getObj();
Size size = refs_[0].size(); Size size = refs_[0].size();
Mat wrapped = Mat(size, CV_32FC1); Mat wrapped = Mat(size, CV_32FC1);
Mat wrapped_ref = Mat(size, CV_32FC1); Mat wrapped_ref = Mat(size, CV_32FC1);
removeShadows(refs, imgs); removeShadows(refs, imgs);
computeAtanDiff(refs, wrapped_ref); computeAtanDiff(refs, wrapped_ref);
computeAtanDiff(imgs, wrapped); computeAtanDiff(imgs, wrapped);
@ -140,31 +107,23 @@ void StructuredLightMono::computePhaseTPU(InputOutputArrayOfArrays refs, InputOu
{ {
vector<Mat>& refs_ = *(vector<Mat>* ) refs.getObj(); vector<Mat>& refs_ = *(vector<Mat>* ) refs.getObj();
vector<Mat>& imgs_ = *(vector<Mat>* ) imgs.getObj(); vector<Mat>& imgs_ = *(vector<Mat>* ) imgs.getObj();
Size size = refs_[0].size(); Size size = refs_[0].size();
removeShadows(refs, imgs); removeShadows(refs, imgs);
int split = (int)(refs_.size()/2); int split = (int)(refs_.size()/2);
auto hf_refs = vector<Mat>(refs_.begin(), refs_.begin()+split); auto hf_refs = vector<Mat>(refs_.begin(), refs_.begin()+split);
auto lf_refs = vector<Mat>(refs_.begin()+split, refs_.end()); auto lf_refs = vector<Mat>(refs_.begin()+split, refs_.end());
auto hf_phases = vector<Mat>(imgs_.begin(), imgs_.begin()+split); auto hf_phases = vector<Mat>(imgs_.begin(), imgs_.begin()+split);
auto lf_phases = vector<Mat>(imgs_.begin()+split, imgs_.end()); auto lf_phases = vector<Mat>(imgs_.begin()+split, imgs_.end());
Mat _lf_ref_phase = Mat(size, CV_32FC1); Mat _lf_ref_phase = Mat(size, CV_32FC1);
Mat _hf_ref_phase= Mat(size, CV_32FC1); Mat _hf_ref_phase= Mat(size, CV_32FC1);
Mat _lf_phase = Mat(size, CV_32FC1); Mat _lf_phase = Mat(size, CV_32FC1);
Mat _hf_phase = Mat(size, CV_32FC1); Mat _hf_phase = Mat(size, CV_32FC1);
computeAtanDiff(lf_refs, _lf_ref_phase); computeAtanDiff(lf_refs, _lf_ref_phase);
computeAtanDiff(hf_refs, _hf_ref_phase); computeAtanDiff(hf_refs, _hf_ref_phase);
computeAtanDiff(lf_phases, _lf_phase); computeAtanDiff(lf_phases, _lf_phase);
computeAtanDiff(hf_phases, _hf_phase); computeAtanDiff(hf_phases, _hf_phase);
subtract(_lf_phase, _lf_ref_phase, _lf_phase); subtract(_lf_phase, _lf_ref_phase, _lf_phase);
subtract(_hf_phase, _hf_ref_phase, _hf_phase); subtract(_hf_phase, _hf_ref_phase, _hf_phase);
unwrapTPU(_lf_phase, _hf_phase, out, stripes_num); unwrapTPU(_lf_phase, _hf_phase, out, stripes_num);
} }

@ -4,7 +4,11 @@ namespace cv{
namespace structured_light{ namespace structured_light{
//quadrand swapping for FFT //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) { if (isFftshift) {
int xshift = (xdim / 2); int xshift = (xdim / 2);
int yshift = (ydim / 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; int ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++) { for (int j = 0; j < ydim; j++) {
int jj = (j + yshift) % ydim; 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; int ii = (i + xshift) % xdim;
for (int j = 0; j < ydim; j++) { for (int j = 0; j < ydim; j++) {
int jj = (j + yshift) % ydim; 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);
} }
} }
} }
@ -182,16 +186,20 @@ void unwrapTPU(InputArray phase1, InputArray phase2, OutputArray out, int scale)
add(phase1_, phase2_, out); 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; Mat padded;
int m = getOptimalDFTSize(in.rows); int m = getOptimalDFTSize(in_.rows);
int n = getOptimalDFTSize(in.cols); int n = getOptimalDFTSize(in_.cols);
copyMakeBorder(in, padded, 0, m - in.rows, 0, n - in.cols, copyMakeBorder(in, padded, 0, m - in.rows, 0, n - in.cols,
BORDER_CONSTANT, Scalar::all(0)); BORDER_CONSTANT, Scalar::all(0));
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)}; Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
merge(planes, 2, complexI); merge(planes, 2, complexI_);
dft(complexI, complexI); dft(complexI_, complexI_);
} }
void lowPassFilter(InputArray image, OutputArray out, int filterSize) { void lowPassFilter(InputArray image, OutputArray out, int filterSize) {

Loading…
Cancel
Save