opencv contrib 中的unwrapping_phase 模块,提供了一种基于路径的解相位方法。
计算绝对相位
void ComputePhase(std::vector<cv::Mat>& mats, cv::Mat& phase) {
int rows = mats[0].rows;
int cols = mats[0].cols;
if (phase.empty()) {
phase.create(rows, cols, CV_32FC1);
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
float f0 = static_cast<float>(mats[0].at<uchar>(r, c));
float f1 = static_cast<float>(mats[1].at<uchar>(r, c));
float f2 = static_cast<float>(mats[2].at<uchar>(r, c));
float f3 = static_cast<float>(mats[3].at<uchar>(r, c));
float radian = std::atan2f(f1 - f3, f0 - f2);
if (radian < 0) radian += CV_2PI;
phase.at<float>(r, c) = radian;
}
}
}
得到包裹相位图
计算解包裹相位
在opecv contrib中phase_unwrapping模块提供了解相位的实现。主要是
cv::phase_unwrapping::HistogramPhaseUnwrapping
类中有一个结构体参数:
struct CV_EXPORTS_W_SIMPLE Params
{
CV_WRAP Params();
CV_PROP_RW int width;// mat cols;
CV_PROP_RW int height;// mat rows
CV_PROP_RW float histThresh;// 分割阈值,默认3*PI*pi,
CV_PROP_RW int nbrOfSmallBins;// 小端 bin数目, 默认10
CV_PROP_RW int nbrOfLargeBins;// 大端 bin数目, 默认5
};
一般参数只需要设置 width, 和 height
类中主要结构是:
1. 静态函数返回构造的指针
static Ptr<HistogramPhaseUnwrapping> create( const HistogramPhaseUnwrapping::Params ¶meters =
HistogramPhaseUnwrapping::Params() );
参数就是 Params
2. unwrapPhaseMap 函数
virtual void unwrapPhaseMap( InputArray wrappedPhaseMap, OutputArray unwrappedPhaseMap,
InputArray shadowMask = noArray() ) = 0;
第一个参数为包裹相位Mat, 第二个是解相位结果Mat, 第三个是Mask。
3. 获取置信Mat。 值越接近0,该点的解相位结果越准确。
virtual void getInverseReliabilityMap( OutputArray reliabilityMap ) = 0;
实际使用
std::string tiffPath = dir + name + "Phase.tiff";
cv::Mat phase = cv::imread(tiffPath, -1);
cv::phase_unwrapping::HistogramPhaseUnwrapping::Params params;
params.width = phase.cols;
params.height = phase.rows;
params.histThresh = CV_PI * CV_PI;
params.nbrOfSmallBins = 10;
params.nbrOfLargeBins = 10;
cv::Ptr<cv::phase_unwrapping::HistogramPhaseUnwrapping> ptr = cv::phase_unwrapping::HistogramPhaseUnwrapping::create(params);
cv::Mat unPhase(phase.size(), CV_32FC1);
ptr->unwrapPhaseMap(phase, unPhase);
std::string unPath = dir + name + "UnPhase.tiff";
cv::imwrite(unPath, unPhase);
}
解相位结果:
基于平面相位高度映射(标定平面解相位过程如上),得到3D点云高度