在OpenCV中绘制梯度向量场 [英] Plotting a Gradient Vector Field in OpenCV

查看:388
本文介绍了在OpenCV中绘制梯度向量场的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想计算灰度图像(代码中的 smoothed_plane )的梯度,并将其绘制为OpenCV中的矢量场,并叠加到现有图像上.

I want to compute the gradient of a gray-scale image (smoothed_plane in the code) and plot it as a vector field in OpenCV, superposed to an existing image.

我试图应用一对Sobel运算符(我也尝试过Scharr)来计算x和y的两个导数,如OpenCV文档中所述,但是当我尝试绘制时,矢量场似乎是完全错误的.我想了解我的错误.

I tried to apply a pair of Sobel operators (I also tried Scharr) to compute the two derivatives along x and y as described in OpenCV documentation, but when I try to plot, the vector field seems to be completely wrong. I would like to understand what is my mistake.

我在这里添加了一些代码,以使其更加清晰.预先感谢您的帮助.

I put some code here to be more clear. Thanks in advance for your help.

//img is a gray-scale image
Mat abs_grad_x, abs_grad_y, grad;
Mat g_img;
int ddepth = CV_16S;
int scale = 1;
int delta = 0;    

cvtColor(img,g_img,CV_GRAY2BGR);


smoothed_plane = Mat::zeros(image_height,image_width,CV_8UC1);
gradient_field = Mat::zeros(image_height,image_width,CV_32FC2);

// Smooth the dominant plane by convolution with a Gaussian
GaussianBlur(dominant_plane,smoothed_plane,Size(51,51),image_height*image_width*0.5);

/// Morphological opening (remove small objects from the foreground)
erode(smoothed_plane, smoothed_plane, getStructuringElement(MORPH_ELLIPSE, Size(40+1,40+1)));
dilate(smoothed_plane, smoothed_plane, getStructuringElement(MORPH_ELLIPSE, Size(40, 40)));
/// Morphological closing (fill small holes in the foreground)
dilate(smoothed_plane, smoothed_plane, getStructuringElement(MORPH_ELLIPSE, Size(40, 40)));
erode(smoothed_plane, smoothed_plane, getStructuringElement(MORPH_ELLIPSE, Size(40, 40)));

imshow("Eroded plane",smoothed_plane);

/// Gradient X
Scharr( smoothed_plane, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );

/// Gradient Y
Scharr( smoothed_plane, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );

for (int i = 0 ; i < image_height ; i ++){
    for (int j = 0 ; j < image_width ; j ++){
        gradient_field.at<Point2f>(Point2f(j,i)) = Point2f(abs_grad_x.at<float>(Point2f(j,i)),abs_grad_y.at<float>(Point2f(j,i)));
    }
}

for (int i = 0 ; i < image_height ; i += flowResolution){
    for (int j = 0 ; j < image_width ; j+= flowResolution){
        Point2f p(j,i);
        Point2f p2(gradient_field.at<Point2f>(p)+p);
        arrowedLine(g_img,p,p2,Scalar(0,0,255),1.5,8,0,0.1);
    }
}//*/

imshow("Gradient Vector Field", g_img);

这是我输入/输出结果的一对框架,根据需要

This is a pair of frames of my input/output results, as required

我尝试打印一些值,在某些情况下,我得到了非常高或非常低的值. 再次感谢

I tried to print out some values, and in some points I got very high or very low values. Thanks again

推荐答案

我解决了我的问题.主要错误在于偏导数矩阵 grad_x grad_y 的访问方法.如此处所述,方法 at.<>() 返回一个 Scalar 对象,因此要访问像素强度值,应使用 .val [] 字段.这是必须更改代码的方式:

I solved my problem. The main mistake lied in the access method of the partial derivatives matrices, grad_x and grad_y. As described here, the method at.<>() returns a Scalar object, so to get access to the pixel intensity value one should use the .val[] field. This is how the code has to be changed:

Scharr(smoothed_plane,grad_x,ddepth,1,0,scale);
Scharr(smoothed_plane,grad_y,ddepth,0,1,scale);

for (int i = 0 ; i < image_height ; i ++){
    for (int j = 0 ; j < image_width ; j ++){
        Scalar xval = grad_x.at<float>(i,j);
        Scalar yval = grad_y.at<float>(i,j);
        gradient_field.at<Point2f>(i,j) = Point2f(xval.val[0],yval.val[0]);
    }
}

,这是预期的结果:

and this is the expected result:

这篇关于在OpenCV中绘制梯度向量场的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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