有关投影仪标定精度的问题
在看了大佬的文章之前,我才用的就是4步相移法+格雷码的编码方法进行解码,其中条纹数量为16条,光机是DLP3010,分辨率为1280*720,相机的标定采用圆形标定板,得到的重投影误差大概在0.07左右,但是当我用横竖相位进行解码,转化为投影仪角度下的坐标时,也是采用opencv的标定程序,发现无论怎么标定,投影仪的标定重投影误差都在1点多个像素,这是为啥呢?请大佬指教
这个是我的投影图像:
其中一组位姿状态下的横竖相位图(绝对相位):
这个是投影图像
建议按流程检查以下选项:
- 将特征点的相位映射至投影仪坐标系下生成图像,烧录并重投影至标定板上,查看偏离现象
- 若有偏离,必然解相存在问题:检查周期像素是否为整数、相位是否从0开始、解相以及相位映射部分程序是否存在问题
我把投影的条纹图拿去解码试了下,发现竖向条纹解码的时候,相位不是从0开始的,好像是因为有这个问题,竖向分辨率是720,如果投影格雷码的话,第五张格雷码的范围是720/32=22.5,这就导致了刚开始半条黑的条纹是22.5的像素范围,这个没办法制作出这种图像,我把他变成23了,这个会不会有影响,因为横向格雷码没这个问题,1280/32=40
解出来的绝对相位一定是从零开始的吗,我看了下我解出来的理论相位,
我的相位最小值是-0.00393707000000000,这个是解绝对相位出问题了吗
得到原因是我解绝对相位出了点问题,但是当我修复了问题之后,重新标定,投影仪的标定重投影误差还是有0.9个像素,这是为啥呢
这个是转换后的投影仪视角图:
这个是相机采集到的图像:
能帮忙看看是哪里还有问题吗,因为转化过来时亚像素坐标,我在投影仪视角图上是四舍五入
问了下光机的厂商,没办法投影上述图像,所以我将每个圆心的横坐标形成条纹投影出来,如下所示:
大佬麻烦帮忙看看问题所在
利用转换的坐标点进行matlab的投影仪标定,结果如下:可以看到重投影误差在0.8个像素,还是达不到使用的精度啊
博主,想问下你在检测完圆心之后,圆心的坐标值是亚像素级别,你有做什么处理之后再转换到投影仪坐标下吗
你可以考虑增加相移步数并做线性插值尝试。此外,你给的投影图片不知道是哪些点,请自行检阅。一般至少能够达到0.2左右精度。
自己查看源码吧,都是开源的:[code]: https://github.com/Practice3DVision/SLMaster/blob/d4590ec7e627e82b700d720f592618105b17c821/gui/src/CalibrateEngine.cpp#L815C1-L870C2
CalibrateEngine::remapProjectorPoint(const cv::Mat &honrizonPhaseMap,
const cv::Mat &verticalPhaseMap,
const cv::Point2f &camPoint) {
#ifdef LinearInter
int index_Y_Upper = std::ceil(camPoint.y);
int index_Y_Lower = std::floor(camPoint.y);
int index_X_Upper = std::ceil(camPoint.x);
int index_X_Lower = std::floor(camPoint.x);
const float vPLU =
verticalPhaseMap.ptr<float>(index_Y_Upper)[index_X_Lower];
const float vPRU =
verticalPhaseMap.ptr<float>(index_Y_Upper)[index_X_Upper];
const float vPLD =
verticalPhaseMap.ptr<float>(index_Y_Lower)[index_X_Lower];
const float vPRD =
verticalPhaseMap.ptr<float>(index_Y_Lower)[index_X_Upper];
const float tPLU =
honrizonPhaseMap.ptr<float>(index_Y_Upper)[index_X_Lower];
const float tPRU =
honrizonPhaseMap.ptr<float>(index_Y_Upper)[index_X_Upper];
const float tPLD =
honrizonPhaseMap.ptr<float>(index_Y_Lower)[index_X_Lower];
const float tPRD =
honrizonPhaseMap.ptr<float>(index_Y_Lower)[index_X_Upper];
const float vfR1 =
(index_X_Upper - camPoint.x) / (index_X_Upper - index_X_Lower) * vPLD +
(camPoint.x - index_X_Lower) / (index_X_Upper - index_X_Lower) * vPRD;
const float vfR2 =
(index_X_Upper - camPoint.x) / (index_X_Upper - index_X_Lower) * vPLU +
(camPoint.x - index_X_Lower) / (index_X_Upper - index_X_Lower) * vPRU;
const float tfR1 =
(index_X_Upper - camPoint.x) / (index_X_Upper - index_X_Lower) * tPLD +
(camPoint.x - index_X_Lower) / (index_X_Upper - index_X_Lower) * tPRD;
const float tfR2 =
(index_X_Upper - camPoint.x) / (index_X_Upper - index_X_Lower) * tPLU +
(camPoint.x - index_X_Lower) / (index_X_Upper - index_X_Lower) * tPRU;
const float verticalPhaseValue =
(index_Y_Upper - camPoint.y) / (index_Y_Upper - index_Y_Lower) * vfR1 +
(camPoint.y - index_Y_Lower) / (index_Y_Upper - index_Y_Lower) * vfR2;
const float transversePhaseValue =
(index_Y_Upper - camPoint.y) / (index_Y_Upper - index_Y_Lower) * tfR1 +
(camPoint.y - index_Y_Lower) / (index_Y_Upper - index_Y_Lower) * tfR2;
#else
int index_Y = std::round(camPoint.y);
int index_X = std::round(camPoint.x);
const float verticalPhaseValue =
verticalPhaseMap.ptr<float>(index_Y)[index_X];
const float transversePhaseValue =
honrizonPhaseMap.ptr<float>(index_Y)[index_X];
#endif
const float xLocation =
(verticalPhaseValue) / CV_2PI * projectorCaliParams_.verticalPitch_;
const float yLocation =
(transversePhaseValue) / CV_2PI * projectorCaliParams_.honrizonPitch_;
return cv::Point2f(xLocation, yLocation);
}
相对相位是能够满足0和2pi都取到的吗
我这个最大相位离2pi还有点距离
简言之,就是0-2pi这个包裹相位的范围是左闭右开的吧,还是说左右都是闭区间?