C++ Sobel的梯度是什么意思?

C++ Sobel的梯度是什么意思?,c++,opencv,orientation,gradient,fingerprint,C++,Opencv,Orientation,Gradient,Fingerprint,我有来自Sobel操作符的每个像素的梯度。就我而言,是320x480。但是我怎样才能把它们和方向联系起来呢?举个例子,我计划画一张指纹方向图。那么,我该如何开始呢 是否将梯度划分为块(例如16x24),然后将梯度相加,再将其下潜384以获得平均梯度?然后用平均梯度从块的中心画一条线 如果我错了,请纠正我。多谢各位 下面是我用来查找渐变的代码 cv::Mat original_Mat=cv::imread("original.bmp", 1); cv::Mat grad = cv::Mat::z

我有来自Sobel操作符的每个像素的梯度。就我而言,是320x480。但是我怎样才能把它们和方向联系起来呢?举个例子,我计划画一张指纹方向图。那么,我该如何开始呢

是否将梯度划分为块(例如16x24),然后将梯度相加,再将其下潜384以获得平均梯度?然后用平均梯度从块的中心画一条线

如果我错了,请纠正我。多谢各位

下面是我用来查找渐变的代码

cv::Mat original_Mat=cv::imread("original.bmp", 1);

cv::Mat grad = cv::Mat::zeros(original_Mat.size(), CV_64F);

cv::Mat grad_x = cv::Mat::zeros(original_Mat.size(), CV_64F); 
cv::Mat grad_y = cv::Mat::zeros(original_Mat.size(), CV_64F);

/// 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);

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

int count = 0;
int min = 999999;
int max = -1;
int a=0,b=0;

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

    //printf("%d ",directionDEG);
    if(directionDEG < min){min = directionDEG;}
    if(directionDEG > max){max = directionDEG;}


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

}
cv::Mat original\u Mat=cv::imread(“original.bmp”,1);
cv::Mat grad=cv::Mat::Zero(原始材料尺寸(),cv_64F);
cv::Mat grad_x=cv::Mat::Zero(原始材料尺寸(),cv_64F);
cv::Mat grad_y=cv::Mat::Zero(原始材料尺寸(),cv_64F);
///梯度X
cv::Sobel(原始材料,梯度x,cv_16S,1,0,3);
///梯度Y
cv::Sobel(原始材料,梯度,cv_16S,0,1,3);
短*像素x=梯度x.ptr(0);
短*像素=grad_y.ptr(0);
整数计数=0;
int min=999999;
int max=-1;
int a=0,b=0;
对于(int i=0;imax){max=directionDEG;}
如果(方向度<0 | |方向度>360)
{

cout有几种方法可以可视化方向图:

正如您所建议的,您可以按块绘制,但在“平均”方向时必须小心。例如,如果平均方向0°和180°,会发生什么情况

更常见的情况是,方向简单地映射到灰度值。这将可视化每个像素的梯度。例如:

int v = (int)(128+directionRAD / CV_PI * 128);
(免责声明:不能100%确定
128
,其中一个可能必须是
127
。)

或者,您可以将x和y梯度大小分别映射到
r
g
分量,理想情况下,将梯度向量归一化为长度1。假设
normX
是x方向上的归一化梯度,其值介于-1和1之间:

int red = (int)((normX + 1)*127.5);
int green= (int)((normY + 1)*127.5);

平均值取决于Sobel核的大小

最好使用CV_32FC或CV_64FC而不是CV_16S来获得结果

您还可以使用cv::phase方法加快代码的速度


请看我的回答:

谢谢,但我仍然感到困惑。v代表什么?我得到的值范围是0-256。灰度?我如何使用这些信息来画线?v是一个灰度值。如果你通过这样计算每个像素值来生成一个新图像,你将得到一个图像,其中每个像素代表该像素处的梯度方向。T根据我的经验,他只是画线和画线的替代品更常用。@andreas,我使用了imwrite并得到了图像,但它看起来与原始图像完全不同,我正在尝试这样做。有什么办法吗?这看起来像是你的代码有问题。你看过了吗?你知道我的代码出了什么问题吗?是的,我以前见过。从你的链接,我现在可以平均一下吗5x5块方向值,然后为每个块绘制线?这会得到方向图吗?谢谢。从你的方法获得的角度与我的方法相同,对吗?你能告诉我如何从这里开始绘制地图吗?我认为HOG visuzlizer应该是最合适的:(看这里)您还可以绘制除最大仓位或平均(N个最强)仓位以外的所有仓位,并绘制每个块的结果。