2017-09-05 8 views
0

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軸上の大きさを求めたいので、どのようにヒストグラムを使って描くことができますか?できるだけコードを使って指導してください。お気軽に –

答えて

0

です。それで、最初の部分はそれぞれのヒストグラムを計算することです。両方ともすでに(自分自身では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で見つかった二つのヒストグラムをプロットする必要があります。あなたは大きさのために同じことを行う、または多分変えることができます。これにより

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

:私は角度のために、それはこのようなものになるだろう、あなたはプロットのラインを持っているコメントで掲示turtorialで

それらが供給された場合にヒストグラムを描画する関数に変換します。ドキュメントで

彼らは我々の場合にそれを適応し、ビンとして四角形を描画するための別のオプションを持って、私たちのようなものを得る:再び

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

多くのお手伝いをしてくれてありがとうございます。矩形の最後のセクションコードはグラフやポイントを表示することはできませんのでご確認ください。彼らはちょうど私の中に任意のポイントが四角形を示しています。 –

+0

私の仕事は、x軸は角度で、y軸はヒストグラムの大きさでなければならないということです。どのように私はこれを得ることができますか? –

+0

@GujjarAdはい、ヒストグラムには、ビンがあります。ビンは、計算されたポイントの束を持っています。マグニチュードとヒストグラムをプロットするのは簡単ですが、OpenCVを使用するのはいいですが、そのためのライブラリはもっと​​良いです。それにもかかわらず、円の描画関数を使用して各点に描画するだけです。 – api55

関連する問題