OpenCVは画像膨張を実現します。


画像の膨張は画像腐食と逆のプロセスであり、画像腐食と同様に、画像膨張を制御するための構造要素の効果が必要である。構造要素は任意に構造の中心点を指定でき、構造要素のサイズと具体的な内容は必要に応じて自分で定義できます。構造要素を定義した後、構造要素の中心点を順に画像の各非0要素に置き、元の画像の中の要素が構造要素によって覆われている場合、この画素の画素値は構造要素の中心点に対応する画素点の画素値と同じではないので、元の画像の画素値を構造要素の中心点に対応する画素値に修正する。画像の膨張過程を模式図に示すように、図中左側は膨張すべき原画像であり、中間は構造要素であり、まず構造要素の中心を原画像中のA画素と重ね合わせ、構造要素で覆われた全ての画素の画素値を1に修正し、構造要素中の心点を原画像中の各画素に順次重ね合わせて、充填が必要な画素があるか否かを判断する。原画像膨張の結果を図中右画像に示します。

画像膨張数学は式(6.5)に示すような形を示していますが、画像Aの膨張演算は、構造要素Bを全て含む画像を生成することができることを式で示しています。

膨張関数

void dilate( 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つのパラメータは画像の主要部分の膨張動作に影響がないので、多くの場合はデフォルト値を使用すれば良い。
    簡単な例
    
    //
    // Created by smallflyfly on 2021/6/18.
    //
     
    #include "opencv2/opencv.hpp"
     
    #include <iostream>
     
    using namespace cv;
    using namespace std;
     
    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 dilateM1, dilateM2;
        dilate(src, dilateM1, m1, Point(-1, -1), 5);
        dilate(src, dilateM2, m2, Point(-1, -1), 5);
     
        imshow("src", src);
        imshow("dilateM1", dilateM1);
        imshow("dilateM2", dilateM2);
     
        Mat xbim = imread("xiaobai.jpg");
        Mat xbM1, xbM2;
        dilate(xbim, xbM1, m1, Point(-1, -1), 2);
        dilate(xbim, xbM2, m2, Point(-1, -1), 2);
     
        imshow("xbim", xbim);
        imshow("xbM1", xbM1);
        imshow("xbM2", xbM2);
     
        Mat im = imread("rice.jfif");
        resize(im, im, Size(0, 0), 0.6, 0.6);
        Mat im1 = 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(im, count1, stats, centroids, "no dilate");
     
        Mat dilateIm1, dilateIm2;
        dilate(riceBin, dilateIm1, m1, Point(-1, -1), 5);
        dilate(riceBin, dilateIm2, m2, Point(-1, -1), 5);
     
        int count2 = connectedComponentsWithStats(dilateIm1, out, stats, centroids, 8, CV_16U);
        drawResult(dilateIm1, count2, stats, centroids, "dilateIm1");
        int count3 = connectedComponentsWithStats(dilateIm2, out, stats, centroids, 8, CV_16U);
        drawResult(dilateIm2, count3, stats, centroids, "dilateIm2");
     
        waitKey(0);
        destroyAllWindows();
     
    }

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