[OpenCV-Python] 18画像勾配

OpenCV-Python:OpenCVでのIV画像処理

18画像勾配

ターゲット
  •画像の勾配、画像の境界など。
  •使用される関数は、cv2.Sobel()、cv2.Schar()、cv2.Laplacian()などです。

原理
  勾配は単に導関数です。
  OpenCVは、Sobel、Scharr、Laplacianの3つの異なる勾配フィルターまたはハイパスフィルターを提供します。それらを一つずつ紹介していきます。
  SobelとScharrは、実際に1次または2次導関数を見つけています。Scharrは、Sobelの最適化です(小さな畳み込みカーネルを使用して勾配角を解く場合)。ラプラシアンは二次導関数を見つけることです。

18.1Sobel演算子とScharr演算子

Sobel演算子は、ガウス平滑化と微分演算を組み合わせたものであるため、そのアンチノイズ能力は非常に優れています。派生の方向(xorderまたはyorder)を設定できます。使用する畳み込みカーネルのサイズ(ksize)を設定することもできます。ksize = -1の場合、3x3 Scharrフィルターが使用され、その効果は3x3 Sobelフィルターよりも優れています(速度は同じなので、3x3フィルターを使用する場合はScharrフィルターを使用してみてください)。3x3Scharrフィルター畳み込みカーネルは次のとおりです。
   img

18.2ラプラシアン算子

ラプラシアン演算子は、2次導関数の形式で定義できます。その離散実装は、2次ソーベル導関数に類似していると見なすことができます。実際、OpenCVは、ラプラシアン演算子を計算するときに直接ソーベル演算子を呼び出します。次のように計算されます。
     src

ラプラスフィルターで使用される畳み込みカーネル:
      カーネル

コード
  以下のコードは、上記の3つのフィルターを使用して同じ画像を操作します。使用される畳み込みカーネルはすべて5x5です。

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('dave.jpg',0)

laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)

plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])

plt.show()

結果:

ラプラシアン

重要なこと!
  上記の例のコメントを見ると、気付いたかどうかはわかりません。パラメータ-1を使用して、出力画像の深度(データ型)を元の画像と一致するように設定できる場合、しかし私たちはコードにいますしかしcv2.CV_64Fが使用されています。どうしてこれなの?黒から白への境界の導関数が整数であるが、白から黒への境界点の導関数が負であると想像してください。元の画像の深さがnp.int8の場合、すべての負の値は0に切り捨てられます。つまり、境界が失われます。したがって、これら2つの境界の両方を検出する場合は、cv2.CV_16S、cv2.CV_64Fなどの出力データ型を高く設定するのが最善の方法です。絶対値を取得してから、cv2.CV_8Uに戻します。次の例は、出力画像の奥行きによって引き起こされるさまざまな影響を示しています。

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('box.png',0)

# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)

# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)

plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])

plt.show()

結果:

ダブルエッジ

詳細については、公式アカウントに注意してください。
img

おすすめ

転載: blog.csdn.net/yegeli/article/details/113421615