使用棋盘图案展开的帽子标签 (OpenCV c++)

unrolled label of a Cap using chessboard pattern (OpenCV c++)

我正在尝试使用棋盘图案来获取圆柱体贴图的信息并纠正 "distortion" 以便图像显示展开的盖子表面。我用一次校准和 cv::fisheye::undistortImage 进行了第一次测试,以获得不失真(附上两张图片)。

*//runCalibrationFishEye
void runCalibrationFishEye(cv::Mat& image, cv::Matx33d&, cv::Vec4d&);
cv::Mat removeFisheyeLensDist(cv::Mat&, cv::Matx33d&, cv::Vec4d&);*

请注意,我对校准图像、获取度量值不感兴趣。我只是想利用棋盘信息展开圆柱面上的图像

最终目的是利用4个摄像头校正后的图像,将校正后的图像拼接成一张展开图。

我需要对相机进行全面校准吗?或者有其他方法可以重新映射圆柱表面吗?

我将尝试实现这个有趣的展开方法:https://dsp.stackexchange.com/questions/2406/how-to-flatten-the-image-of-a-label-on-a-food-jar/2409#2409

cap with chessboard

Rectification

我发现了一个类似的方法,解决另一个问题,但具有类似的数学。它在没有校准模式的情况下解决了。 Link here。这是一个近似值,但结果已经足够好了。

Hammer 用户给出的答案帮助我找到了解决方案。我已经改变了他做映射的方式,使用 OpenCV 重映射。重新计算坐标的公式就像他给的一样,使用不同的值,并进行预处理以调整图像(旋转,缩放和其他调整)。Unrolled image。我现在正在改善边缘的变形,使其在边缘处不那么明显。但是主要问题已经解决了。

cv::Point2f convert_pt(cv::Point2f point, int w, int h)
{
cv::Point2f pc(point.x - w / 2, point.y - h / 2);
float f =  w;   
float r =  w;
float omega = w / 2;
float z0 = f - sqrt(r*r - omega*omega);

//Formula para remapear el cylindro
float zc = (2 * z0 + sqrt(4 * z0*z0 - 4 * (pc.x*pc.x / (f*f) + 1)*(z0*z0        - r*r))) / (2 * (pc.x*pc.x / (f*f) + 1));
cv::Point2f final_point(pc.x*zc / f, pc.y*zc / f);
final_point.x += w / 2;
final_point.y += h / 2;
return final_point;
}