Repository for OpenCV's extra modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

260 lines
7.0 KiB

#include "opencv2/structured_light/slmono_utils.hpp"
namespace cv{
namespace structured_light{
//quadrand swapping for FFT
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);
for (int i = 0; i < xdim; i++) {
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);
}
}
}
else {
int xshift = ((xdim + 1) / 2);
int yshift = ((ydim + 1) / 2);
for (int i = 0; i < xdim; i++) {
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);
}
}
}
}
void createGrid(OutputArray output, Size size) {
auto gridX = Mat(size, CV_32FC1);
auto gridY = Mat(size, CV_32FC1);
for (auto i = 0; i < size.height; i++) {
for (auto j = 0; j < size.width; j++) {
gridX.at<float>(i, j) = float(j + 1);
gridY.at<float>(i, j) = float(i + 1);
}
}
multiply(gridX, gridX, gridX);
multiply(gridY, gridY, gridY);
add(gridX, gridY, output);
}
void wrapSin(InputArray img, OutputArray out) {
Mat img_ = img.getMat();
Mat& out_ = *(Mat*) out.getObj();
out_ = Mat(img_.rows, img_.cols, CV_32FC1);
for (auto i = 0; i < img_.rows; i++) {
for (auto j = 0; j < img_.cols; j++) {
float x = img_.at<float>(i, j);
while (abs(x) >= M_PI_2) {
x += ((x > 0) - (x < 0)) * (float(M_PI) - 2 * abs(x));
}
out_.at<float>(i, j) = x;
}
}
}
void wrapCos(InputArray img, OutputArray out) {
Mat img_ = img.getMat();
Mat& out_ = *(Mat*) out.getObj();
out_ = Mat(img_.rows, img_.cols, CV_32FC1);
for (auto i = 0; i < img_.rows; i++) {
for (auto j = 0; j < img_.cols; j++) {
float x = img_.at<float>(i, j) - (float)M_PI_2;
while (abs(x) > M_PI_2) {
x += ((x > 0) - (x < 0)) * ((float)M_PI - 2 * abs(x));
}
out_.at<float>(i, j) = -x;
}
}
}
void computeAtanDiff(InputOutputArrayOfArrays src, OutputArray dst) {
std::vector<Mat>& src_ = *( std::vector<Mat>* ) src.getObj();
Mat& dst_ = *(Mat*) dst.getObj();
for (int i = 0; i < src_[0].rows; i++) {
for (int j = 0; j < src_[0].cols; j++) {
float x = src_[3].at<float>(i, j) - src_[1].at<float>(i, j);
float y = src_[0].at<float>(i, j) - src_[2].at<float>(i, j);
dst_.at<float>(i, j) = std::atan2(x, y);
}
}
}
void Laplacian(InputArray img, InputArray grid, OutputArray out, int flag = 0) {
Mat& img_ = *(Mat*) img.getObj();
Mat& out_ = *(Mat*) out.getObj();
if (flag == 0){
dct(img, out_);
multiply(out_, grid, out_);
dct(out_, out_, DCT_INVERSE);
out_ = out_ * (-4 * M_PI * M_PI / (img_.rows * img_.cols));
}
else if (flag == 1)
{
dct(img, out_);
divide(out_, grid, out_);
dct(out_, out_, DCT_INVERSE);
out_ = out_ * (-img_.rows * img_.cols) / (4 * M_PI * M_PI);
}
}
void computeDelta(InputArray img, InputArray grid, OutputArray out) {
Mat x1, x2;
Mat img_sin, img_cos;
wrapSin(img, img_sin);
wrapCos(img, img_cos);
Mat laplacian1, laplacian2;
Laplacian(img_sin, grid, laplacian1);
Laplacian(img_cos, grid, laplacian2);
multiply(img_cos, laplacian1, x1);
multiply(img_sin, laplacian2, x2);
subtract(x1, x2, out);
}
void unwrapPCG(InputArray img, OutputArray out, Size imgSize) {
Mat g_laplacian;
Mat phase1;
Mat error, k1, k2, phase2;
Mat phiError;
createGrid(g_laplacian, imgSize);
computeDelta(img, g_laplacian, phase1);
Laplacian(phase1, g_laplacian, phase1, 1);
subtract(phase1, img, k1);
k1 *= 0.5 / M_PI;
abs(k1);
k1 *= 2 * M_PI;
add(img, k1, out);
for (auto i = 0; i < 0; i++) {
subtract(phase2, phase1, error);
computeDelta(error, g_laplacian, phiError);
Laplacian(phiError, g_laplacian, phiError, 1);
add(phase1, phiError, phase1);
subtract(phase1, img, k2);
k2 *= 0.5 / M_PI;
abs(k2);
k2 *= 2 * M_PI;
add(img, k2, out);
k2.copyTo(k1);
}
}
void unwrapTPU(InputArray phase1, InputArray phase2, OutputArray out, int scale) {
Mat& phase1_ = *(Mat*) phase1.getObj();
Mat& phase2_ = *(Mat*) phase2.getObj();
phase1_.convertTo(phase1_, phase1_.type(), scale);
subtract(phase1_, phase2_, phase1_);
phase1_.convertTo(phase1_, phase1_.type(), 0.5f / CV_PI);
abs(phase1_);
phase1_.convertTo(phase1_, phase1_.type(), 2 * CV_PI);
add(phase1_, phase2_, out);
}
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);
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_);
}
void lowPassFilter(InputArray image, OutputArray out, int filterSize) {
Mat& image_ = *(Mat*) image.getObj();
int rows = image_.rows;
int cols = image_.cols;
Mat greyMat;
cvtColor(image, greyMat, COLOR_BGR2GRAY);
Mat result;
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));
lowPass(Rect_<int>((int)(0.5*rows-filterSize), (int)(0.5 * cols - filterSize),
(int)(0.5*rows+filterSize), (int)(0.5 * cols + filterSize))) = 1;
Mat pass = matrix_.mul(lowPass);
Mat J1(Size(rows, cols), CV_64FC1);
circshift(J1, pass, rows, cols, false);
idft(J1, out);
}
void highPassFilter(InputArray image, OutputArray out, int filterSize) {
Mat& image_ = *(Mat*) image.getObj();
int rows = image_.rows;
int cols = image_.cols;
Mat greyMat;
cvtColor(image, greyMat, COLOR_BGR2GRAY);
Mat result;
fft2(greyMat, result);
Mat matrix_(Size(rows, cols), CV_64FC1);
circshift(matrix_, result, result.rows, result.cols, true);
Mat highPass(Size(rows, cols), CV_64FC1, Scalar(1));
highPass(Rect_<int>((int)(0.5*rows-filterSize), (int)(0.5 * cols - filterSize),
(int)(0.5*rows+filterSize), (int)(0.5 * cols + filterSize))) = 0;
Mat pass = matrix_.mul(highPass);
Mat filter(Size(rows, cols), CV_64FC1);
circshift(filter, pass, rows, cols, false);
idft(filter, out);
}
}
}