1

この投稿に似たようなことをしようとしています: HSV ヒストグラムから支配的な色の値を取得する

画像があり、そこからドミナント カラー (色相) を抽出したいと考えています。ヒストグラムを計算し、minMaxLoc から maxValue を取得するところまで来ました。しかし、Core.MinMaxLocResult から取得している数値はまったく意味がありません。806924 や 1067036 のようなものが表示されます。色相の期待値は 0 から 180 の間であるべきではありませんか?

ヒストグラムは正規化されているはずですか?どうして?「equalizeHist」や「normalize」などのメソッドを見たことがありますが、これらの使用方法とそれらがどのように役立つかはよくわかりません。

また、賢明な「最も発生する」色相数を取得したら、それを実際の色合いに変換するにはどうすればよいですか (「この画像では緑が最も発生する色です」など)。標準的な色相範囲はありますか? 0 から 10 は赤、10 から 20 は紫などですか?

更新:ここに私のコードがあります:

    private void processImage(String imgFilename) {
            channels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1),
            new MatOfInt(2) };
    histSize = new MatOfInt(histSizeNum);
    hRanges = new MatOfFloat(0f, 180f); // hue varies from 0 to 179
    // use openCV stuff to convert from RGB to HLS space
    Mat src = Highgui.imread(imgFilename);
    Mat hls = new Mat();// destination color space
    Imgproc.cvtColor(src, hls, Imgproc.COLOR_RGB2HLS);
    Core.split(hls, hlsChannels);
    Mat hue = hlsChannels.get(0);
    Mat lum = hlsChannels.get(1);
    Mat sat = hlsChannels.get(2);
    // we compute the histogram from the 0-th channel for hue
    Imgproc.calcHist(Arrays.asList(hls), channels[0], new Mat(), hist,
            histSize, hRanges);

     Core.normalize(hist, hist, 0,2, Core.NORM_MINMAX, -1, new Mat());

    Core.MinMaxLocResult result = Core.minMaxLoc(hist);
    // max value should contain the most-recurring Hue value.
    double mostOccurringHue = result.maxVal;
    double leastOccurringHue = result.minVal;
    //double mostOccurringHue = result.maxLoc.x;
    //double leastOccurringHue = result.minLoc.x;

    // print out for sanity checking
    System.out.println("MAX HUE = " + Double.toString(mostOccurringHue) +"\n");
    System.out.println("MIN HUE = " + Double.toString(leastOccurringHue) +"\n");
4

3 に答える 3

1

ヒストグラムとその正規化を計算するopenCVのibuiltメソッドを使用する代わりに、色相チャネルのみのヒストグラムを作成しているため、独自のコードを作成しました。私のコードを見てください。

int main()
{

    Mat input = imread("jan31/class4Jan31.jpg",1);
    Mat hsv_input;
    int h_bins = 5;
    Mat hist_input = Mat::zeros( 1, h_bins, CV_32FC1);
    int h_range = 179;
    int totalNumberPixels = 0;

    cvtColor(input, hsv_input, CV_RGB2HSV);
    Mat hsv_channels[3];

    split( hsv_input, hsv_channels );

    for (int i=0; i<hsv_channels[0].rows; i++)
    {
        for (int j=0; j<hsv_channels[0].cols; j++)
        {               
            if( (int)hsv_channels[1].at<uchar>(i,j)>10 &&    (int)hsv_channels[1].at<uchar>(i,j)>100)
            {               
                totalNumberPixels++;
                int pixel_value = (int)hsv_channels[0].at<uchar>(i,j);
                int corresponding_bin =  ( pixel_value * h_bins ) / h_range;                
                hist_input.at<float>( 0, corresponding_bin ) = ( hist_input.at<float>( 0, corresponding_bin ) + 1 );                
            }                                                                                       
        }
    }

    cout<<"\n total pixels: "<<totalNumberPixels;

    for(int i=0; i<hist_input.rows; i++)
    {
        for (int j=0; j<hist_input.cols; j++)
        {
            float pixel = hist_input.at<float>(i,j);
            hist_input.at<float>(i,j) = pixel / totalNumberPixels;

            pixel = hist_input.at<float>(i,j);
            cout<<"\n Pixel: "<<pixel;
        }
    }

    cv::waitKey(0);
    return 0;
}
于 2014-02-11T18:58:33.407 に答える
1

あなたが言及したリンクに投稿された回答をもう一度確認することをお勧めします。次の点について考える必要があります。

-支配的な色の値を探しているので、色相チャネルのみで作業する必要があります。

- 範囲は 0 ~ 180 である必要があります。

値のヒストグラムのみが必要なため、-dims は (2 ではなく) 1 にする必要があります。

==> その後、 maxValLoc は、ポイントが x 座標と y 座標で構成される「ポイント」形式で最大値を持つビンを通知します。

例えば:

double minVal; double maxVal; Point minLoc; Point maxLoc;
minMaxLoc( hist_image, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

「maxVal」には最大値が含まれ、「maxLoc.y」と「maxLoc.x」はその最大値を含むポイントの行と列の値を示します。

于 2014-02-07T22:11:27.577 に答える