什么是梯度定向和梯度大小 [英] What is gradient orientation and gradient magnitude

查看:463
本文介绍了什么是梯度定向和梯度大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习一个称为边缘检测的计算机视觉模块。
我试图理解梯度方向和梯度幅度的含义。

解决方案

http://stackoverflow.com/users/13313/dima\"> Dima 在他的回答中,您应该熟悉渐变的数学概念,以便更好地了解字段中的渐变图像处理。



我的回答是基于回答 mevatron 到此

您可以在黑色背景上找到白色磁盘的简单初始映像:



>



你可以计算这个图像的梯度的近似值。正如Dima在他的答案中解释的,你有两个梯度的组件,水平和垂直的组件。



下面的图片显示了水平组件:



>



它显示图像中的灰度级在水平方向上的变化(它是正x的方向,从左到右扫描图像),这种变化在灰度级编码水平分量的图像:平均灰度级意味着没有变化,亮级意味着从暗值到亮值的变化,暗级意味着从明亮值到暗值的变化。所以,在上面的图像中,你会看到圆圈的左边部分的亮度值,因为它在初始图像的左边部分,你有黑色到白色的过渡,给你磁盘的左边缘;类似地,在上面的图像中,你会看到圆圈右部分的暗值,因为它在初始图像的右边部分,你有白到黑的过渡,给你的磁盘的右边缘。在上面的图像中,磁盘的内部和背景是一个平均灰度级,因为在磁盘和后台没有变化。



我们可以对垂直分量进行类似观察,它显示图像在垂直方向上的变化,即从顶部到底部扫描图像:





您现在可以合并这两个组件得到渐变的大小和渐变的方向。



下面的图像是渐变的大小:





在上面的图像中,初始图像的变化以灰度级编码:这里你看到白色意味着初始图像的高变化,而黑色意味着没有变化。
所以,当你看到梯度幅度的图像,你可以说如果图像明亮,这意味着初始图像的一个大变化;如果它是黑暗的,这意味着没有变化或非常微小的变化 。



以下图片是渐变的方向:





在上面的图片中,方向再次编码为灰度级:you可以在取向上认为是从图像的暗部分指向图像的亮部分的箭头的角度;该角度被称为xy框架,其中x从左向右延伸,而y从上向下延伸。在上述图像中,您将看到从黑色(零度)到白色(360度)的所有灰度级。我们可以使用颜色对信息进行编码:





红色:角度是在0和90度之间



青色:角度在90到180度之间



绿色:在180到270度之间



黄色:角度在270到360度之间



用于生成上述图片的OpenCV代码。

  //原始代码由http://stackoverflow.com/users/951860/mevatron 
//参见http://stackoverflow.com/a/11157426/15485
// http://stackoverflow.com/users/15485/uvts-cvs添加了用于保存x和y渐变的代码组件

#include< opencv2 / core / core.hpp>
#include< Opencv2 / highgui / highgui.hpp>
#include< opencv2 / imgproc / imgproc.hpp>

#include< iostream>
#include< vector>

using namespace cv;
using namespace std;

Mat mat2gray(const cv :: Mat& src)
{
Mat dst;
normalize(src,dst,0.0,255.0,cv :: NORM_MINMAX,CV_8U);

return dst;
}

Mat orientationMap(const cv :: Mat& mag,const cv :: Mat& ori,double thresh = 1.0)
{
Mat oriMap = Mat :: zeros(ori.size(),CV_8UC3);
Vec3b red(0,0,255);
Vec3b cyan(255,255,0);
Vec3b green(0,255,0);
Vec3b yellow(0,255,255);
for(int i = 0; i {
float * magPixel = reinterpret_cast< float *>(mag.data + i * sizeof(float));
if(* magPixel> thresh)
{
float * oriPixel = reinterpret_cast< float *>(ori.data + i * sizeof(float)
Vec3b * mapPixel = reinterpret_cast< Vec3b *>(oriMap.data + i * 3 * sizeof(char));
if(* oriPixel <90.0)
* mapPixel = red;
else if(* oriPixel> = 90.0&& * oriPixel< 180.0)
* mapPixel =
else if(* oriPixel> = 180.0&& * oriPixel< 270.0)
* mapPixel = green;
else if(* oriPixel> = 270.0&& * oriPixel< 360.0)
* mapPixel =
}
}

return oriMap;
}

int main(int argc,char * argv [])
{
Mat image = Mat :: zeros(Size(320,240),CV_8UC1 );
circle(image,Point(160,120),80,Scalar(255,255,255),-1,CV_AA);

imshow(original,image);

Mat Sx;
Sobel(image,Sx,CV_32F,1,0,3);

Mat Sy;
Sobel(image,Sy,CV_32F,0,1,3);

Mat mag,ori;
magnitude(Sx,Sy,mag);
phase(Sx,Sy,ori,true);

Mat oriMap = orientationMap(mag,ori,1.0);

imshow(x,mat2gray(Sx));
imshow(y,mat2gray(Sy));

imwrite(hor.png,mat2gray(Sx));
imwrite(ver.png,mat2gray(Sy));

imshow(magnitude,mat2gray(mag));
imshow(orientation,mat2gray(ori));
imshow(orientation map,oriMap);
waitKey();

return 0;
}


I am currently studying a module in computer vision called edge detection. I am trying to understand the meaning of gradient orientation and gradient magnitude.

解决方案

As explained by Dima in his answer, you should be familiar with the mathematical concept of gradient in order to better understand the gradient in the field of image processing.

My answer is based on the answer of mevatron to this question.

Here you find a simple initial image of a white disk on a black background:

you can compute an approximation of the gradient of this image. As Dima explained in his answer, you have two component of the gradient, an horizontal and a vertical component.

The following images shows you the horizontal component:

it shows how much the gray levels in your image change in the horizontal direction (it is the direction of positive x, scanning the image from left to right), this change is "encoded" in the grey level of the image of the horizontal component: the mean grey level means no change, the bright levels mean change from a dark value to a bright value, the dark levels mean a change from a bright value to a dark value. So, in the above image you see the brighter value in the left part of the circle because it is in the left part of the initial image that you have the black to white transition that gives you the left edge of the disk; similarly, in the above image you see the darker value in the right part of the circle because it is in the right part of the initial image that you have the white to black transition that gives you the right edge of the disk. In the above image, the inner part of the disk and the background are at a mean grey level because there is no change inside the disk and in the background.

We can make analogous observations for the vertical component, it shows how the image change in the vertical direction, i.e. scanning the image from the top to the bottom:

You can now combine the two components in order to get the magnitude of the gradient and the orientation of the gradient.

The following image is the magnitude of the gradient:

Again, in the above image the change in initial image is encoded in the gray level: here you see that white means an high change in the initial image while black means no change at all. So, when you look at the image of the magnitude of the gradient you can say "if the image is bright it means a big change in the initial image; if it is dark it means no change or very llittle change".

The following image is the orientation of the gradient:

In the above image the orientation is again encoded as gray levels: you can think at the orientation as the angle of an arrow pointing from the the dark part of the image to the bright part of the image; the angle is referred to an xy frame where the x runs from left to right while the y runs from top to bottom. In the above image you see all the grey level from the black (zero degree) to the white (360 degree). We can encode the information with color:

in the above image the information is encode in this way:

red: the angle is between 0 and 90 degree

cyan: the angle is between 90 and 180 degree

green: the angle is between 180 and 270 degree

yellow: the angle is between 270 and 360 degree

Here it is the C++ OpenCV code for producing the above images.

// original code by http://stackoverflow.com/users/951860/mevatron
// see http://stackoverflow.com/a/11157426/15485
// http://stackoverflow.com/users/15485/uvts-cvs added the code for saving x and y gradient component 

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

Mat mat2gray(const cv::Mat& src)
{
    Mat dst;
    normalize(src, dst, 0.0, 255.0, cv::NORM_MINMAX, CV_8U);

    return dst;
}

Mat orientationMap(const cv::Mat& mag, const cv::Mat& ori, double thresh = 1.0)
{
    Mat oriMap = Mat::zeros(ori.size(), CV_8UC3);
    Vec3b red(0, 0, 255);
    Vec3b cyan(255, 255, 0);
    Vec3b green(0, 255, 0);
    Vec3b yellow(0, 255, 255);
    for(int i = 0; i < mag.rows*mag.cols; i++)
    {
        float* magPixel = reinterpret_cast<float*>(mag.data + i*sizeof(float));
        if(*magPixel > thresh)
        {
            float* oriPixel = reinterpret_cast<float*>(ori.data + i*sizeof(float));
            Vec3b* mapPixel = reinterpret_cast<Vec3b*>(oriMap.data + i*3*sizeof(char));
            if(*oriPixel < 90.0)
                *mapPixel = red;
            else if(*oriPixel >= 90.0 && *oriPixel < 180.0)
                *mapPixel = cyan;
            else if(*oriPixel >= 180.0 && *oriPixel < 270.0)
                *mapPixel = green;
            else if(*oriPixel >= 270.0 && *oriPixel < 360.0)
                *mapPixel = yellow;
        }
    }

    return oriMap;
}

int main(int argc, char* argv[])
{
    Mat image = Mat::zeros(Size(320, 240), CV_8UC1);
    circle(image, Point(160, 120), 80, Scalar(255, 255, 255), -1, CV_AA);

    imshow("original", image);

    Mat Sx;
    Sobel(image, Sx, CV_32F, 1, 0, 3);

    Mat Sy;
    Sobel(image, Sy, CV_32F, 0, 1, 3);

    Mat mag, ori;
    magnitude(Sx, Sy, mag);
    phase(Sx, Sy, ori, true);

    Mat oriMap = orientationMap(mag, ori, 1.0);

    imshow("x", mat2gray(Sx));
    imshow("y", mat2gray(Sy));

    imwrite("hor.png",mat2gray(Sx));
    imwrite("ver.png",mat2gray(Sy));

    imshow("magnitude", mat2gray(mag));
    imshow("orientation", mat2gray(ori));
    imshow("orientation map", oriMap);
    waitKey();

    return 0;
}

这篇关于什么是梯度定向和梯度大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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