OpenCV Mat::convertTo(type)无法转换指定类型问题原因与解决方法
问题原因
cv::Mat::convertTo 方法的设计逻辑仅负责转换矩阵元素的位深度(即元素存储的数据类型),不会修改矩阵的通道数,执行时会强制让输出矩阵和输入矩阵保持相同的尺寸、通道数,传入的目标类型参数中携带的通道数标识会被直接忽略。
你的代码中源矩阵a本身就是CV_64F(64位双精度浮点数)位深度,和你传入的CV_64FC4里的位深度部分完全匹配,因此转换时既没有修改位深度,也没有修改通道数,最终输出的b和源矩阵a类型一致,为CV_64FC1,和预期的4通道结果不符。
正确实现方式
要得到指定通道数的目标矩阵,不能单独依赖convertTo,需要搭配OpenCV的通道操作API完成,分两种场景处理:
- 如果仅需要修改位深度,不需要调整通道数:直接使用
convertTo即可,传入目标类型时不需要关心通道数部分,方法会自动对齐源矩阵通道数。 - 如果需要调整通道数(比如本例中单通道转4通道):
- 若同时需要修改位深度,先调用
convertTo把源矩阵转成目标位深度的对应通道矩阵 - 准备好所有通道的矩阵数据,使用
cv::merge接口将多个单通道矩阵拼接为目标多通道矩阵
- 若同时需要修改位深度,先调用
本例中要得到CV_64FC4类型的b,可参考如下可运行代码:
#include <opencv2/core.hpp> #include <iostream> #include <vector> int main(int argc, char** argv) { cv::Mat a = (cv::Mat_<double>(3,1) << 1, 2, 3); cv::Mat b; std::cout << "a(before): " << cv::typeToString(a.type()) << std::endl; std::cout << "b(before): " << cv::typeToString(b.type()) << std::endl; std::cout << std::endl; std::cout << "Convert 'a' --> 'b' with type CV_64FC4" << std::endl; std::cout << std::endl; // 构造4个通道,此处示例为所有通道值和原矩阵a一致,可根据实际需求替换各通道数据 std::vector<cv::Mat> channels(4, a); cv::merge(channels, b); std::cout << "a(after): " << cv::typeToString(a.type()) << std::endl; std::cout << "b(after): " << cv::typeToString(b.type()) << std::endl; return 0; }
运行上述代码即可得到预期输出,b的类型为CV_64FC4。
注意:
cv::Mat::reshape方法虽然可以修改矩阵通道数,但它要求矩阵总元素数(rows * cols * channels)和修改前完全一致,无法凭空新增通道的元素值,因此不适合本例这类单通道扩多通道的场景。
内容的提问来源于stack exchange,提问作者Frank-Rene Schäfer
相关产品推荐
相关产品推荐

