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<int>(i,j)
的cout
不应该是Image.at<int>(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除了我对罗宾回答的评论之外,您的错误是您尝试将 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<unsigned char>(j,i)
而不是 Image.at<unsigned char>(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<int>(j,i) >= 150 )
替换if ( Image.at<int>(i,j) >= 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)