Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有关投影仪标定精度的问题 #21

Open
Raymonddhr opened this issue May 10, 2024 · 13 comments
Open

有关投影仪标定精度的问题 #21

Raymonddhr opened this issue May 10, 2024 · 13 comments
Assignees
Labels
help wanted Extra attention is needed

Comments

@Raymonddhr
Copy link

在看了大佬的文章之前,我才用的就是4步相移法+格雷码的编码方法进行解码,其中条纹数量为16条,光机是DLP3010,分辨率为1280*720,相机的标定采用圆形标定板,得到的重投影误差大概在0.07左右,但是当我用横竖相位进行解码,转化为投影仪角度下的坐标时,也是采用opencv的标定程序,发现无论怎么标定,投影仪的标定重投影误差都在1点多个像素,这是为啥呢?请大佬指教
这个是我的投影图像:
image
image
image
image
其中一组位姿状态下的横竖相位图(绝对相位):
Absolute_pha_h
Absolute_pha_v

@Raymonddhr Raymonddhr added the compilation issues Problems at compile time label May 10, 2024
@Raymonddhr
Copy link
Author

这个是投影图像
1

@Practice3DVision Practice3DVision added help wanted Extra attention is needed and removed compilation issues Problems at compile time labels May 11, 2024
@Practice3DVision
Copy link
Owner

建议按流程检查以下选项:

  1. 将特征点的相位映射至投影仪坐标系下生成图像,烧录并重投影至标定板上,查看偏离现象
  2. 若有偏离,必然解相存在问题:检查周期像素是否为整数、相位是否从0开始、解相以及相位映射部分程序是否存在问题

@Raymonddhr
Copy link
Author

我把投影的条纹图拿去解码试了下,发现竖向条纹解码的时候,相位不是从0开始的,好像是因为有这个问题,竖向分辨率是720,如果投影格雷码的话,第五张格雷码的范围是720/32=22.5,这就导致了刚开始半条黑的条纹是22.5的像素范围,这个没办法制作出这种图像,我把他变成23了,这个会不会有影响,因为横向格雷码没这个问题,1280/32=40

@Raymonddhr
Copy link
Author

解出来的绝对相位一定是从零开始的吗,我看了下我解出来的理论相位,
image
image
我的相位最小值是-0.00393707000000000,这个是解绝对相位出问题了吗

@Raymonddhr
Copy link
Author

得到原因是我解绝对相位出了点问题,但是当我修复了问题之后,重新标定,投影仪的标定重投影误差还是有0.9个像素,这是为啥呢

@Raymonddhr
Copy link
Author

这个是转换后的投影仪视角图:
circle_image
这个是相机采集到的图像:
cicle12
能帮忙看看是哪里还有问题吗,因为转化过来时亚像素坐标,我在投影仪视角图上是四舍五入

@Raymonddhr
Copy link
Author

问了下光机的厂商,没办法投影上述图像,所以我将每个圆心的横坐标形成条纹投影出来,如下所示:
4E6$YB$QQ7}2AMDI41{23S_tmb
大佬麻烦帮忙看看问题所在

@Raymonddhr
Copy link
Author

利用转换的坐标点进行matlab的投影仪标定,结果如下:可以看到重投影误差在0.8个像素,还是达不到使用的精度啊
image

@Raymonddhr
Copy link
Author

博主,想问下你在检测完圆心之后,圆心的坐标值是亚像素级别,你有做什么处理之后再转换到投影仪坐标下吗

@Practice3DVision
Copy link
Owner

你可以考虑增加相移步数并做线性插值尝试。此外,你给的投影图片不知道是哪些点,请自行检阅。一般至少能够达到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);
}

@Raymonddhr
Copy link
Author

相对相位是能够满足0和2pi都取到的吗
0aae69944e1aa7fafdf77e9ab8e5c51
我这个最大相位离2pi还有点距离

@Raymonddhr
Copy link
Author

简言之,就是0-2pi这个包裹相位的范围是左闭右开的吧,还是说左右都是闭区间?

@Raymonddhr
Copy link
Author

而且你说的插值方法我早就用到过了,不就是双线性插值嘛,如下是我的投影图像,以及检测到的圆心,还有转换到光机下的圆心位置图像:
投影仪.zip
相机检测.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants