2017-03-03 15 views
0

バイナリイメージと同じサイズのカラーイメージがあります。私は、バイナリイメージの各ブロブ(白いピクセルブロック)を繰り返し、それをマスクとして使用し、カラーイメージからこのブロブ領域の平均カラーを見つける必要があります。OpenCV - バイナリイメージ内の各ブロブを繰り返し、マスクとして使用します。

私が試してみました:穴を持っていないの塊のため

HierarchyIndex[] hierarchy; 
Point[][] contours; 
binaryImage.FindContours(out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone); 

    using (Mat mask = Mat.Zeros(matColor.Size(), MatType.CV_8UC1)) 
     foreach (var bl in contours) 
      if (Cv2.ContourArea(bl) > 5) 
      { 
       mask.DrawContour(bl, Scalar.White, -1);              
       Rect rect = Cv2.BoundingRect(bl); 
       Scalar mean = Cv2.Mean(colorImage[rect], mask[rect]); 

       mask.DrawContour(bl, Scalar.Black, -1); 
      } 

働きます。しかし、私の場合、私は平均計算に影響する巨大な穴を持つ多くのブロブ領域を持っています。

階層情報を使って解決する方法を理解できませんでした。または別の方法で

(私のコードはOpenCVSharpのためであるが、他のラッパーでの回答や言語はウェルカムです。)

編集:私は、例の画像を追加しました。交通標識の部分が問題です。

var blobContours = blobs.FindContoursWithHoles().ToList(); 
using (Mat mask = Mat.Zeros(mat0.Size(), MatType.CV_8UC1)) 
    for (int i = 0; i < blobContours.Count; i++) 
    { 
     var tu = blobContours[i]; 
     var bl = tu.Item1; 
     if (Cv2.ContourArea(bl) > 100) 
     { 
      mask.DrawContour(bl, Scalar.White, -1); 
      foreach (var child in tu.Item2) 
       mask.DrawContour(child, Scalar.Black, -1); 
      Rect rect = Cv2.BoundingRect(bl); 
      Scalar mean = Cv2.Mean(mat0[rect], mask[rect]); 
     } 
    } 
:我々は、単一のマスクとして各ブロブを使用することができ、ブラックなどの穴を描くことで

using PLine = List<Point>; 
using Shape = List<List<Point>>; 
internal static IEnumerable<Tuple<PLine, Shape>> FindContoursWithHoles(this Mat mat) 
     { 
      Point[][] contours; 
      HierarchyIndex[] hierarchy; 
      mat.FindContours(out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); 

      Dictionary<int, bool> dic = new Dictionary<int, bool>(); 
      for (int i = 0; i < contours.Length; i++) 
       if (hierarchy[i].Parent < 0) 
        dic[i] = true; 

      bool ok = false; 
      while (!ok) 
      { 
       ok = true; 
       for (int i = 0; i < contours.Length; i++) 
        if (dic.ContainsKey(i)) 
        { 
         bool isParent = dic[i]; 
         var hi = hierarchy[i]; 
         if (hi.Parent >= 0) dic[hi.Parent] = (!isParent); 
         if (hi.Child >= 0) dic[hi.Child] = (!isParent); 
         while (hi.Next >= 0) 
         { 
          dic[hi.Next] = isParent; 
          hi = hierarchy[hi.Next]; 
          if (hi.Parent >= 0) dic[hi.Parent] = (!isParent); 
          if (hi.Child >= 0) dic[hi.Child] = (!isParent); 
         } 
         hi = hierarchy[i]; 
         while (hi.Previous >= 0) 
         { 
          dic[hi.Previous] = isParent; 
          hi = hierarchy[hi.Previous]; 
          if (hi.Parent >= 0) dic[hi.Parent] = (!isParent); 
          if (hi.Child >= 0) dic[hi.Child] = (!isParent); 
         } 
        } 
        else 
         ok = false; 
      } 
      foreach (int i in dic.Keys.Where(a => dic[a])) 
      { 
       PLine pl = contours[i].ToList(); 
       Shape childs = new Shape(); 
       var hiParent = hierarchy[i]; 
       if (hiParent.Child >= 0) 
       { 
        childs.Add(contours[hiParent.Child].ToList()); 
        var hi = hierarchy[hiParent.Child]; 
        while (hi.Next >= 0) 
        { 
         childs.Add(contours[hi.Next].ToList()); 
         hi = hierarchy[hi.Next]; 
        } 
        hi = hierarchy[hiParent.Child]; 
        while (hi.Previous >= 0) 
        { 
         childs.Add(contours[hi.Previous].ToList()); 
         hi = hierarchy[hi.Previous]; 
        } 
       } 

       yield return Tuple.Create(pl, childs); 
      } 
     } 

enter image description here enter image description here

は、実際に私は、私はこの方法でこの問題を解決したと思います

私はもっと簡単な方法があるはずだと思います。

さらに別の問題があります。場合によっては、標識の個々の赤い部分(別個の白い塊)は、円の外側の親として、および円の内側の子としては見えないが、2つの円を子として持つ大きな親輪郭(すなわち、親として見つからない別個の塊を作る)。はい、階層的には正しいですが、私を助けません。私は自分の英語を残念に思って、私の自己を明確にすることができたと思う。

+0

あなたが使っている画像とマスクをアップロードできますか?私はあなたが言及している '穴'を手に入れません –

+0

穴があるくぼみのサンプル画像を添付できますか?計算は正確ではありませんか? – ZdaR

+0

バイナリイメージでは、blobとは何を考えますか? –

答えて

1

@ミキありがとうございました。私はConnectedComponentsを使って私が望むものを達成することができました。簡単で速い:

var cc = Cv2.ConnectedComponentsEx(binaryImage, PixelConnectivity.Connectivity8); 
foreach (var bl in cc.Blobs) 
    using (Mat mask = new Mat()) 
    { 
     cc.FilterByBlob(binaryImage, mask, bl); 
     Rect rect = bl.Rect; 
     Scalar mean = Cv2.Mean(colorImage[rect], mask[rect]); 
    } 
関連する問題