首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从cv::Mat获得cv::标量

从cv::Mat获得cv::标量
EN

Stack Overflow用户
提问于 2013-10-21 18:18:20
回答 4查看 2.9K关注 0票数 1

在读取了未知深度和信道数的图像后,我想逐一访问它的像素。

在opencv 1.x上,代码如下:

代码语言:javascript
复制
IplImage * I = cvLoadImage( "myimage.tif" );
CvScalar pixel = cvGet2D( I, y, x );

但是在OpenCV2.x上,cv::Mat.at()方法要求我知道图像的类型:

代码语言:javascript
复制
cv::Mat I = cv::imread( "myimage.tif" );
if( I.depth() == CV_8U && I.channels() == 3 )
    cv::Vec3b pixel = I.at<cv::Vec3b>( x, y );
else if( I.depth() == CV_32F && I.channels() == 1 )
    float pixel = I.at<cv::float>( x, y );

是否有一个类似于cvGet2D的函数可以在编译时接收cv::Mat并返回cv::Scalar而不知道图像的类型?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-10-31 22:14:13

对于C++的初学者来说.

...和/或一个只需要节省几秒钟代码输入就能完成 http://en.wikipedia.org/wiki/%C3%89variste_Galois的黑客

代码语言:javascript
复制
cv::Mat mat = ...; // something
cv::Scalar value = cv::mean(mat(cv::Rect(x, y, 1, 1)));

(免责声明:这段代码的浪费程度仅略低于为革命事业而死的年轻人。)

票数 2
EN

Stack Overflow用户

发布于 2013-10-22 08:14:10

简短的回答是否定的。在C++ API中没有这样的函数。

这背后的理由是性能。cv::Scalar (和CvScalar)和cv::Vec<double,4>是一样的。因此,对于除CV_64FC4以外的任何CV_64FC4类型,都需要进行转换才能获得cv::Scalar。此外,这个方法将是一个巨大的switch,就像在您的示例中(您只有两个分支)。

但是我想这个函数通常是很方便的,所以为什么不使用它呢?我的猜测是,人们会过度使用它,从而导致他们的算法性能非常差。因此,为了强制客户端代码使用静态类型的方法,OpenCV使得访问单个像素变得非常不方便。这并不是一件很方便的事情,因为通常情况下,你实际上是静态地知道这种类型的,从性能上来说,这是一个非常大的问题。所以,我认为这是一个很好的交换。

票数 2
EN

Stack Overflow用户

发布于 2013-10-22 14:41:24

我也有同样的问题,我只是想快速测试一些东西,而性能不是问题。但是代码的所有部分都使用cv::Mat()。我所做的是

代码语言:javascript
复制
Mat img;  // My input mat, initialized elsewhere

// Pretty fast operation, Will only create an iplHeader pointing to the data in the mat
// No data is copied and no memory is mallocated. 
// The Header resides on the stack (note its type is "IplImage" not "IplImage*")
IplImage iplImg = (IplImage)img;

// Then you may use the old (slow converting) legacy-functions if you like
CvScalar s = cvGet2D( &iplImg, y, x );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19501805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档