概要
しきい値処理は、画像の基本的なセグメンテーションを実行し、ピクセルが 0
or 1
(または 255
それらを表すために整数を使用している場合)。
通常、しきい値処理を使用して、画像内の単純な背景と前景のセグメンテーションを実行できます。これは、各ピクセルの単純な手法のバリエーションに要約されます。
if pixel_value > threshold:
pixel_value = MAX
else:
pixel_value = 0
この重要なプロセスは次のように知られています。 バイナリしきい値処理. 現在、この一般的な考え方を微調整する方法はいくつかあります。たとえば、操作を逆にする ( >
で署名する <
記号)、設定 pixel_value
threshold
最大値/0 (切り捨てと呼ばれる) の代わりに、 pixel_value
それが上にある場合、それ自体 threshold
またはそれより下にある場合 threshold
.
これらはすべて、次のように OpenCV で便利に実装されています。
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
… それぞれ。 これらは、かなり単純で、画像のコンテキストを考慮せず、どのような形状が一般的かについての知識があるなどの点で、比較的「単純な」方法です。これらのプロパティについては、計算コストが高く強力な方法を採用する必要があります技術。
さて、「素朴な」方法でも - 一部 適切なしきい値を見つけるために、ヒューリスティックを導入することができます。これには、Otsu メソッドと Triangle メソッドが含まれます。
cv2.THRESH_OTSU
cv2.THRESH_TRIANGLE
注: OpenCV のしきい値処理は初歩的な手法であり、照明の変化やグラデーション、色の不均一性などの影響を受けます。比較的きれいな画像に適用するのが最適です。画像をぼかしてノイズを減らした後、セグメント化するオブジェクトの色のばらつきが大きくありません。
単一のしきい値を使用した基本的なしきい値処理に関する問題のいくつかを克服する別の方法は、次を使用することです。 適応しきい値 これは、グローバルではなく、画像内の小さな領域ごとにしきい値を適用します。
OpenCV による単純なしきい値処理
OpenCV の Python API でのしきい値処理は、 cv2.threshold()
method – 画像 (整数で表される NumPy 配列)、しきい値、最大値、およびしきい値処理方法 (どのように threshold
& maximum_value
使用されています):
img = cv2.imread('objects.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blurred = cv2.GaussianBlur(img, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)
戻りコードは、適用されたしきい値です。
print(f"Threshold: {ret}")
ここで、閾値は 220
そして、私たちは THRESH_BINARY
method – 上記のすべてのピクセル値 220
に増加します 255
、下のすべてのピクセル値 220
に引き下げられます 0
、前景オブジェクトを覆う「マスク」を使用して白黒画像を作成します。
なんで220? 画像がどのように見えるかを知ることで、選択できるしきい値についておおよその推測を行うことができます。 実際には、手動でしきい値を設定する必要はほとんどないため、自動しきい値の選択についてはすぐに説明します。
結果をプロットしましょう! OpenCV ウィンドウは少し扱いにくいので、Matplotlib を使用して元の画像、ぼやけた画像、および結果をプロットします。
fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)
しきい値処理方法
前述のように、関数でしきい値と最大値を使用するにはさまざまな方法があります。 最初にバイナリしきい値を見てきました。 メソッドのリストを作成し、それらを XNUMX つずつ適用して、結果をプロットしましょう。
methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']
def thresh(img_path, method, index):
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blurred = cv2.GaussianBlur(img, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 220, 255, method)
fig, ax = plt.subplots(1, 3, figsize=(12, 4))
fig.suptitle(names[index], fontsize=18)
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)
plt.tight_layout()
for index, method in enumerate(methods):
thresh('coins.jpeg', method, index)
THRESH_BINARY
& THRESH_BINARY_INV
は互いに逆であり、画像を XNUMX 値化します。 0
& 255
、それらをそれぞれ背景と前景に割り当て、その逆も同様です。
THRESH_TRUNC
間の画像を二値化します threshold
& 255
.
THRESH_TOZERO
& THRESH_TOZERO_INV
間で二値化 0
および現在のピクセル値 (src(x, y)
)。 結果の画像を見てみましょう。
ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!
これらの方法は十分に直感的ですが、適切なしきい値を自動化するにはどうすればよいでしょうか? また、「適切なしきい値」とは何を意味するのでしょうか? これまでの結果のほとんどには、マークや斑点が含まれる理想的ではないマスクが含まれていました。 これは、コインの反射面の違いが原因で発生します。リッジが光を反射する方法が異なるため、コインの色は均一ではありません。
より良いグローバルしきい値を見つけることで、ある程度これと戦うことができます.
OpenCV による自動/最適化されたしきい値処理
OpenCV は、XNUMX つの効果的なグローバルしきい値検索方法 (Otsu の方法と Triangle 方法) を採用しています。
大津の方法は、それが働いていることを前提としています バイモーダル 画像。 バイモーダル イメージは、カラー ヒストグラムに XNUMX つのピークしか含まれない (つまり、XNUMX つの異なるピクセル値しかない) イメージです。 ピークがそれぞれ「背景」や「前景」などのクラスに属していることを考えると、理想的なしきい値はそれらの中間にあります。
画像クレジット: https://scipy-lectures.org/
一部の画像は、ガウスぼかしを使用してよりバイモーダルにすることができますが、すべてではありません。
代替の、多くの場合、より優れたパフォーマンスのアルゴリズムは三角形アルゴリズムです。これは、グレー レベル ヒストグラムの最大値と最小値の間の距離を計算し、線を描画します。 その線がヒストグラムの残りの部分から最大に離れている点がしきい値として選択されます。
これらはどちらもグレースケールの画像を想定しているため、次の方法で入力画像をグレーに変換する必要があります cv2.cvtColor()
:
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)
masked = cv2.bitwise_and(img, img, mask=mask1)
両方の方法で画像を実行し、結果を視覚化しましょう。
methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']
def thresh(img_path, method, index):
img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
ret, img_masked = cv2.threshold(blurred, 0, 255, method)
print(f"Threshold: {ret}")
fig, ax = plt.subplots(1, 3, figsize=(12, 5))
fig.suptitle(names[index], fontsize=18)
ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))
for index, method in enumerate(methods):
thresh('coins.jpeg', method, index)
ここでは、イメージがバイモーダルではないため、三角形の方法が Otsu の方法よりも優れています。
import numpy as np
img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)
ただし、三角形の方法がどのように画像を処理し、より満足のいく結果を生み出すことができたかは明らかです。
OpenCV しきい値処理の制限
OpenCV を使用したしきい値処理は、シンプルで簡単かつ効率的です。 とはいえ、かなり限定的です。 カラフルな要素、不均一な背景、変化する照明条件を導入するとすぐに、概念としてのグローバルなしきい値設定は硬直的になりすぎます。
通常、画像は複雑すぎて単一のしきい値では十分ではありません。 適応しきい値、単一のグローバルしきい値ではなく、多くのローカルしきい値が適用されます。 制限もありますが、適応しきい値処理はグローバルしきい値処理よりもはるかに柔軟です。
まとめ
近年、バイナリ セグメンテーション (ここで行ったように) とマルチラベル セグメンテーション (任意の数のクラスをエンコードできる) が、はるかに強力で柔軟なディープ ラーニング ネットワークでうまくモデル化されています。 さらに、グローバルおよびローカル コンテキストを、セグメント化する画像にエンコードできます。 欠点は、トレーニングするためのデータと、時間と専門知識が必要なことです。
オンザフライで単純なしきい値処理を行うには、OpenCV を使用できます。 正確な本番レベルのセグメンテーションを行うには、ニューラル ネットワークを使用する必要があります。
さらに先へ - コンピュータ ビジョンのための実用的な深層学習
あなたの好奇心旺盛な性質は、さらに先へ進みたいと思わせますか? 私たちは私たちをチェックアウトすることをお勧めします コース: 「Pythonによるコンピュータビジョンのための実践的な深層学習」.
別のコンピューター ビジョン コースですか?
MNIST 数字や MNIST ファッションの分類は行いません。 彼らはずっと前に彼らの役割を果たしました。 高度なブラックボックス アーキテクチャにパフォーマンスの負担を負わせる前に、あまりにも多くの学習リソースが基本的なデータセットと基本的なアーキテクチャに焦点を合わせています。
私たちが注目したいのは 謎解き, 実用性, 理解する, 直感 & 実際のプロジェクト. 学びたい の あなたは違いを生むことができますか? 私たちの脳が画像を処理する方法から、乳がんの研究レベルのディープ ラーニング分類器の作成、「幻覚」を起こすディープ ラーニング ネットワークまで、実際の作業を通じて原理と理論を教え、コンピュータビジョンを解決するためにディープラーニングを適用する専門家になるためのノウハウとツール。
内部には何がありますか?
- ビジョンの第一原理と、コンピューターに「見る」ことを教える方法
- コンピューター ビジョンのさまざまなタスクとアプリケーション
- あなたの仕事を楽にする貿易ツール
- コンピュータ ビジョンのためのデータセットの検索、作成、および利用
- 畳み込みニューラル ネットワークの理論と応用
- データセット内のドメイン シフト、共起、およびその他のバイアスの処理
- 転移学習と、他人のトレーニング時間と計算リソースを自分の利益のために利用する
- 最先端の乳がん分類器の構築とトレーニング
- 主流のアイデアに健全な懐疑心を適用し、広く採用されている手法の意味を理解する方法
- t-SNE と PCA を使用した ConvNet の「概念空間」の可視化
- 企業がコンピューター ビジョン技術を使用してより良い結果を達成する方法のケース スタディ
- 適切なモデル評価、潜在空間の可視化、モデルの注意の特定
- ドメイン調査の実施、独自のデータセットの処理、モデル テストの確立
- 最先端のアーキテクチャ、アイデアの進展、それらの独自性と実装方法
- KerasCV – 最先端のパイプラインとモデルを作成するための WIP ライブラリ
- 論文を解析して読み、自分で実装する方法
- 用途に応じた機種選定
- エンドツーエンドの機械学習パイプラインの作成
- Faster R-CNN、RetinaNet、SSD、YOLO を使用したオブジェクト検出のランドスケープと直感
- インスタンスとセマンティック セグメンテーション
- YOLOv5によるリアルタイム物体認識
- YOLOv5 オブジェクト検出器のトレーニング
- KerasNLP (業界で強力な WIP ライブラリ) を使用したトランスフォーマーの操作
- トランスフォーマーを ConvNets と統合して画像のキャプションを生成する
- DeepDream
- コンピューター ビジョンのためのディープ ラーニング モデルの最適化