调用cv::eigen2cv后cv::getPerspectiveTransform抛错的解决方案
问题根因
你的排查结论完全正确:cv::eigen2cv 不会复用输出参数预先分配的内存与类型设置。由于你的入参是Eigen::MatrixXd(双精度浮点型矩阵),转换后输出的OpenCV Mat会自动匹配为CV_64FC1(双精度浮点)类型,直接覆盖你之前初始化quad、warpedQuad时指定的CV_32FC1类型与尺寸。而cv::getPerspectiveTransform接口要求输入点集必须为CV_32F类型,因此触发类型断言报错。
报错断言的校验逻辑明确要求:输入的源、目标点集必须是2通道CV_32F类型、共4个点的向量,类型不匹配就会直接抛出异常。
标准解决方案
有两种合规实现,优先选择第一种避免不必要的类型转换开销:
- 方案1(零额外开销,推荐):将函数入参的Eigen矩阵类型从双精度
Eigen::MatrixXd改为单精度Eigen::MatrixXf,和OpenCV接口要求的CV_32F类型完全对齐,转换后可直接传入接口。 - 方案2(兼容双精度入参场景):如果业务逻辑必须保留
Eigen::MatrixXd作为入参,在cv::eigen2cv转换完成后,显式调用convertTo将Mat转换为CV_32FC1类型再传入计算接口。
修正后代码示例
方案1(推荐)
cv::Mat getPerspectiveTransform(Eigen::MatrixXf quadrangle, Eigen::MatrixXf warpedQuadrangle) { cv::Mat transMat; cv::Mat quad, warpedQuad; // 无需提前指定输出Mat的类型、尺寸,eigen2cv会自动匹配Eigen单精度类型输出CV_32FC1格式 cv::eigen2cv(quadrangle, quad); cv::eigen2cv(warpedQuadrangle, warpedQuad); transMat = cv::getPerspectiveTransform(quad, warpedQuad); return transMat; }
方案2(兼容双精度入参)
cv::Mat getPerspectiveTransform(Eigen::MatrixXd quadrangle, Eigen::MatrixXd warpedQuadrangle) { cv::Mat transMat; cv::Mat quad, warpedQuad; cv::eigen2cv(quadrangle, quad); cv::eigen2cv(warpedQuadrangle, warpedQuad); // 显式转换为接口要求的CV_32F类型 quad.convertTo(quad, CV_32FC1); warpedQuad.convertTo(warpedQuad, CV_32FC1); transMat = cv::getPerspectiveTransform(quad, warpedQuad); return transMat; }
注意事项
不要为cv::eigen2cv的输出参数提前预分配指定类型的内存,该函数执行时会重新分配输出Mat的内存,覆盖原有对象的所有属性,提前预分配的操作没有任何实际作用。
内容的提问来源于stack exchange,提问作者Ayushman Kumar
相关产品推荐
相关产品推荐

