OpenCVSharp4で構造要素(structure elements)を使った処理

はじめに

OpenCVの公式サイトを見てstructure elments(≒カーネル)を使った水平線・鉛直線の抽出を勉強した。

方法

structure elementsと一致する箇所だけを残し、楽譜から、線と音符を切り分ける。

  1. 画像を読み込む
  2. 読み込んだ画像を二値化し反転する
  3. 鉛直(水平)線状のstructure elementsを作成
  4. structure elementsを用いてオープン処理し、鉛直(水平)でない領域を除去する。さらに、反転で白黒を元に戻す。
  5. (鉛直成分のみ)輪郭を滑らかにする。

プログラム

using System;  
using OpenCvSharp;  

namespace 垂直線_水平線の検出 {  
    class Program {  
        static void Main(string[] args) {  
            //① 画像をグレースケールとして読み込み  
            Mat src = new Mat(@"D:\src (1).png", ImreadModes.Grayscale);  
            Cv2.ImShow("src", src);  


            //② 二値化&反転を行う  
            Mat bw = new Mat();  
            Cv2.AdaptiveThreshold(src, bw, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.BinaryInv, 15, 3);  
            Cv2.ImShow("bw", bw);  


            //③-a 水平な構造要素を作成  
            Mat horizontal = bw.Clone();  
            int horizontal_size = horizontal.Cols / 30;//構造要素の幅を定義  
            Mat horizontalStructure  
                = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(horizontal_size, 1));  


            //④-a 水平な構造要素を用いてオープン処理し、反転する  
            Cv2.MorphologyEx(horizontal, horizontal, MorphTypes.Open, horizontalStructure, new Point(-1, -1));  
            horizontal = 255 - horizontal;//反転  
            Cv2.ImShow("horizontal", horizontal);  


            //③-b 鉛直な構造要素を作成  
            Mat vertical = bw.Clone();  
            int vertical_size = vertical.Rows / 30;//構造要素の幅を定義  
            Mat verticalStructure  
                = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(1, vertical_size));  


            //④-b 鉛直な構造要素を用いてオープン処理し、反転する  
            Cv2.MorphologyEx(vertical, vertical, MorphTypes.Open, verticalStructure, new Point(-1, -1));  
            vertical = 255 - vertical;//反転  
            Cv2.ImShow("vertical", vertical);  


            //⑤-b 輪郭を滑らかにする  
            Mat edges = new Mat();//輪郭抽出  
            Cv2.AdaptiveThreshold(vertical, edges, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 3, -2);  
            edges.Dilate(Mat.Ones(2, 2, MatType.CV_8UC1));  
            Mat smooth = vertical.Clone();  

            smooth.Blur(new Size(5, 5));  
            smooth.CopyTo(vertical, edges);//輪郭をマスクとしてコピー              
            Cv2.ImShow("refined", vertical);  


            Cv2.WaitKey();  
        }  
    }  
}  

結果

f:id:negizoku:20200920231108p:plain



参考

https://docs.opencv.org/4.0.0/dd/dd7/tutorial_morph_lines_detection.html