计算c+中的梯度方向+;使用opencv函数

计算c+中的梯度方向+;使用opencv函数,opencv,Opencv,有人能帮我解决这个问题吗 我正在尝试使用OpenCV中的Sobel操作符计算x和y方向的渐变方向。我使用atan2函数来计算以弧度为单位的切线,稍后将其转换为度,但我得到的所有角度都在0到90度之间 我的期望是得到0到360度之间的角度。我使用的是灰度图像。下面是代码段 Mat PeripheralArea; Mat grad_x, grad_y; // this is the matrix for the gradients in x and y directions int off_set

有人能帮我解决这个问题吗

我正在尝试使用OpenCV中的Sobel操作符计算x和y方向的渐变方向。我使用atan2函数来计算以弧度为单位的切线,稍后将其转换为度,但我得到的所有角度都在0到90度之间

我的期望是得到0到360度之间的角度。我使用的是灰度图像。下面是代码段

Mat PeripheralArea;
Mat grad_x, grad_y;  // this is the matrix for the gradients in x and y directions
int off_set_y = 0, off_set_x = 0;
int scale = 1, num_bins = 8, bin = 0;
int delta=-1 ;
int ddepth = CV_16S;

GaussianBlur(PeripheralArea, PeripheralArea, Size(3, 3), 0, 0, BORDER_DEFAULT);
Sobel(PeripheralArea, grad_y, ddepth, 0, 1,3,scale, delta, BORDER_DEFAULT);
Sobel(PeripheralArea, grad_x, ddepth, 1, 0,3, scale, delta, BORDER_DEFAULT);

for (int row_y1 = 0, row_y2 = 0; row_y1 < grad_y.rows / 5, row_y2 < grad_x.rows / 5; row_y1++, row_y2++) {
    for (int col_x1 = 0, col_x2 = 0; col_x1 < grad_y.cols / 5, col_x2 < grad_x.cols / 5; col_x1++, col_x2++) {
        gradient_direction_radians = (double) atan2((double) grad_y.at<uchar>(row_y1 + off_set_y, col_x1 + off_set_x), (double) grad_x.at<uchar>(row_y2 + off_set_y, col_x2 + off_set_x));
        gradient_direction_degrees = (int) (180 * gradient_direction_radians / 3.1415);
        gradient_direction_degrees = gradient_direction_degrees < 0
                                     ? gradient_direction_degrees+360
                                     : gradient_direction_degrees;

    }

}
Mat外围设备区域;
材料梯度x,梯度y;//这是x和y方向梯度的矩阵
int off_set_y=0,off_set_x=0;
int scale=1,num_bins=8,bin=0;
int delta=-1;
int ddepth=CV_16S;
GaussianBlur(PeripheralArea,PeripheralArea,大小(3,3),0,0,边框_默认值);
Sobel(外围区域、梯度、深度、0、1、3、比例、增量、边界默认值);
Sobel(外围区域、梯度、深度、1、0、3、比例、增量、边界默认值);
对于(int row_y1=0,row_y2=0;row_y1
注意
off\u set\u x
off\u set\u y
变量不是计算的一部分 但要偏移到我最终想要的不同的方块
计算直方图特征向量

您已指定
Sobel()
的目标深度为
CV\u 16S
。 然而,当您访问
grad_x
grad_y
时,您使用
.at()
,这意味着它们的元素是8位无符号量,而实际上它们是16位有符号的。您可以使用
.at()
,但在我看来,您的代码似乎存在许多问题,其中最重要的一点是,OpenCV函数完全满足您的需要

使用,并将for循环替换为

    cv::Mat gradient_angle_degrees;
    bool angleInDegrees = true;

    cv::phase(grad_x, grad_y, gradient_angle_degrees, angleInDegrees);

我在用C++进行边缘检测时,解决了这个问题。 对于渐变方向,我使用artan2(),这个标准API定义它的+y和+x,与我们通常遍历2D图像的方式相同

画出来让你看看我的理解

///////////////////////////////
// Quadrants of image:
// 3(-dx,-dy) | 4(+dx,-dy)      [-pi,0]
// ------------------------->+x
// 2(-dx,+dy) | 1(+dx,+dy)      [0,pi]
//            v
//            +y
///////////////////////////////
// Definition of arctan2():
// -135(-dx,-dy) | -45(+dx,-dy)
// ------------------------->+x
//  135(-dx,+dy) | +45(+dx,+dy)
//               v
//               +y
///////////////////////////////
我如何处理渐变:

bool gradient(double*& magnitude, double*& orientation, double* src, int width, int height, string file) {
if (src == NULL)
    return false;
if (width <= 0 || height <= 0)
    return false;

double gradient_x_correlation[3*3] = {-0.5, 0.0, 0.5,
                                      -0.5, 0.0, 0.5,
                                      -0.5, 0.0, 0.5};
double gradient_y_correlation[3*3] = {-0.5,-0.5,-0.5,
                                       0.0, 0.0, 0.0,
                                       0.5, 0.5, 0.5};

double *Gx = NULL;
double *Gy = NULL;

this->correlation(Gx, src, gradient_x_correlation, width, height, 3);
this->correlation(Gy, src, gradient_y_correlation, width, height, 3);

if (Gx == NULL || Gy == NULL) 
    return false;

//magnitude
magnitude = new double[sizeof(double)*width*height];
if (magnitude == NULL)
    return false;
memset(magnitude, 0, sizeof(double)*width*height);
double gx = 0.0;
double gy = 0.0;
double gm = 0.0; 
for (int j=0; j<height; j++) {
    for (int i=0; i<width; i++) {
        gx = pow(Gx[i+j*width],2);
        gy = pow(Gy[i+j*width],2);
        gm = sqrt(pow(Gx[i+j*width],2)+pow(Gy[i+j*width],2));
        if (gm >= 255.0) {
            return false;
        }
        magnitude[i+j*width] = gm;
    }
}

//orientation
orientation = new double[sizeof(double)*width*height];
if (orientation == NULL)
    return false;
memset(orientation, 0, sizeof(double)*width*height);
double ori = 0.0;

double dtmp = 0.0;
double ori_normalized = 0.0;
for (int j=0; j<height; j++) {
    for (int i=0; i<width; i++) {
        gx = (Gx[i+j*width]);
        gy = (Gy[i+j*width]);
        ori = atan2(Gy[i+j*width], Gx[i+j*width])/PI*(180.0); //[-pi,+pi]
        if (gx >= 0 && gy >= 0) { //[Qudrant 1]:[0,90] to be [0,63] 
            if (ori < 0) {
                printf("[Err1QUA]ori:%.1f\n", ori);
                return false;
            }
            ori_normalized = (ori)*255.0/360.0; 
            if (ori != 0.0 && dtmp != ori) {
                printf("[Qudrant 1]orientation: %.1f to be %.1f(%d)\n", ori, ori_normalized, (uint8_t)ori_normalized);
                dtmp = ori;
            }
        }
        else if (gx >= 0 && gy < 0) { //[Qudrant 4]:[270,360) equal to [-90, 0) to be [191,255]
            if (ori > 0) {
                printf("[Err4QUA]orientation:%.1f\n", ori);
                return false;
            }
            ori_normalized = (360.0+ori)*255.0/360.0;
            if (ori != 0.0 && dtmp != ori) {
                printf("[Qudrant 4]orientation:%.1f to be %.1f(%d)\n", ori, ori_normalized, (uint8_t)ori_normalized);
                dtmp = ori;
            }
        }
        else if (gx < 0 && gy >= 0) { //[Qudrant 2]:(90,180] to be [64,127]
            if (ori < 0) {
                printf("[Err2QUA]orientation:%.1f\n", ori);
                return false;
            }
            ori_normalized = (ori)*255.0/360.0; 
            if (ori != 0.0 && dtmp != ori) {
                printf("[Qudrant 2]orientation: %.1f to be %.1f(%d)\n", ori, ori_normalized, (uint8_t)ori_normalized);
                dtmp = ori;
            }
        }
        else if (gx < 0 && gy < 0) { //[Qudrant 3]:(180,270) equal to (-180, -90) to be [128,190] 
            if (ori > 0) {
                printf("[Err3QUA]orientation:%.1f\n", ori);
                return false;
            }
            ori_normalized = (360.0+ori)*255.0/360.0; 
            if (ori != 0.0 && dtmp != ori) { 
                printf("[Qudrant 3]orientation:%.1f to be %.1f(%d)\n", ori, ori_normalized, (uint8_t)ori_normalized);
                dtmp = ori;
            }
        }
        else {
            printf("[EXCEPTION]orientation:%.1f\n", ori);
            return false;
        }
        orientation[i+j*width] = ori_normalized;
    }
}
return true;
}

您可以在my上查看更多有关数字图像处理的源代码:)

请编辑您的代码。很难阅读。如果没有阅读代码:您还记得arctan总是生成介于-pi/2和pi/2()之间的值吗?@mistapink但是
atan2()
生成介于-pi和pi之间的值,请参见@B。。。嗯,我不知怎么读到了阿坦。一定错过了那边的两个:(
bool correlation(double*& dst, double* src, double* kernel, int width, int height, int window) {
if (src == NULL || kernel == NULL)
    return false;
if (width <= 0 || height <= 0 || width < window || height < window )
    return false;
dst = new double[sizeof(double)*width*height];
if (dst == NULL)
    return false;
memset(dst, 0, sizeof(double)*width*height);

int ii = 0;
int jj = 0;
int nn = 0;
int mm = 0;

double max = std::numeric_limits<double>::min();
double min = std::numeric_limits<double>::max();
double range = std::numeric_limits<double>::max();

for (int j=0; j<height; j++) {
    for (int i=0; i<width; i++) {
        for (int m=0; m<window; m++) {
            for (int n=0; n<window; n++) {
                ii = i+(n-window/2);
                jj = j+(m-window/2);
                nn = n;
                mm = m;
                if (ii >=0 && ii<width && jj>=0 && jj<height) {
                    dst[i+j*width] += src[ii+jj*width]*kernel[nn+mm*window];
                }
                else {
                    dst[i+j*width] += 0;
                }
            }
        }
        if (dst[i+j*width] > max) 
            max = dst[i+j*width];
        else if (dst[i+j*width] < min)
            min = dst[i+j*width];
    }
}

//normalize double matrix to be an uint8_t matrix
range = max - min;
double norm  = 0.0;
printf("correlated matrix max:%.1f, min:%.1f, range:%.1f\n", max, min, range);
for (int j=0; j<height; j++) {
    for (int i=0; i<width; i++) {
        norm = dst[i+j*width];
        norm = 255.0*norm/range;
        dst[i+j*width] = norm;
    }
}
return true;
}
[Qudrant 1]orientation: 45.0 to be 31.9(31)
[Qudrant 1]orientation: 90.0 to be 63.8(63)
[Qudrant 2]orientation: 135.0 to be 95.6(95)
[Qudrant 2]orientation: 180.0 to be 127.5(127)
[Qudrant 3]orientation:-135.0 to be 159.4(159)
[Qudrant 3]orientation:-116.6 to be 172.4(172)
[Qudrant 4]orientation:-90.0 to be 191.2(191)
[Qudrant 4]orientation:-63.4 to be 210.1(210)
[Qudrant 4]orientation:-45.0 to be 223.1(223)