2016-04-06 8 views
0

画像がその中に現れる支配的な色でフィルタリングしようとしています。 Thatsが完了しました。これで、得られた色が定義された色の範囲から来ているかどうかを知りたいと思っています。この特定のケースでは、オレンジ色の範囲内にあるかどうかを知りたいと思います。色が範囲にあるかどうかを調べる方法

私は「inrange」機能を見ましたが、このケースは私を助けてくれないと思います。これで私は次のコードを実行しました:

Scalar ORANGE_MIN = Scalar(18, 40, 90); 
Scalar ORANGE_MAX = Scalar(27, 255, 255); 

bool in_range(Scalar color, Scalar orange_min, Scalar orange_max) 
{ 
bool result = false; 
if ((color.val[0] > orange_min.val[0] && color.val[0] < orange_max.val[0]) && 
    (color.val[1] > orange_min.val[1] && color.val[1] < orange_max.val[1]) && 
    (color.val[2] > orange_min.val[2] && color.val[2] < orange_max.val[2])) 
{ 
    result = true; 
} 
return result; 
} 

私は期待どおりのフィルタがないので、何か間違っています。 誰でも助けてくれますか? ありがとう!

+1

[18,27]、[40,255]、[90,255]の間隔のRGB値は実際には多くの色が可能です。私はあなたがはるかに具体的にチェックする必要があると思います。 –

+2

_私が予期していたようなフィルタではないので、何か間違っています:あなたはどう思いますか? –

+3

おおよそ「オレンジ」なものが本当に必要な場合は、[HSLまたはHSV色空間](https://en.wikipedia.org/wiki/HSL_and_HSV)に切り替えることを検討してください。 – mindriot

答えて

0

HSLへORANGE_MINORANGE_MAX、及びcolor(HSV)カラーモデルに変換し、色相が所要範囲内にあることを確認してください。数学については、例えばhttp://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/を参照してください。

UPDATE

彩度や明度が同様に、いくつかの範囲に照らしてチェックする必要があり、以下のコメントを参照してください。ありがとうございましたMSaltersこれを指摘してください。

+1

他の2つの変数をチェックして、白、灰色または黒を扱っているかどうかを確認する必要があります。 – MSalters

+0

あなたはそうです、これを忘れてください。いくつかの許容範囲に対して明度と彩度をチェックする可能性があります。 –

+0

私はなぜそれが使用されていない場合、飽和値を計算しているのかわかりません。それの重要性は何ですか? –

1

少し異なるアプローチをとっていきます。代わりに、すべての定義済み色の範囲間隔を定義するのは、次のことができます

  1. はあなた事前に定義された色を定義します。これは、チェックあなたのパレット内のすべての色からの距離を計算し、最も近いパレット色を維持したい色を考えると
  2. あなたの可能な色のパレットだろう。
  3. 見つかったパレットの色が十分に近いかどうか確認してください。ユークリッド距離(2色のnorm)が行儀であるので、私は、BGRの色空間を使用したこの小さなサンプルで

HSVのような別の色空間を使用できますが、適切な距離を見つける必要があります。白黒/灰色の色が欠けているので、H値だけを使うことはできません(@MSaltersで述べたように)。

だから、あなたのようなものを得るでしょう、適切なパレットで、たとえばあなたの色ほとんどオレンジ20, 130, 250のために与えられた:

[20, 130, 250] is similar to orange 
Distance with nearest color [0, 127, 255] is 20.8327 

コード:

あなたは、任意の組み合わせを許可しているので
#include <opencv2/opencv.hpp> 
#include <vector> 
#include <map> 
#include <string> 
using namespace cv; 
using namespace std; 

// Needed to put Vec3b into a std::map 
struct lessVec3b 
{ 
    bool operator()(const Vec3b& lhs, const Vec3b& rhs) { 
     return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2])); 
    } 
}; 


int main() 
{ 
    // Define a set of predefined BGR colors 
    map<Vec3b, string, lessVec3b> palette; 
    palette[Vec3b(0, 0, 0)] = "black"; 
    palette[Vec3b(0, 0, 255)] = "red"; 
    palette[Vec3b(0, 255, 0)] = "green"; 
    palette[Vec3b(255, 0, 0)] = "blue"; 
    palette[Vec3b(0, 127, 255)] = "orange"; 

    // Your color 
    Vec3b my_color(20, 130, 250); // almost orange 

    // Look for nearest color in palette 
    Vec3b nearest_color; 
    string color_name; 
    float min_distance = FLT_MAX; 
    for (const auto& pal : palette) 
    { 
     float dist = norm(pal.first, my_color); 
     if (dist < min_distance) 
     { 
      nearest_color = pal.first; 
      color_name = pal.second; 
      min_distance = dist; 
     } 
    } 

    // Define a distance. This will behave like your ranges 
    float th_distance = 1000.f; 

    if (min_distance < th_distance) 
    { 
     cout << my_color << " is similar to " << color_name << endl; 
    } 
    else 
    { 
     cout << my_color << " is not in the palette" << endl; 
    } 
    cout << "Distance with nearest color " << nearest_color << " is " << min_distance << endl; 

    return 0; 
}