python-opencv 第8回:オープン・クローズ操作の詳細解説(その2)(erode関数とdilate関数の詳細解説含む)

目次

概要:

テキスト部分:

原理と機能:

原理分析:

視覚的な表示:

機能分析:

(1) 腐食操作:

(2) 拡張操作:

ケースと操作:

 (1) ストーリー背景:

 (2) ストーリー 1 (オープン操作):

 (3) ストーリー 2 (クローズドオペレーション):

結論:

参考記事: 


概要:

周知のとおり、コンピューター ビジョン ( Computer Version略して CV) は、今日の 人工知能とロボット技術の開発における主要な研究方向であり、 opencvは、特にコンピューター ビジョン プログラミングの技術的および機能的サポートを提供するサードパーティ ライブラリです。、当然注目すべき内容です。

この号では、まず画像の開閉操作に関連する原理と機能分析について説明し、参考としていくつかの古典的なケースを示します。

早速、仮面ブラックです、今日の勉強を始めましょう!

テキスト部分:

print("祝大家每天快乐,love and peace!")

原理と機能:

——初めて玄関を覗いてみると

原理分析:

実際、開閉操作は主にdilateとその弟のerode という2 つの素晴らしい関数を通じて実装されています。

このうち、dilate は画像の形態的拡大に使用され、erode は画像の形態的収縮に使用されます。前号の比喩と同様に、膨張の効果は大雨に相当し、浸食の効果は継続的な干ばつに相当します。

つまり、次のようになります。

拡張視覚化の機能は、領域を増やすという目的を達成するために、画像のピクセルを外側に拡大することです。

侵食視覚化の機能は、画像のピクセルを内側に劣化させて領域縮小の効果を実現することです。

しかし、膨張と腐食の原理を詳しく研究するには、構造要素とアンカー ポイントという 2 つの最も重要な概念を理解する必要があります

(1) 構造要素 -マスク(ウィンドウとしても理解できます) に相当し、操作画像上をスライドし、操作画像のピクセルフレームの一部をその瞬間に選択できます。構造要素は通常長方形で、長さと幅はさまざまです。

(2) アンカー ポイント - 構造要素用。構造要素はその名の通り錨のようなもので、重心を固定する点が構造要素と操作画像の接続位置となります。デフォルトでは、アンカーポイントは構造要素の形状の中心点です。アンカーポイントの選択方法については、以下の機能分析で紹介します。

これら 2 つの概念を理解した後、膨張と腐食の動作原理を簡単に説明できます (複雑な文章を避けるため、以下では、操作された画像を A​​、操作された画像を B と呼びます)。

(1)Erosion - A の画素と構造要素、つまり構造要素のアンカーポイントが A の画素に一致するフレーム選択処理を行い、選択された A の全画素の画素を観察します。構造要素のマスク枠の画素値、最小値をBのこの画素の画素値とする。A の各ピクセルに対して上記の操作を実行して、B を生成します。

         数式は次のとおりです。

 このうち、dst(x,y)はBの座標(x,y)の画素の画素値を表します。

            element(x,y) は構造要素を表します (実際には要素として直接表現できます。構造要素自体は各ピクセルとは何の関係もありません。(x,y) は単にわかりやすくするために追加されています)。

            (x',y') は、アンカー ポイントを基準とした構造要素内の各位置の座標を表します。たとえば、アンカー ポイントの座標は (0,0)、アンカー ポイントの 2 行下 3 列上の座標です。アンカーポイントは (2,-3 ) です。

            src(x+x',y+y') は、A の座標 (x+x',y+y') のピクセルのピクセル値を表します。

            min は最小値を取ることを意味します。

(2) 拡張 - A のピクセルと構造要素に対してフレーム選択プロセスを実行します。つまり、構造要素のアンカー ポイントを A のピクセルに重ね、A のすべてのピクセルの値を観察します。構造要素のマスク枠で選択された画素値、その最大値をBのこの画素の画素値とする。A の各ピクセルに対して上記の操作を実行して、B を生成します。

         数式は次のとおりです。

 このうち、dst(x,y)はBの座標(x,y)の画素の画素値を表します。

            element(x,y) は構造要素を表します (実際には要素として直接表現できます。構造要素自体は各ピクセルとは何の関係もありません。(x,y) は単にわかりやすくするために追加されています)。

            (x',y') は、アンカー ポイントを基準とした構造要素内の各位置の座標を表します。たとえば、アンカー ポイントの座標は (0,0)、アンカー ポイントの 2 行下 3 列上の座標です。アンカーポイントは (2,-3 ) です。

            src(x+x',y+y') は、A の座標 (x+x',y+y') のピクセルのピクセル値を表します。

            max は最大値をとることを意味します。

動作原理を理解した後でも、読者の将来の疑問を事前に解決するために、簡単に説明する必要がある点がいくつかあります。

(1)中心点座標の計算方法:構造要素の行数と列数が奇数であれば中心点は見つけやすいはずですが、行数や列数が偶数の場合はどうなるでしょうか?このとき、行数を例にとると、構造要素の行数の合計が偶数の場合、中心点が位置する行数は、 合計行数/2 で計算できます。 +1、これは中心点が位置する行の数です。列数についても同様です。注: ここで、行番号 (列番号) の最初の桁は 0 ではなく 1 です。

         実際、行数 (列数) が奇数か偶数かに関係なく、次の式を使用して計算できます。

  このうち、ceil関数はオペランドを四捨五入する関数で、例えば(2,3]の範囲のオペランドの場合、ceil関数の結果は常に3になります。

(2)構造要素の選択範囲が操作画像を超えている場合:構造要素が操作画像上をスライドしますが、範囲を超えていない場合は、式に従って操作画像のピクセル値を計算できます。加工されたイメージを超えていますか?このとき、境界が拡張されない場合と境界が拡張される場合の2つの状況が存在する。

境界が拡張されていない場合:操作画像の外側の状況は直接考慮せず、範囲内の状況のみを考慮します。収縮操作の場合は、操作画像内のフレーム化されたピクセル値のうちの最小値のみが考慮され、拡張操作の場合は、操作画像内のフレーム化されたピクセル値のうちの最大値のみが考慮されます。

境界が拡張された場合の状況: 境界が拡張された場合、拡張された境界の値を考慮し、対応する状況に従って操作を実行する必要がありますたとえば、拡張された境界線のタイプ (borderType、後述) が cv2.BORDER_CONSTANT で、拡張された値 (borderValue、同様に後述) が 0 の場合、それは操作された画像の周囲の円と同等です。別の 0 の円(恋の魔法はぐるぐる回る)。マスクで選択できる範囲で範囲外であれば、ピクセル値は0として表示する必要があります。拡張値が3の場合、何度も周回するのは3です。

視覚的な表示:

言葉だけではまだ抽象的すぎるように思えるかもしれないので、グラフィックを使ってより直感的に説明しましょう。

(1) 構造要素は右に示すとおりです。デフォルトでは、アンカー ポイントは中心点にあります。弊社の中心点座標計算方法によると、その中心点は以下になります。

         図の斜めの十字の位置は次のとおりです

(2) 操作後のイメージは右のとおりです

(3) その後の腐食および拡張操作後の画像表示:

①腐食後の画像:;

②展開後の画像:

実際の操作に基づいて、形態腐食および拡張操作がこの記事で説明されている原則と規則に従っている ことを証明できます。

機能分析:

①使用前の準備:

以前の号と同様に、 Rectangle を使用するための前提条件として、古いツールパートナー ---- opencvを引き続き呼び出します。

import cv2

②用途:

この部分については前回説明したので、ここでは繰り返しません。

③ 文法説明:

この問題には、erode と dilate という 2 つの関数があります。これらについては個別に説明します。

(1) 腐食操作:

使用構文: dst = cv2.erode(src、カーネル、dst、アンカー、反復、borderType、borderValue)

パラメータの説明:最初の dst : erode 関数による形態的侵食後に取得されたターゲット画像、データ型は (array) 配列型です。

                  src : erode 関数を使用して処理されたソース画像。データ型も (array) 配列型です。

                  カーネル: 前述の構造要素。構造化要素は、cv2.getStructuringElement 関数、または numpy ライブラリの one 関数または配列関数を通じて構築できます。次に、 cv2.getStructuringElement 関数を使用して構造化要素を構築する方法についてさらに簡単に説明します。

            使用構文: kernel = cv2.getStructuringElement(shape, ksize, anchor)

            パラメータの説明: カーネル: getStructureElement 関数を通じて構築された構造要素。

                              形状: 構造要素の形状。オプションの値は次のとおりです: cv2.MORPH_RECT (長方形)、cv2.MORPH_CROSS (十字)、cv2.MORPH_ELLIPSE (楕円形)。

                              ksize: 構造要素の行と列の数。値の形式は (x, y) です。ここで、x は列数を表し、y は行数を表します (これは直観に反するので注意してください)

                              アンカー:構造要素のアンカー ポイント。値をとらない場合、または値が (-1,-1) の場合、構造要素の中心点がアンカー ポイントとして使用されます。ここで、アンカーポイントの選択に関係するのはcv2.MORPH_CROSSのマスク形状(十字形状)のみであり、その他の形状はここでのアンカーポイントの選択とは関係なく、任意に選択することができる。

                  2 番目の dst : 説明は最初の dst と同じなので繰り返されません。デフォルトは [なし] です。

                  アンカー:構造要素のアンカー ポイント。値をとらない場合、または値が (-1,-1) の場合、構造要素の中心点がアンカー ポイントとして使用されます。getStructuringElement 関数のアンカー ポイントとは異なります。ここでのアンカー ポイントの選択は、すべての形状の構造要素に影響します。

                  iterations : 反復の数。N 回目の反復では、N-1 回目の反復の dst が操作の src として使用され、他のパラメーターは変更されません。

                  borderType : 境界線を拡張する方法。デフォルト値は None で、境界線の拡張は実行されません。具体的なタイプを次の図に示します。

テーブルソース: opencv の borderType のタイプ、erode および dilate 関数は BORDER_WRAP タイプの値をサポートしません。

                  borderValue : borderType 値が cv2.BORDER_CONSTANT の場合、境界線を拡張する要素は borderValue で埋められます。borderValue のデフォルト値は (0, 0, 0) です。もちろん、他の値を指定することもできます。3 つの要素はそれぞれ BGR を表します。RGB ではないことに注意してください。

(2) 拡張操作:

使用構文: dst = cv2.dilate(src、カーネル、dst、アンカー、反復、borderType、borderValue)

パラメータの説明: erode 関数と同じため、詳細は省略します。

以下に参照用の erode および dilate 関数に関連するネイティブ ドキュメントを添付します。

def erode(src: Mat, kernel, dst: Mat = ..., anchor=..., iterations=..., borderType=..., borderValue=...) -> typing.Any:
    '''
    ·"erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) -> dst  
    ·@brief Erodes an image by using a specific structuring element.  

    ·The function erodes the source image using the specified structuring element that determines the  
    ·shape of a pixel neighborhood over which the minimum is taken:

    ·\\f[\\texttt{dst} (x,y) =  \\min _{(x',y'):  \\, \\texttt{element} (x',y') \\ne0 } \\texttt{src} (x+x',y+y')\\f]  

    ·The function supports the in-place mode. Erosion can be applied several ( iterations ) times. In 
    ·case of multi-channel images, each channel is processed independently.

    ·@param src input image; the number of channels can be arbitrary, but the depth should be one of 
    ·CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. 
    ·@param dst output image of the same size and type as src.  
    ·@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular
    ·structuring element is used. Kernel can be created using #getStructuringElement.  
    ·@param anchor position of the anchor within the element; default value (-1, -1) means that the 
    ·anchor is at the element center.   
    ·@param iterations number of times erosion is applied.   
    ·@param borderType pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported. 
    ·@param borderValue border value in case of a constant border   
    ·@sa  dilate, morphologyEx, getStructuringElement"
    ...
    '''
def dilate(src: Mat, kernel, dst: Mat = ..., anchor=..., iterations=..., borderType=..., borderValue=...) -> typing.Any:
    '''
    ·"dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) -> dst 
    ·@brief Dilates an image by using a specific structuring element.      

    ·The function dilates the source image using the specified structuring element that determines the   
    ·shape of a pixel neighborhood over which the maximum is taken:  
    ·\\f[\\texttt{dst} (x,y) =  \\max _{(x',y'):  \\, \\texttt{element} (x',y') \\ne0 } \\texttt{src} (x+x',y+y')\\f]   

    ·The function supports the in-place mode. Dilation can be applied several ( iterations ) times. In   
    ·case of multi-channel images, each channel is processed independently.   

    ·@param src input image; the number of channels can be arbitrary, but the depth should be one of  
    ·CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.   
    ·@param dst output image of the same size and type as src.   
    ·@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular   
    ·structuring element is used. Kernel can be created using #getStructuringElement\n.   
    ·@param anchor position of the anchor within the element; default value (-1, -1) means that the
    ·anchor is at the element center.   
    ·@param iterations number of times dilation is applied.   
    ·@param borderType pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not suported.\   
    ·@param borderValue border value in case of a constant border  
    ·@sa  erode, morphologyEx, getStructuringElement"
    ...
    '''

ケースと操作:

- -小型チョッパー

次に、前号での 2 つの湖の間の小さなインシデントをケース操作として引き続き使用します。

(1) ストーリー背景:

        むかしむかし、二つの湖があり、まるで恋人同士のように寄り添い、真ん中には小さな川が湖を繋いでいたと言われています。近くの人々は、一方を鉄竹湖、もう一方を翠化埔呼び、真ん中の小さな川は二つの小さな湖が手をつないでいるようなので、青寿江と呼んでいます。久しぶりにこんな日が続くようだ。(私が次に何を言おうとしているか知っています:))

鉄竹湖と翠化埔

 (2) ストーリー 1 (オープン操作):

        しかし、このように長い時間が経つと、それはまるで7年間のかゆみに苦しんでいる人のようで、2つの湖はお互いが常に一緒にいるのを嫌うようになりました。そこで二人は神に不平を言い、二人を引き離し、お互いに自分の人生を生きる余地を与えたいと願いました。神は彼らの願いを聞いて、「はい」と答えましたが、彼らは試練を受け入れなければなりません。それは、彼らの間に手を繋いでいた川を断ち切り、彼ら自身の湖を蒸発させる長期にわたる干ばつです。

        二つの湖は長年お互いにうんざりしていたので、二人とも何も言わずに試験を受け入れた。すぐに干ばつが起こり、最初は 2 つの湖は許容範囲内でしたが、容量が少し減ったように感じました。しかし、その後も干ばつの影響は大きく、一日中続いた干ばつのせいで植物は枯れ続け、動物たちも別の居場所を探し、そこに住んでいた村人たちは徐々にこの悲しい場所を離れていきました。最終的に、蓮寿江は完全に蒸発し、2つの湖は完全に分離されました。しかし、周囲の環境はすでに荒廃しており、湖は活気を失っています。鉄竹湖と翠化埔も昔を思い出し始め、当時に比べて非常に輝いていて美しいです。

        徐々に時間が経ち、干ばつが終わり、雨季が到来しました。雨水が降り続けるにつれて、2つの湖の面積はゆっくりと拡大し始め、相互接続への希望が彼らの心に芽生え始めました。しかし、雨季が明け、両湖は以前とほぼ同じ面積まで回復しただけで、依然として湖同士は繋がっておらず、ハンズハンド川の河床は長い間、両湖の間の乗り越えられない高地となっていた。二つ。 

import cv2
import numpy as np

img = cv2.imread("F://src.jpg")

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10))

img1 = cv2.erode(img,kernel,iterations=2)
img2 = cv2.dilate(img1,kernel,iterations=3)

cv2.imwrite("F://rst1.jpg",img2)

cv2.imshow("src",img)
cv2.imshow("rst1",img2)
cv2.waitKey(5000)
cv2.destroyAllWindows()
互いに離れた 2 つの湖

 

 (3) ストーリー 2 (クローズドオペレーション):

        二つの湖は再び結ばれることを願い、再び神に祈りました。神は、もし彼らが本当にそうしたいのなら、今度はあなたの願いを叶えて差し上げますが、まだ条件が1つあります、それは、今回は手を繋ぐ川でつながっているだけではなく、完全に統合されているということです。あなたが私の中にいて、私があなたの中にいるという状況を達成するために湖を作ります。そして、これが最後の願い、一度ひとつになったら二度と離れることはできない。

        今回は鉄竹も翠華もすぐには結論が出ず、二人とも長い時間をかけて考え、熟考した。最後に、彼らは自分たちの選択を神に告げました。二人とも一つになりたいと思ったのです。神は「そうだ」と言ってあなたの願いを叶えてくれるでしょう。その後、大雨が降りました。雨は激しいだけでなく長く続き、ハンドハンド川の河床に水が補充され、さらに拡大し続けました。雨が激しすぎて、動植物の生存に適さない環境が再び戻ってきました。湖の周囲は再び無人になりました。しかし、今回、二つの湖は何の不満もありませんでした。彼らはそれを黙って受け入れることを選択しました。支援します。」お互い、最後の瞬間まで一緒にいよう。

        やがて雨が止み、太陽が顔を出し、一つになった湖に波紋が広がった。雨季の終わりとともに、湖の面積は徐々に通常の大きさに戻りましたが、それ以来、湖が分離されることはありませんでした。その後、人々は 2 つの湖が 1 つになっていることを知りましたが、もはや 2 つの湖の名前は覚えておらず、和心海という湖があることだけを知っていました。毎年、多くのカップルがここに祈りに来ます。お互いの愛が和心海の原点のようになるように願います。さまざまな困難を経験しましたが、戻ってきたら決して離れることはなく、幸せな時間を過ごします。一緒の日々。

import cv2
import numpy as np

img = cv2.imread("F://rst1.jpg")

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10),anchor=(0,0))

img1 = cv2.dilate(img,kernel,iterations=6)
img2 = cv2.erode(img1,kernel,iterations=3)

cv2.imwrite("F://rst2.jpg",img2)

cv2.imshow("rst1",img)
cv2.imshow("rst2",img2)
cv2.waitKey(5000)
cv2.destroyAllWindows()
和心海

 

        最も貴重な愛は一目惚れではなく、波や砂を越えても輝き続けるお互いへの忠誠心と責任感だと私は信じています。風や霜、時間の堆積という試練を乗り越えた真珠だけが、艶やかで透明感のある真珠になるのです。後漢時代の崔源が書いた「座右の銘」の碑文には、「涅槃には子がなく、暖かさの中に光がある」と言われています。

結論:

この記事では、膨張と腐食の基本原理を学ぶとともに、中心点座標の計算方法、構造要素のフレーム選択が制限を超えるさまざまな状況など、作業中に注意すべきいくつかのポイントを学びました。操作された画像などを学習し、侵食関数と拡張関数の各パラメータの意味と設定方法を学び、最後に、美しい(昔ながらの)ラブストーリーを背景として、実際の開閉操作の例を示します。全体的に充実した内容となっておりますので、皆様に知識を学んで幸せになっていただければ幸いです。

 以上、内容は以上です。ぜひ注目して、「いいね!」を押して集めていただければ幸いです。皆さん、ありがとうございました!

  はい、仮面ブラックです。皆様の平和と繁栄を祈ります、またお会いしましょう! よーよ〜〜

参考記事: 

OpenCV-Python 画像処理: 腐食と拡張の原理、および侵食と拡張関数の概要

おすすめ

転載: blog.csdn.net/m0_55320151/article/details/132015619