ダミーの色分け

この記事は、画像処理技術を習い始めたばかりの初心者を対象としています。 私自身は、特にロシア語で簡単な例が不足していることが多いので、この資料が役立つことを願っています。



どういうわけか、次のタスクに直面しました。 ピーマンの写真をたくさん撮りましたが、背景から植物を分離する必要がありました。 このタスクを例として使用して、openCV 2.4でこれを行う最も基本的な方法の1つを紹介します。



問題の本質:植物ではないものすべてを白で塗りつぶすこと。





元の写真(左)と何が起こるべきか(右)。



開始するには、画像をアップロードします。



Mat src = imread("1.jpg"); // 
      
      





デフォルトでは、opencvはカラー画像をBGRパレットに保存します。 BGRで色を定義するのはあまり便利ではないため、最初に画像をHSV形式に変換します。

HSV(またはHSB)は、色相、彩度、明度(輝度)を意味します。ここで、

色相-色調、すなわち カラーキャスト。



彩度-彩度。 このパラメータが高いほど、色は「きれい」になり、低いほど、灰色に近くなります。



値(明るさ)-色の値(明るさ)。 値が高いほど、色は明るくなります(ただし、白くなりません)。 そして、暗いほど(0%-黒)


画像



色で植物を正確に検索するので、何よりも私たちの興味を引くのはトーンです。



画像をHSVパレットに変換し、それぞれ3つの色相彩度値に分割します。



 //   HSV Mat hsv = Mat(src.cols, src.rows, 8, 3); // vector<Mat> splitedHsv = vector<Mat>(); cvtColor(src, hsv, CV_BGR2HSV); split(hsv, splitedHsv);
      
      





トーン値の範囲を設定します。 OpenCVでは、緑の範囲は34〜72です。写真のピーマンは完全に緑ではありません。 したがって、21〜110の範囲が実験的に選択されました。



 const int GREEN_MIN = 21; const int GREEN_MAX = 110;
      
      





次に、画像を確認します。 各ピクセルについて、3つのコンポーネントすべてを取得します。 強度は使用しませんが、より明確にし、インデックスをスキップしないようにするため、そのままにします。 トーンが指定された範囲に収まらない場合、または明るさが低すぎる場合は、これが背景なので、すべてを白で塗りつぶします。



 for (int y = 0; y < hsv.cols; y++) { for (int x = 0; x < hsv.rows; x++) { //  HSV-  int H = static_cast<int>(splitedHsv[0].at<uchar>(x, y)); //  int S = static_cast<int>(splitedHsv[1].at<uchar>(x, y)); //  int V = static_cast<int>(splitedHsv[2].at<uchar>(x, y)); //  //          ,    if ((V < 20) || (H < GREEN_MIN) || (H > GREEN_MAX)) { src.at<Vec3b>(x, y)[0] = 255; src.at<Vec3b>(x, y)[1] = 255; src.at<Vec3b>(x, y)[2] = 255; } } }
      
      





その結果、次の画像が得られます。







一般に、背景は消えましたが、左隅に理解できないノイズがありました。



小さなインコヒーレント粒子を除去する1つの方法は、形態学的画像処理です。



拡張(形態学的拡張)-画像または画像の選択された領域と特定のコアの畳み込み。 カーネルの形状とサイズは任意です。 同時に、カーネルで唯一の先頭位置が強調表示され、畳み込みの計算時に現在のピクセルに合わせられます。 多くの場合、中心に先頭位置を持つ正方形または円がコアとして選択されます。 カーネルは、テンプレートまたはマスクと見なすことができます。 拡張の適用は、画像全体を通過するパターンと、そのパターンで覆われている画像ピクセルの強度への極大検索演算子の適用に限定されます。 このような操作は、画像内の明るい領域の成長を引き起こします。 図では、ピクセルは灰色でマークされています。これは、膨張の結果として白になります。



侵食(形態学的狭小化)は逆の操作です。 侵食の効果は膨張と似ていますが、唯一の違いは、侵食の結果として黒くなるピクセルを埋めるためにローカル最小検索演算子が使用されることです。


この事例の詳細については、 こちらをご覧ください 。 モルフォロジー演算を写真に適用します。 楕円を構造要素として取ります。



 int an = 5; //     . Mat element = getStructuringElement(MORPH_ELLIPSE, Size(an * 2 + 1, an * 2 + 1), Point(an, an)); dilate(src, tmp, element); erode(tmp, tmp, element);
      
      







形態学的処理の結果。



ほとんどのノイズは除去されましたが、画像自体はぼやけていました。これは私たちが望んでいたものではありません。 したがって、変換された画像をマスクとして使用して、不要なノイズを除去します。



 Mat grayscaleMat; cvtColor(tmp, grayscaleMat, CV_BGR2GRAY); //   Mat mask(grayscaleMat.size(), grayscaleMat.type()); Mat out(src.size(), src.type()); threshold(grayscaleMat, mask, 200, 255, THRESH_BINARY_INV); //       out = Scalar::all(255); //     src.copyTo(out, mask);
      
      







左側がマスク、右側がマスクの適用結果です。



このようにして、背景からオブジェクトを基本的に選択できます。



完全なサンプルコード



UPD:リンク切れを修正。



All Articles