使用 c++ 和 opencv 计算 Mat 的大小和方向时出错

Posted

技术标签:

【中文标题】使用 c++ 和 opencv 计算 Mat 的大小和方向时出错【英文标题】:getting error in calculating the Magnitude and Orientation of a Mat Using c++ and opencv 【发布时间】:2014-02-19 13:29:21 【问题描述】:

我想获取图像中所有像素值的大小和方向。这是我到目前为止所做的:

cv::Sobel( dis, grad_x, dis.depth(), 1, 0, 3);     
cv::Sobel( dis, grad_y, dis.depth(), 0, 1, 3); 
Mat orientation(width, height, CV_32FC1);

#define PI 3.14159265
 for(int i = 0; i < grad_y.rows; ++i)
  for(int j= 0; j< grad_y.cols; ++j)
       orientation = atan( grad_y / grad_x ) * 180/PI ;
       magnitude= sqrt((grad_x)*(grad_x)+(grad_y)*(grad_y));
  
   

但我在 atan 和 sqrt 行中收到此错误:

error C2665: 'atan' : none of the 3 overloads could convert all the argument type   
 math.h(108):could be 'double atan(double)
 math.h(505):float atan(float)
 math.h(553):long double atan(long double)

有谁知道问题出在哪里?

提前谢谢...

-----------编辑后------------

#define PI 3.14159265
  for(int i=0; i<grad_y.rows; i++)
    for(int j=0; j<grad_y.cols; j++)
        orientation = atan( grad_y.at<float>(i,j) / grad_x.at<float>(i,j) ) * 180/PI ;
    

我把 sqrt 改成了这个,但还是报错:

 Mat magnitude(m_pmdDevice->GetY(), m_pmdDevice->GetX(), CV_32FC1);
    Mat gradAdd(m_pmdDevice->GetY(), m_pmdDevice->GetX(), CV_32FC1);
    grad_x = grad_x.mul(grad_x);
    grad_y = grad_y.mul(grad_y);
    cv::add(grad_x, grad_y, gradAdd);
    magnitude = sqrt(gradAdd);

【问题讨论】:

【参考方案1】:

atan 应该得到数字(double、float 或 long),但您提供的是矩阵。你应该使用

orientation = atan( grad_y.at<float>(i,j) / grad_x.at<float>(i,j) ) * 180/PI ;

我在示例中写了“float”,因为我不知道您实际使用的是什么类型。必要时更换。

sqrt 中的同样问题。

编辑(问题编辑后):

您以错误的方式使用 sqrt。请参阅其documentation。应该是:

sqrt(gradAdd, magnitude);

更好的是使用函数magnitude 而不是所有的乘法和平方根:

magnitude(grad_x, grad_y, magnit);

另外我建议你不要给作为 OpenCV 函数的矩阵命名。这会造成混乱。

【讨论】:

谢谢,但我无法解决 sqrt 的问题。让我编辑帖子,请让我知道是什么问题..提前谢谢..【参考方案2】:

问题出在下面一行:

orientation = atan( grad_y / grad_x ) * 180/PI ;

因为 Orientation 是 Mat 类型并且应该包含浮点值(因为您已将其声明为 CV_32FC1)所以,您不能将值直接放入其中。你应该这样做:

 orientation.at<float>(i,j) = (float)atan( grad_y / grad_x ) * 180/PI ;

PS:只需一次,如何将单个值放入矩阵中

【讨论】:

【参考方案3】:

使用以下代码进行元素计算,以获得方向和大小。如果您想使用上面答案中定义的函数,请使用幅度

     cv::Sobel( dis, grad_x, CV_32F, 1, 0, 3);     
     cv::Sobel( dis, grad_y, CV_32F, 0, 1, 3); 
     Mat orientation(width, height, CV_32FC1);
     Mat magnitude(width, height, CV_32FC1);
     for(int i = 0; i < grad_y.rows; ++i)
     for(int j= 0; j< grad_y.cols; ++j)
     
      orientation.at<float>(i,j) = atan2(grad_y.at<float>(i,j),grad_x.at<float>(i,j) ) * 180/PI ;
       magnitude.at<float>(i,j)= sqrt(grad_x.at<float>(i,j)*grad_x.at<float>(i,j)+grad_y.at<float>(i,j)*grad_y.at<float>(i,j));
      

请查看您是否将矩阵定义为 CV_8UC1,然后将 sqrt 的类型转换参数定义为 float/double,因为它仅定义为 float/double 而不是整数

【讨论】:

以上是关于使用 c++ 和 opencv 计算 Mat 的大小和方向时出错的主要内容,如果未能解决你的问题,请参考以下文章

计算 Mat OpenCV 子集的总和

FFTW 和 OpenCV 的 C++ 接口,Mat 输出中的实部和虚部

C++ OpenCV Mat 像素值和 OpenCV 错误

将 c++ opencv IplImage imageData 和 widthStep 转换为 android opencv Mat

OpenCV大型阵列类型Mat类

OpenCV C++ 使用高斯核函数计算晕影效果