我想计算背景图像中只有黑色和白色的白点数。我有这样的代码:
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)&gt; = 150)”这一行导致了问题。我的“图像”是“cv :: Mat”,带有“CV_8UC3”类型。有人可以帮助我吗?谢谢。
答案 0 :(得分:11)
除了我对Robin的答案的评论之外,您的错误是您尝试以int为单位访问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;
}
}
答案 1 :(得分:5)
我相信这更整洁:
Mat result;
threshold(Image,result,150,255,THRESH_BINARY);
int white_count = countNonZero(result);
答案 2 :(得分:3)
如果您将i用于cols而j用于行,则将Image.at<unsigned char>(j,i)
写为Image.at<unsigned char>(i,j)
。
答案 3 :(得分:2)
我认为您必须访问该列之前的行,这意味着您应该交换i和j。
用if ( Image.at<int>(i,j) >= 150 )
if ( Image.at<int>(j,i) >= 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;
最后但并非最不重要的是,您还可以获得指向每一行的指针并通过plain []运算符访问数据:
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;
}
}
答案 4 :(得分:1)
您可以使用opencv字节向量(无符号字符像素)访问CV_8UC3像素! 在这种情况下,您可以进行以下操作(现在您也可以使用一些特殊颜色阈值)
int channel = 0;
Image.at<Vec3b>( row , col )[channel]
答案 5 :(得分:1)
有很多方法可以访问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.ptr&lt;访问cv :: Mat图像Imagetype&gt; 不会检查访问点是否正确,因此如果您确定知道图像的范围,则通过ptr访问图像会很好,否则,您可以通过 img来完成。在&LT; Imagetype&gt;(),它会在每次调用时检查每个点是否正确,why access image by ptr is faster 所以如果有无效的访问点,它会断言你!