OpenCV:读取矩阵值

Posted

技术标签:

【中文标题】OpenCV:读取矩阵值【英文标题】:OpenCV: read matrix value 【发布时间】:2012-08-22 09:29:35 【问题描述】:

我想计算只有黑白的背景图像中白点的数量。我有这样的代码:

int count = 0; 
for ( int j = 0; j < Image.rows; j ++ )
    
    for ( int i = 0; i < Image.cols; i ++ )
        
            if ( Image.at<int>(i,j) >= 150 )
            
                count ++ ;
            
        
    

由于某种原因,上面的代码不起作用,它只是停止反应。我检查了一下,“if (Image.at(i,j) >= 150)”行导致了问题。我的“图像”是“cv::Mat”,类型为“CV_8UC3”。有人可以帮助我吗?谢谢你。

【问题讨论】:

做一个Image.at&lt;int&gt;(i,j)的cout 不应该是Image.at&lt;int&gt;(j,i)吗? 非常感谢您的回复。 cout 部分结果是这样的: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1109311264,11117845974,9668574984 ,0,0,0,0,0,0,0,0,0,0,0,0,2514654812,1101231542,121415421,0,0,0,0,0,0,0... 我改了进入“Image.at(j,i)”,cout的输出是这样的:7745580006,-1869970562,1835821674,-1987475062,...有什么想法吗? 【参考方案1】:

除了我对罗宾回答的评论之外,您的错误是您尝试将 CV_8UC3 类型的图像作为整数访问。如果您想检查灰度,请执行以下操作(注意“unsigned char”而不是“int”,如 Robin 的回答)。

cv::Mat greyscale;
cv::cvtColor(image,grayscale,CV_RGB2GRAY);
// either, most elegant:
int count = cv::countNonZero(greyscale >= 150);
// or, copied from Robin's answer:
int count = 0;
for(int i = 0; i < greyscale.rows; ++i) 
    const unsigned char* row = greyscale.ptr<unsigned char>(i);
    for(int j = 0; j < greyscale.cols; j++) 
        if (row[j] >= 150)
            ++count;
    

【讨论】:

亲爱的 Etarion、Robin 和所有其他回答我问题的人,非常感谢您的帮助。现在它工作正常。我使用了最后提供的代码 Etarion。最好的问候。 感谢您引用我^_^【参考方案2】:

我相信这更整洁:

Mat result;
threshold(Image,result,150,255,THRESH_BINARY);
int white_count = countNonZero(result);

【讨论】:

是的,这确实非常有效。谢谢你:) 这很可能是最快的方法 - 阈值和 countNonZero 比 for 循环方法优化得更好 @ederman 不客气。我不明白,如果它有帮助,为什么要投反对票? (与谁有关!) @Kamyar,我没有投反对票,我选择了 Robin 的答案作为参考,然后也将您的答案投票为有用。我在这里错过了什么吗?请不要误会什么。谢谢。 @ederman,我知道! :) 我说的是做这件事的人。我注意到:它与谁有关。无论如何,如果它对任何人都有帮助,我很高兴......【参考方案3】:

如果您使用 i 表示列,使用 j 表示行,请写 Image.at&lt;unsigned char&gt;(j,i) 而不是 Image.at&lt;unsigned char&gt;(i,j)

【讨论】:

我最后把它改成了 (j,i),谢谢你为我指出这个错误。然后我使用了其他朋友在这里提供的“countNonZero”方法。谢谢你的回答。 Sammy,你是不是在吃药? :) Mai bine da-mi si mie un up! :) iti fac up, daca schimbi int cu uchar, ca asa nu merge ;) Si-apoi ma mai Relaxez si eu, ca pe mine nu ma pandeste nimeni【参考方案4】:

我认为您必须访问列之前的行,这意味着您应该交换 i 和 j。 用if ( Image.at&lt;int&gt;(j,i) &gt;= 150 )替换if ( Image.at&lt;int&gt;(i,j) &gt;= 150 )

虽然有更简单的方法可以访问 Mat。 OpenCV 提供了一个类似 STL 的迭代器,它易于使用,如果您想访问所有元素,则非常易于使用。示例:

int count = 0;
MatConstIterator_<int> it = Image.begin<int>(), it_end = Image.end<int>();
for(; it != it_end; ++it)
    if ((*it) >= 150)
        ++count;

最后但同样重要的是,您还可以获得指向每一行的指针并通过普通的 [] 运算符访问数据:

int count = 0;
for(int i = 0; i < Image.rows; ++i) 
    const int* Ii = Image.ptr<int>(i);
    for(int j = 0; j < Image.cols; j++) 
        if (Ii[j] >= 150)
            ++count;
    

【讨论】:

感谢罗宾的回答。我尝试了迭代器,但是对于“if((*it) >=15)”行,它给出了一个错误,说“没有运算符 >= 匹配这些操作数”。 比你的第一种方法更容易,cv::Mat tmp; cv::threshold(image, tmp, 150, 1, cv::THRESH_BINARY); count = cv::countNonZero(tmp);【参考方案5】:

您可以使用 opencv 字节向量(无符号字符像素)访问 CV_8UC3 像素! 在这种情况下,您可以进行以下操作(现在您还可以使用一些特殊的颜色阈值)

int channel = 0;
Image.at<Vec3b>( row , col )[channel]

【讨论】:

谢谢你的回答,现在我学会了如何使用颜色阈值:)【参考方案6】:

有很多方法可以访问 cv::Mat 图像, 如果你想直接访问彩色图像(CV_8UC3), 它可以通过以下方式实现:

int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) 
   for(int i = 0; i < img.cols; i++) 
      //white point which means that the point in every channel(BGR)
      //are all higher than threshold!
      if(img.ptr<cv::Vec3b>(j)[i][0] > threshold && 
         img.ptr<cv::Vec3b>(j)[i][1] > threshold 
         img.ptr<cv::Vec3b>(j)[i][2] > threshold ) 
             count++;
         

    
 

但我建议如果你只想计算白点,你可以将图像转换为灰度 (CV_8UC1),并执行以下操作:

cv::Mat img;
cv::cvtColor(src,img,CV_BGR2RGB);
int count = 0;
int threshold = 150;
for(int j = 0; j < img.rows; j++) 
   for(int i = 0; i < img.cols; i++) 
      if(img.ptr<uchar>(j)[i] > threshold) 
            count++;
      
   

最后要注意,通过img.ptrImagetype>访问cv::Mat image不会检查访问点是否正确,所以如果你肯定知道image的范围,访问ptr 的图像就可以了,否则,你可以通过 img.at() 来做,它会在每次调用时检查每个点是否正确,why access image by ptr is faster 所以如果有无效的访问点,它会断言你!

【讨论】:

以上是关于OpenCV:读取矩阵值的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 读取图像并使用整数值管理它们的像素(如 matlab)

opencv中16位的矩阵保存成图像,最大灰度值只有32768

如何用opencv提取一张图片的像素矩阵

求用opencv把摄像头读取的图像转换成矩阵形式的代码

求用opencv把摄像头读取的图像转换成矩阵形式的代码

JAVA 图像处理基于OpenCv与JVM-----矩阵处理图像