使用OpenCV的Sobel操作计算图像梯度方向 [英] Calculating image gradient direction using OpenCV's Sobel operation

查看:444
本文介绍了使用OpenCV的Sobel操作计算图像梯度方向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用OpenCV的Sobel方法的结果来确定图像梯度方向。



我理解这应该是一个非常简单的任务,我认为我理解这个理论,但实现这一点比我想象的更具挑战性。



我希望梯度方向在0-360度之间,但是我的代码显示所有的梯度在180 - 270度之间。



提交了此代码的以前版本,其中包括整数除法问题。我已经解决了这个问题,但它没有解决限制角度方向的问题。



我已经走过所有的代码,但我只是看不到我的方向, m错了?任何人都可以发现我的错误?



谢谢。

  void getGradients IplImage * original,cv :: Mat * gradArray)
{
cv :: Mat original_Mat(original,true);

//将其转换为灰色
cv :: cvtColor(original_Mat,original_Mat,CV_RGB2GRAY);
// cv :: blur(original_Mat,original_Mat,cv :: Size(7,7));

///生成grad_x和grad_y
cv :: Mat grad_x = cv :: Mat :: zeros(original-> height,original-> width,CV_16S);
cv :: Mat grad_y = cv :: Mat :: zeros(original-> height,original-> width,CV_16S);

///渐变X
cv :: Sobel(original_Mat,grad_x,CV_16S,1,0,3);

///渐变Y
cv :: Sobel(original_Mat,grad_y,CV_16S,0,1,3);

uchar * pixelX = grad_x.data;
uchar * pixelY = grad_y.data;
uchar * grad1 = gradArray [0] .data;
uchar * grad2 = gradArray [1] .data;
uchar * grad3 = gradArray [2] .data;
uchar * grad4 = gradArray [3] .data;
uchar * grad5 = gradArray [4] .data;
uchar * grad6 = gradArray [5] .data;
uchar * grad7 = gradArray [6] .data;
uchar * grad8 = gradArray [7] .data;
int count = 0;
int min = 999999;
int max = -1;

for(int i = 0; i< grad_x.rows * grad_x.cols; i ++)
{
double directionRAD = atan2(pixelY [i],pixelX [i ]);
int directionDEG =(int)(180 + directionRAD / M_PI * 180);

if(directionDEG if(directionDEG> max){max = directionDEG;}

if(directionDEG> ; = 0&& directionDEG <= 45){grad1 [i] = 255; count ++;}
if(directionDEG> = 45&& directionDEG< = 90){grad2 [i] = 255; count ++;}
if(directionDEG> = 90&& directionDEG< = 135){grad3 [i] = 255; count ++;}
if(directionDEG> = 135&& directionDEG< = 190){grad4 [i] = 255; count ++;}
if(directionDEG> = 190&& directionDEG< = 225){grad5 [i] = 255; count ++;}
if(directionDEG> = 225&& directionDEG< = 270){grad6 [i] = 255; count ++;}
if(directionDEG> = 270&& directionDEG< = 315){grad7 [i] = 255; count ++;}
if(directionDEG> = 315&& directionDEG< = 360){grad8 [i] = 255; count ++;}

if(directionDEG <0 || directionDEG> 360)
{
cout<<方法中给出的奇怪梯度方向:getGradients。
}

}

}

解决方案

grad_x grad_y

但是,您声明了 pixelX pixelY 指向8位字节的指针。因此 pixelX [1] 是第一个渐变的第二个字节,而不是第二个渐变。



  short * pixelX = grad_x.ptr< short>(0); 
short * pixelY = grad_y.ptr< short>(0);


I am attempting to determine the image gradient direction using the results from OpenCV's Sobel method.

I understand this should be a very simple task, I think I understand the theory but implementing this has been more challenging than I thought.

I would expect the gradient directions to be between 0-360 degrees, however my code shows all gradients fall between 180 - 270 degrees.

I submitted a previous version of this code which included an integer division issue. I have fixed this but it has not solved the problem of a restricted angle of direction.

I have stepped through all the code but I just can't see where I'm going wrong? Can anyone spot my mistake?

Thanks.

void getGradients(IplImage* original, cv::Mat* gradArray)
{
cv::Mat original_Mat(original, true);

// Convert it to gray
cv::cvtColor( original_Mat, original_Mat, CV_RGB2GRAY );
//cv::blur(original_Mat, original_Mat, cv::Size(7,7));

/// Generate grad_x and grad_y
cv::Mat grad_x = cv::Mat::zeros(original->height, original->width, CV_16S); 
cv::Mat grad_y = cv::Mat::zeros(original->height, original->width, CV_16S);

/// Gradient X
cv::Sobel(original_Mat, grad_x, CV_16S, 1, 0, 3);

/// Gradient Y
cv::Sobel(original_Mat, grad_y, CV_16S, 0, 1, 3);

uchar* pixelX = grad_x.data;
uchar* pixelY = grad_y.data;
uchar* grad1 = gradArray[0].data;
uchar* grad2 = gradArray[1].data;
uchar* grad3 = gradArray[2].data;
uchar* grad4 = gradArray[3].data;
uchar* grad5 = gradArray[4].data;
uchar* grad6 = gradArray[5].data;
uchar* grad7 = gradArray[6].data;
uchar* grad8 = gradArray[7].data;
int count = 0;
int min = 999999;
int max = -1;

for(int i = 0; i < grad_x.rows * grad_x.cols; i++) 
{
        double directionRAD = atan2(pixelY[i], pixelX[i]);
        int directionDEG = (int)(180 + directionRAD / M_PI * 180);

        if(directionDEG < min){min = directionDEG;}
        if(directionDEG > max){max = directionDEG;}

        if(directionDEG >= 0 && directionDEG <= 45)         { grad1[i] = 255; count++;}         
        if(directionDEG >= 45 && directionDEG <= 90)        { grad2[i] = 255; count++;}         
        if(directionDEG >= 90 && directionDEG <= 135)       { grad3[i] = 255; count++;}         
        if(directionDEG >= 135 && directionDEG <= 190)      { grad4[i] = 255; count++;}         
        if(directionDEG >= 190 && directionDEG <= 225)      { grad5[i] = 255; count++;}         
        if(directionDEG >= 225 && directionDEG <= 270)      { grad6[i] = 255; count++;}     
        if(directionDEG >= 270 && directionDEG <= 315)      { grad7[i] = 255; count++;}
        if(directionDEG >= 315 && directionDEG <= 360)      { grad8[i] = 255; count++;}

        if(directionDEG < 0 || directionDEG > 360)
        {
            cout<<"Weird gradient direction given in method: getGradients.";
        }

}

}

解决方案

grad_x and grad_y are Mats of type CV_16SC1, that is every pixel in them takes up two bytes.

However you declare pixelX and pixelY to pointers to 8 bit bytes. Therefore pixelX[1] is the second byte of the first gradient, rather than the second gradient.

You need

short* pixelX = grad_x.ptr<short>(0);
short* pixelY = grad_y.ptr<short>(0);

这篇关于使用OpenCV的Sobel操作计算图像梯度方向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆