OpenCV的:读取矩阵值(OpenCV: read matrix value)

2019-06-27 06:11发布

我希望计算的背景图像是只有黑色和白色的白点的数量。 我有这样的代码:

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 ++ ;
            }
        }
    }

出于某种原因,上面的代码不工作,它只是停止反应。 余检查,行 “如果(Image.at(I,J)> = 150)” 导致该问题。 我的“形象”是一个“CV ::垫”,用“CV_8UC3”型。 有没有人能帮助我吗? 谢谢。

Answer 1:

另外我对罗宾的答案评论,你的错误是您尝试访问CV_8UC3类型的图像为整数。 如果您想检查灰度级,这样做(注意“无符号的字符”,而不是“INT”,在罗宾的答案)。

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;
    }
}


Answer 2:

我相信这是非常巧妙:

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


Answer 3:

Image.at<unsigned char>(j,i)Image.at<unsigned char>(i,j)如果使用的是我为COLS和j为行。



Answer 4:

我认为你有列之前访问行,这意味着你应该交换i和j。
替代if ( Image.at<int>(i,j) >= 150 )if ( Image.at<int>(j,i) >= 150 )

有虽则访问垫更简单的方法。
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;
    }
}


Answer 5:

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

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


Answer 6:

有很多的方法来访问CV ::垫的形象,如果你想直接访问彩色图像(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++;
      }
   }
}

最后,注意,使用CV ::通过img.ptr垫图像< IMAGETYPE >将无法检查访问点是正确的,所以如果你当然知道图像的范围内,通过PTR的接入图像将被罚款,否则,你可以做通过img.at <IMAGETYPE>(),它会检查每个点是正确的,在每一个电话, 通过PTR为什么访问图像速度更快 ,所以如果有无效的访问点,它会断言你!



文章来源: OpenCV: read matrix value