OpenCVは画像腐食を実現します。


画像の腐食過程は画像の畳込み動作と類似しており、いずれもテンプレートマトリックスを必要として演算の結果を制御し、画像の腐食と膨張の中でこのテンプレート行列を構造要素と呼ぶ。画像の畳込みと同じように、構造要素は任意に画像の中心点を指定でき、構造要素のサイズと具体的な内容は必要に応じて自分で定義できます。構造要素を定義した後、構造要素の中心点を順に画像中の非0要素ごとに置き、構造要素内のすべての要素がカバーする画像ピクセル値が0でない場合、構造要素の中心点に対応する画像ピクセルを保持します。そうでなければ、要素の中心点に対応するピクセルを削除します。画像の腐食過程を模式的に図6-12に示すように、図6-12において左側は腐食すべき原画像であり、中間は構造要素であり、まず構造要素の中心と原画像中のA画素とを重ね合わせる。このとき、構造要素の中心点の左と上の要素で覆われた画像の画素値は共に0であるので、原画像中のA画素を削除する必要がある。構造要素の中心点をB画素と重ね合わせると、構造要素のすべての要素で覆われた画像画素値が1になるので、元の画像のB画素が保持される。構造要素の中心点を原画像の各画素に順次重ね、各画素点が保留または削除されたかどうかを判断し、最終的に原画像が腐食した結果を図中右画像に示す。

画像の腐食はΘ”式(6.4)に示すように、その数学的表現は、画像Aに対する腐食演算とは、構造要素Bを全て含む画素点を求めることであることが、式により分かります。

一般的な長方形構造要素、十字構造要素、楕円構造を生成します。

Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
  • shape:構造要素の種類、選択可能なパラメータおよび意味は表6-5で与えられます。
  • ksize:構造要素のサイズ
  • アンチョー:中心点の位置、標準パラメータは構造要素の幾何学的中心点である。
  • この関数は、画像の形態学的操作において一般的に使用される矩形構造要素、十字構造要素、楕円構造要素を生成するために使用される。関数の最初のパラメータは構造要素の種類です。選択できるパラメータと意味は表で与えられます。関数の2番目のパラメータは構造要素のサイズです。画像腐食の効果に影響します。関数の最後のパラメータは構造要素の中心点であり、十字構造要素の中心点位置のみが画像腐食後の輪郭形状に影響し、他の種類の構造要素の中心点位置は形態学的操作結果の並進量に影響します。

    腐食関数
    
    void erode( InputArray src, OutputArray dst, InputArray kernel,
                             Point anchor = Point(-1,-1), int iterations = 1,
                             int borderType = BORDER_CONSTANT,
                             const Scalar& borderValue = morphologyDefaultBorderValue() );
  • src:入力された腐食待ち画像は、画像のチャンネル数は任意であっても良いが、画像のデータタイプはCV_でなければならない。8 U,CV_16 U,CV_16 S,CV_32 FまたはCV_64 Fの一つ
  • dst:腐食後の出力画像は、入力画像srcと同じサイズとデータタイプを有する。
  • ケネル:腐食操作のための構造要素は、自分で定義しても良いし、get StructuringElement()関数で生成しても良いです。
  • アンチョー:中心点の構造要素中の位置、デフォルトのパラメータは構造要素の幾何学的中心点
  • である。
  • iterations:腐食の回数は、デフォルト値は1です。
  • borderType:ピクセル外挿の選択フラグは、値の範囲を表3-5で与えられます。デフォルトのパラメータはBORDER_です。DEFAULTは、境界値が含まれていないことを示しています。
  • borderValue:境界不変外挿法を使用する場合の境界値。
  • この関数は,構造要素に従って入力画像を腐食し,多チャンネル画像を腐食する際に,チャネルごとに独立して腐食演算を行う。
    関数の最初のパラメータは腐食対象の画像であり,画像のチャンネル数は任意であってもよいが,画像のデータタイプはCV_でなければならない。8 U,CV_16 U,CV_16 S,CV_32 FまたはCV_64 Fの一つ。
    関数の2番目のパラメータは腐食後の出力画像で、入力画像と同じサイズとデータタイプを持っています。
    関数の3番目と4番目のパラメータは構造要素に関連するパラメータで、3番目のパラメータは構造要素で、4番目のパラメータは構造要素の中心位置で、4番目のパラメータのデフォルトはPoint(-1、-1)で、構造要素の幾何学中心は構造要素の中心点である。
    関数の5番目のパラメータは構造元素を使って腐食する回数で、腐食回数が多ければ多いほど効果が顕著で、パラメータのデフォルト値は1で、1回だけ腐食することを示します。
    関数の6番目のパラメータは画像ピクセル外挿法の選択フラグです。
    7番目のパラメータは境界不変外挿法を使用する場合の境界値で、この2つのパラメータは画像の主要部分の腐食操作に影響がないので、多くの場合はデフォルト値を使用すれば良いです。
    この関数の腐食過程は、画像中の非0ピクセルに対してのみ行われるので、画像が0ピクセルを背景にしていると、腐食操作後に画像の内容がより小さくなります。画像が255ピクセルを背景にしていると、腐食操作で画像の内容がより太くなります。
    簡単な例
    
    //
    // Created by smallflyfly on 2021/6/18.
    //
     
    #include "opencv2/opencv.hpp"
     
    #include <iostream>
     
    using namespace std;
    using namespace cv;
     
     
    void drawResult(Mat im, int num, Mat stats, Mat centroids, const string& name) {
        for (int i = 1; i < num; ++i) {
            int x = centroids.at<double>(i, 0);
            int y = centroids.at<double>(i, 1);
            cout << x << " " << y << endl;
            circle(im, Point(x, y), 2, Scalar(0, 0, 255), -1);
            int xmin = stats.at<int>(i, CC_STAT_LEFT);
            int ymin = stats.at<int>(i, CC_STAT_TOP);
            int w = stats.at<int>(i, CC_STAT_WIDTH);
            int h = stats.at<int>(i, CC_STAT_HEIGHT);
     
            Rect rect(xmin, ymin, w, h);
            rectangle(im, rect, Scalar(255, 255, 255), 2);
            putText(im, to_string(i), Point(x+5, y), FONT_HERSHEY_SCRIPT_SIMPLEX, 0.3, Scalar(0, 0, 255), 1);
        }
        imshow(name, im);
    }
     
     
    int main() {
     
        Mat src = (
                    Mat_<uchar>(6, 6) <<
                            0, 0, 0, 0, 255, 0,
                            0, 255, 255, 255, 255, 255,
                            0, 255, 255, 255, 255, 0,
                            0, 255, 255, 255, 255, 0,
                            0, 255, 255, 255, 255, 0,
                            0, 0, 0, 0, 255, 0
                );
        resize(src, src, Size(0, 0), 50, 50, INTER_NEAREST);
        Mat m1, m2;
        m1 = getStructuringElement(0, Size(3, 3));
        m2 = getStructuringElement(1, Size(3, 3));
     
        Mat erodeM1, erodeM2;
        erode(src, erodeM1, m1, Point(-1, -1), 10);
        erode(src, erodeM2, m2, Point(-1, -1), 10);
     
        imshow("src", src);
        imshow("erodeM1", erodeM1);
        imshow("erodeM2", erodeM2);
     
        Mat xbim = imread("xiaobai.jpg");
        Mat xbM1, xbM2;
        erode(xbim, xbM1, m1, Point(-1, -1), 2);
        erode(xbim, xbM2, m2, Point(-1, -1), 2);
     
        imshow("xb", xbim);
        imshow("xbM1", xbM1);
        imshow("xbM2", xbM2);
     
        Mat im = imread("rice.jfif");
        Mat im1 = im.clone();
        Mat im2 = im.clone();
        Mat im3 = im.clone();
     
        Mat gray;
        cvtColor(im, gray, CV_BGR2GRAY);
        Mat riceBin;
        threshold(gray, riceBin, 125, 255, THRESH_BINARY);
     
        Mat out, stats, centroids;
        int count1 = connectedComponentsWithStats(riceBin, out, stats, centroids, 8, CV_16U);
        drawResult(im1, count1, stats, centroids, "no erode");
     
        Mat erodeIm1, erodeIm2;
        erode(riceBin, erodeIm1, m1, Point(-1, -1), 5);
        erode(riceBin, erodeIm2, m2, Point(-1, -1), 5);
     
        int count2 = connectedComponentsWithStats(erodeIm1, out, stats, centroids, 8, CV_16U);
        drawResult(erodeIm1, count2, stats, centroids, "erode1");
        int count3 = connectedComponentsWithStats(erodeIm2, out, stats, centroids, 8, CV_16U);
        drawResult(erodeIm2, count3, stats, centroids, "erode2");
     
        waitKey(0);
        destroyAllWindows();
     
    }

    以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。