OpenCV: read matrix value

两盒软妹~` 提交于 2019-12-19 09:11:21

问题


I want to count the number of white points in a background image which is only black and white. I have a code like this:

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

For some reason, the above code doesn't work, it just stops reacting. I checked, and the line" if ( Image.at(i,j) >= 150 ) " causes the problem. My "Image" is a "cv::Mat", with "CV_8UC3" type. Is there someone can help me? Thank you.


回答1:


In addition to my comment to Robin's answer, your error is that you try to access an image of CV_8UC3 type as ints. If you want to check grey levels, do something like this (note the "unsigned char" instead of "int", as in Robin's answer).

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



回答2:


I believe this is much neater:

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



回答3:


Write Image.at<unsigned char>(j,i) not Image.at<unsigned char>(i,j) if you are using i for cols and j for rows.




回答4:


I think you have to access the row before the column, meaning you should swap i and j.
Substitute if ( Image.at<int>(i,j) >= 150 ) with if ( Image.at<int>(j,i) >= 150 )

There are easier ways to access a Mat though.
OpenCV provides an STL-like iterator which is easy to use and if you want to access all the elements very easy to use. Example:

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

Last but not least you could also get a pointer to each row and access the data via the plain [] operator:

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



回答5:


you could access the CV_8UC3 Pixels with opencv bytes vectors (unsigned char pixels) ! In this case you can make the following (now you could also use some special color threshold)

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



回答6:


There are a lot of methods to access the cv::Mat image, if you want to directly access the color image(CV_8UC3), it could be implemented by following:

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

    }
 }

but I recommend that if you only want to count white points, you can just convert image into grayscale (CV_8UC1), and do as following:

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

Finally, note that access cv::Mat image by img.ptr< Imagetype> will not check the accessed point is correct, so if you certainly know the range of image, the access image by ptr will be fine, otherwise, you can do by img.at< Imagetype>(), it will check every point is correct at every call,why access image by ptr is faster so if there are invalid accessed point, it will assert you!



来源:https://stackoverflow.com/questions/12070139/opencv-read-matrix-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!