在OpenCV中绘制Sobel算子幅度和角度的直方图

问题描述:

我想在OpenCV C++中绘制直方图。任务是x轴应该是角度,而y轴应该是直方图的大小。我使用Sobel算子计算幅度和角度。现在我怎样才能绘制直方图通过使用幅度和角度?在OpenCV中绘制Sobel算子幅度和角度的直方图

在此先感谢。问题的简单代码是

// Read image 
     Mat img = imread("abs.jpg"); 
    img.convertTo(img, CV_32F, 1/255.0); 
    /*GaussianBlur(img, img, Size(3, 3), 0, 0, BORDER_CONSTANT);*/ 
    // Calculate gradients gx, gy 
    Mat gx, gy; 
    Sobel(img, gx, CV_32F, 1, 0, 1); 
    Sobel(img, gy, CV_32F, 0, 1, 1); 

    // C++ Calculate gradient magnitude and direction (in degrees) 
    Mat mag, angle; 
cartToPolar(gx, gy, mag, angle, 1); 
imshow("magnitude of image is", mag); 
imshow("angle of image is", angle); 
+1

您可以尝试[OpenCV教程](http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html),其中显示了如何计算和绘制直方图,您可以跳过分裂矩阵的步骤,因为你在这两种情况下有1个通道 – api55

+0

@ api55问题是我不知道如何绘制幅度和角度,我可以将这些参数放在calHist函数中。请你给一点时间给代码。我只是在opencv非常初学者。谢谢。 –

+0

因为我想要在X轴上的角度和在Y轴上的幅度,我怎样才能使用直方图来绘制它。请指导如果可能的话使用代码。谢谢 –

好的,所以它的第一部分是计算它们每个的直方图。由于两者已经分开(在他们自己的Mat中),我们不必分割它们或任何东西,我们可以直接在OpenCV的calcHist函数中使用它们。

通过的文件有:

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false) 

所以,你必须做的:

cv::Mat histMag, histAng; 
// number of bins of the histogram, adjust to your liking 
int histSize = 10; 
// degrees goes from 0-360 if radians then change acordingly 
float rangeAng[] = { 0, 360} ; 
const float* histRangeAng = { rangeAng }; 
double minval, maxval; 
// get the range for the magnitude 
cv::minMaxLoc(mag, &minval, &maxval); 
float rangeMag[] = { static_cast<float>(minval), static_cast<float>(maxval)} ; 
const float* histRangeMag = { rangeMag }; 
cv::calcHist(&mag, 1, 0, cv::NoArray(), histMag, 1, &histSize, &histRangeMag, true, false); 
cv::calcHist(&angle, 1, 0, cv::NoArray(), histAng, 1, &histSize, &histRangeAng, true, false); 

现在,你必须绘制在histMaghistAng发现两个柱状图。

在我贴在你的情节线的评论turtorial,对角,将是这样的:

// Draw the histograms for B, G and R 
    int hist_w = 512; int hist_h = 400; 
    int bin_w = cvRound((double) hist_w/histSize); 

    cv::Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0,0,0)); 

    /// Normalize the result to [ 0, histImage.rows ] 
    cv::normalize(histAng, histAng, 0, histImage.rows, cv::NORM_MINMAX, -1, Mat()); 

    // Draw the lines 
    for(int i = 1; i < histSize; i++) 
    { 
     cv::line(histImage, cv::Point(bin_w*(i-1), hist_h - cvRound(histAng.at<float>(i-1))) , 
         cv::Point(bin_w*(i), hist_h - cvRound(histAng.at<float>(i))), 
         cv::Scalar(255, 0, 0), 2, 8, 0 ); 
    } 

有了这个,你可以为大小做同样的,也可能转它变成了一个函数,如果它们被提供,它将绘制直方图。

在他们有另一种选择,绘制矩形的箱,使其适应我们的情况下的文档,我们得到这样的:

// Draw the histograms for B, G and R 
    int hist_w = 512; int hist_h = 400; 
    int bin_w = std::round(static_cast<double>(hist_w)/static_cast<double>(histSize)); 

    cv::Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0,0,0)); 

    /// Normalize the result to [ 0, histImage.rows ] 
    cv::normalize(histAng, histAng, 0, histImage.rows, cv::NORM_MINMAX, -1, Mat()); 

    for(int i = 1; i < histSize; i++) 
    { 
     cv::rectangle(histImage, cv::Point(bin_w*(i-1), hist_h - static_cast<int>(std::round(histAng.at<float>(i-1)))), cv::Point(bin_w*(i), hist_h),); 
    } 

同样,这可以用于幅度在要做的事同样的方式。这是超级简单的图,如果您需要更复杂或更美观的图,则可能需要调用外部库并将数据传递到计算出的直方图中。此外,这段代码还没有经过测试,所以它可能有错误或错误,但如果失败了,只需写一条评论,我们可以找到解决方案。

我希望这可以帮助你,并为迟到的答案抱歉。

+0

非常感谢@ api55帮助我很多。但是绘制矩形的最后一段代码不能显示任何图形或点,请检查一下。他们只是向我展示矩形内没有任何点。 –

+0

我的任务是x轴应该是角度,而y轴应该是直方图的大小?我怎么能得到这个? –

+0

@GujjarAd是的,在一个柱状图中,你有一些箱子,它们有一堆计算点。要绘制幅度与直方图,它更容易,但我会建议不要使用OpenCV,但为此更好的库。尽管如此,使用'circle'绘图函数并绘制每个点的方法很简单。 – api55