确定 OpenCV 中矩阵的类型

Determining the type of Matrix in OpenCV

本文关键字:类型 OpenCV 确定      更新时间:2023-10-16

我正在尝试在opencv中索引3通道图像。

当我读入图像文件时,这段代码有效

int Blue  = LeftCol.at<cv::Vec3b>(v,u)[0];
int Green = LeftCol.at<cv::Vec3b>(v,u)[1]; 
int Red   = LeftCol.at<cv::Vec3b>(v,u)[2]; 

但是当我使用网络摄像头输入时它会崩溃。网络摄像头有 3 个频道,u,v0,0 开始。我不知道为什么它不起作用。我已经尝试了Vec3bVec3iVec3sVec3fVec3d的所有变体

我迷路了....为什么我无法索引此网络摄像头图像?

编辑

几个小时后,这就是我必须去的地方......以下是该计划的概述。我在函数中遇到了上面提到的问题。所以我回到了基础,试图在函数之前查看矩阵......

void main (int argc, char** argv) {
Mat LeftCol;
while (1==1) {
    if (ProgramMode == "Files") {
        //read in the colour images
        LeftCol  = imread(ColImLeft.c_str(),1);
        RightCol = imread(ColImRight.c_str(),1);
    } else if (ProgramMode == "Camera") {
        VideoCapture CapLeft, CapRight;
        CapLeft.open(1);
        CapRight.open(2);
        CapLeft  >> LeftCol;
        CapRight >> RightCol;
                    //THIS WORKS, THIS PIXEL VALUES ARE DISPLAYED
        cout << "uchar" << endl;
        for (int x=0;x<10;x++) {
            for (int y=0;y<10;y++) {
                int pixel = LeftCol.at<cv::Vec3b>(x,y)[0];
                cout << pixel;
            }
            cout << endl;
        }
    } //end if
            ///////ADDED THIS BIT ////////
    cout << "channels = " << LeftCol.channels() << endl;
            //^^This bit works, output shows "channels = 3"
            //vv This bit doesn't work.... so there's a problem with LeftCol.
            //I wonder if reading the data like CapLeft  >> LeftCol; is changing something
    imshow("Test",LeftCol);
            ///////ADDED THIS BIT ////////
           //THIS DOES NOT WORK WHEN USING THE CAMERA INPUT, PROGRAM CRASHES
    cout << "uchar" << endl;
    for (int x=0;x<10;x++) {
        for (int y=0;y<10;y++) {
            int pixel = LeftCol.at<cv::Vec3b>(x,y)[0];
            cout << pixel;
        } //end for
        cout << endl;
    } //end for
   } //end while
} //end main

是的,我已经让它工作了,但它并不理想。我正在创建一个临时Mat来读取文件,然后克隆它们。

        Mat TempLeft;
        Mat TempRight;
        VideoCapture CapLeft, CapRight;
        CapLeft.open(1);
        CapRight.open(2);
        CapLeft  >> TempLeft;
        CapRight >> TempRight;
        LeftCol = TempLeft.clone();
        RightCol = TempRight.clone();

OpenCV尽可能制作图像的软拷贝。从文档中:

数组赋值是一个 O(1) 操作,因为它只复制标头并增加引用计数器。Mat::clone() 方法可用于在需要时获取数组的完整(深度)副本。

我怀疑正在发生的事情是LeftCol使用仍然属于VideoCapture对象的数据。如果是这种情况,那么当CapLeftCapRightif结束时超出范围时,它们将被析构函数关闭,并且LeftCol仍然指向的图像数据将被销毁。

可能的解决方案是像您正在做的那样克隆映像,或者在 if 块之外声明VideoCapture CapLeft, CapRight;(如果需要,您仍然可以在内部打开它们)。

您可以使用 cv::Mat.type() 检查类型,使用 cv::Mat.channels() 检查通道数

从相机返回的数据将按 B、G、R 顺序转换为 Vec3b(即 uchar * 3)。

您确定图像有效吗 - 其他地方是否有错误?

仅仅因为您尝试了所有 Vec* 组合,这里是完整列表,我的 2ct:

typedef Vec< uchar, 3 >     Vec3b   (so normal 8 bit)
typedef Vec< double,3 >     Vec3d   (so normal double precision)
typedef Vec< float, 3 >     Vec3f   (so normal floating point)
typedef Vec< int,   3 >     Vec3i   (normal int)
typedef Vec< short, 3 >     Vec3s
typedef Vec< ushort 3 >     Vec3w   (so normal 16 bit)