OpenCV的cv::Mat如何创建多通道矩阵的'ones'?

12

在使用OpenCV中的1通道(例如CV_8UC1)Mat对象时,可以创建一个全为1的Mat:cv::Mat img = cv::Mat::ones(x,y,CV_8UC1)

然而,当使用3通道图像(例如CV_8UC3)时,情况会变得有些复杂。执行cv::Mat img = cv::Mat::ones(x,y,CV_8UC3)会将1放入通道0,但通道1和2包含0那么,如何在多通道图像中使用cv::Mat::ones()呢?

以下是一些代码,可帮助您了解我的意思:

void testOnes() {
 int x=2; int y=2; //arbitrary

 // 1 channel
 cv::Mat img_C1 = cv::Mat::ones(x,y,CV_8UC1);
 uchar px1 = img_C1.at<uchar>(0,0); //not sure of correct data type for px in 1-channel img
 printf("px of 1-channel img: %d \n", (int)px1); //prints 1

 // 3 channels
 cv::Mat img_C3 = cv::Mat::ones(x,y,CV_8UC3); //note 8UC3 instead of 8UC1
 cv::Vec3b px3 = img_C3.at<cv::Vec3b>(0,0);
 printf("px of 3-channel img: %d %d %d \n", (int)px3[0], (int)px3[1], (int)px3[2]); //prints 1 0 0
}

所以,我本来期望看到这样的输出:3通道图片的像素值:1 1 1,但实际上我看到了这个:3通道图片的像素值:1 0 0

附言:在发布帖子之前,我进行了大量搜索。但是通过搜索“[opencv] Mat::ones”或“[opencv] +mat +ones”无法解决这个问题。


1
附注:我不确定在单通道图像像素中是否应该使用uchar代替cv :: Vec3b。 OpenCV提供了许多2、3和4项向量类,但没有单例的类比。 (在此页面上搜索“Vec3b”:http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#vec) - solvingPuzzles
2个回答

9
我不使用OpenCV,但我相信我知道这里发生了什么。您定义了一个数据类型,但您正在请求该值的'1'。 Mat类似乎没有注意到您有一个多通道数据类型,因此它将'1'简单地转换为3字节的无符号字符。
因此,不要使用ones函数,只需使用标量构造函数即可:
cv::Mat img_C3( x, y, CV_8UC3, CV_RGB(1,1,1) );

我刚试了一下你的解决方案。cv::Mat img_C3 = cv::Mat::ones(x,y,CV_8UC3) * CV_RGB(1,1,1);无法编译,因为cv::Mat类型没有重载运算符*cv::Mat img_C3( x,y,CV_8UC3,CV_RGB(1,1,1) );可以编译,但它将像素通道定义为1 0 0,就像我问题中的ones示例一样。我现在正在深入研究你的答案。 - solvingPuzzles
2
哦,等等,cv::Mat img_C3( x,y,CV_8UC3,CV_RGB(1,1,1) ); 确实可以正常工作! - solvingPuzzles
当我执行以下代码时:cv::Mat img_C3 = cv::Mat::ones(x,y,CV_8UC3) * CV_RGB(1,1,1);,代码会输出 px of 3-channel img: 255 0 0。问题的一部分是,如果我们从值为{1,0,0}的像素开始,将图像乘以一个数字会得到{ n,0,0 }。然而,我错了,关于 * 运算符没有被重载--当乘以原始数据类型时,它显然是有效的。感谢您的跟进和花费这么多时间。 :) - solvingPuzzles
嗯,这很奇怪。在这种情况下,它似乎正在进行单个通道的乘法并夹紧结果。无论如何,那个“ones”方法远不如使用标量构造函数好。所以对你来说是双赢 =) - paddy
1
没问题。由于某种原因,我又没有看到你的编辑。无论如何,我刚刚删除了另一个选项。那个选项很愚蠢。此外,我随后读到使用 * 运算符实际上并不会立即进行乘法运算。它会存储一个缩放因子以供以后使用。听起来有些可疑。 - paddy
显示剩余2条评论

2
您也可以这样初始化:
Mat img;

/// Lots of stuff here ...

// Need to initialize again for some reason:
img = Mat::Mat(Size(width, height), CV_8UC3, CV_RGB(255,255,255));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接