如何将cv::Scalar赋值给cv::Mat?为何两种赋值方式有正误之分?
关于cv::Scalar赋值给cv::Mat的问题解答
嘿,我来帮你理清OpenCV里cv::Scalar和cv::Mat赋值的问题~
一、怎么把cv::Scalar赋值给cv::Mat?
根据你的需求,有几种实用的方式:
创建Mat时直接初始化:如果你刚创建矩阵,直接把Scalar当参数传进去,就能让整个矩阵的所有元素都是这个Scalar的值
// 生成一个3行3列的3通道彩色矩阵,所有像素都是绿色(0,255,0) cv::Mat mat(3, 3, CV_8UC3, cv::Scalar(0,255,0));给已有矩阵统一赋值:如果矩阵已经存在,用
setTo()方法是最稳妥的选择,它会遍历整个矩阵,把每个元素都替换成指定的Scalarcv::Mat mat = cv::Mat::zeros(3,3,CV_8UC3); // 先创建一个全黑矩阵 mat.setTo(cv::Scalar(0,255,0)); // 把所有元素改成绿色单通道矩阵的简化赋值:如果是单通道的灰度矩阵,直接用等号赋值也能行(不过还是更推荐用setTo,语义更明确)
cv::Mat gray_mat(3,3,CV_8UC1); gray_mat = cv::Scalar(255); // 把整个灰度矩阵设为白色
二、两种赋值方式的区别(以常见错误场景为例)
我猜你遇到的两种代码大概是下面这样——第一种能用,第二种却不符合预期:
正确的方式
cv::Mat mat(3,3,CV_8UC3); mat.setTo(cv::Scalar(0,255,0)); // 正确,整个矩阵变成绿色
错误的方式
cv::Mat mat(3,3,CV_8UC3); mat = cv::Scalar(0,255,0); // 错误,矩阵尺寸会被改变
为啥会这样?核心原因是两者的逻辑完全不同:
setTo()的作用就是给矩阵的所有元素统一赋值,不管矩阵是单通道还是多通道,它都会自动匹配通道数,把Scalar的每个分量对应到元素的每个通道上,而且不会改变矩阵的尺寸。- 而直接用
=赋值时,OpenCV会把cv::Scalar转换成一个1x1的多通道Mat,然后让原矩阵的头部指向这个新的小矩阵。也就是说,执行完mat = cv::Scalar(...)后,你的3x3矩阵就变成1x1的了,这显然不是你想要的“给整个矩阵填充值”的效果。
你可以跑个测试看看:
cv::Mat mat(3,3,CV_8UC3); std::cout << "赋值前尺寸:" << mat.size() << std::endl; // 输出 [3 x 3] mat = cv::Scalar(0,255,0); std::cout << "赋值后尺寸:" << mat.size() << std::endl; // 输出 [1 x 1]
而用setTo()的话,尺寸完全不会变,只是元素值被替换:
cv::Mat mat(3,3,CV_8UC3); std::cout << "赋值前尺寸:" << mat.size() << std::endl; // 输出 [3 x 3] mat.setTo(cv::Scalar(0,255,0)); std::cout << "赋值后尺寸:" << mat.size() << std::endl; // 还是 [3 x 3]
顺便提一句,单通道矩阵直接用等号赋值是可行的,因为OpenCV会做广播填充,但多通道下就踩坑了。所以不管哪种场景,都推荐用setTo()来统一赋值,避免出错~
内容的提问来源于stack exchange,提问作者BrainabilGH
相关产品推荐
相关产品推荐

