【OpenCV】cv2.Canny関数でエッジ検出した画像の表示
Canny関数とは取得した画像の輝度差が大きい部分を輪郭として検出するためのOpenCVの関数です。
例えば、文字の認識(OCR)やLEDランプの点灯監視といった自動認識の前処理フィルタとして使えます。
このプログラムはカラーカメラで取得した画像をモノクロに変換し、変換後の画像をさらにOpenCVライブラリCanny関数を使ってエッジ検出し、1秒ごとに表示を行っています。
カメラで画像を取得したときに、エッジを見つけるために取得した画像内にある隣り合うピクセルの輝度値の差が大きい場合に、それを境界線として検出します(ソーベルフィルタ)。Cannyフィルタはノイズ除去のために画像を平滑化(ガウシアンフィルタ)した後にソーベルフィルタを使って輪郭を境界線として検出しています。
なお、このサンプルプログラムはTheImagingSource社製のモジュールを使用せず、OpenCVのオープンソースのライブラリのみを用いたPythonのコーディングとなります。
検証のための準備
実行結果
エッジ検出後の画像
モノクロ:cvtColor処理後の画像(比較のため記載)
プログラム解説
OpenCVモジュールをインポートします。
import cv2
OpenCVライブラリを使ってVideoCaptureオブジェクトを取得します。
USBカメラを読み込む場合はVideoCaptureの引数にカメラの番号を指定します(PCに内蔵カメラが搭載されている場合、内蔵カメラに0が割り振られるのでUSBカメラは1以降の番号になります)。
capture = cv2.VideoCapture(1)
サンプルではwhile文のループ中に下記の手順で画像の取得し画像処理を行っています。
① capture.readで画像の読み取り
② cvtColor関数 を使いカメラから取得した画像をモノクロ化。
詳細は下記を参照
(OpenCVのcvtColor関数でモノクロ化した画像の表示・保存するプログラムについて)
③ Canny関数を使い②でモノクロ化した画像をエッジ検出
(第1引数:②でモノクロ化した画像,第2引数:小さい閾値,第3引数:大きい閾値)
輝度差(勾配)を境界線として表示するか判定するために大きい閾値と小さい閾値を使用します。
輝度差が閾値(大きい閾値)よりも大きい場合、境界線として認識します。
Canny関数は「設定した閾値(大きい閾値)よりも輝度差が大きい場合」と、「ヒステリシス閾値(※)内の輝度差であっても隣のピセルの輝度差が大きい場合」にそのピクセルを境界線として判定します。
※補足:ヒステリシス閾値とは大きい閾値と小さい閾値の間の領域です。 例えば、大きい閾値を100、小さい閾値を30としたときに、あるピクセルの勾配が70であったとき、隣りのピクセルの勾配が100を超えている場合はそのピクセルは境界線となりますが、隣のピクセルの勾配が大きい閾値100を下回っている場合はそのピクセルは境界線にはなりません。
④ imshowで表示(第1引数:ウィンドウ名,第2引数:③でエッジ検出した画像)
try:
while(True):
# ①画像の読み取り
ret,frame=capture.read()
# ②モノクロ化
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# ③エッジ検出
gray=cv2.Canny(gray,100,200)
# ④ウィンドウ表示
cv2.imshow("frame_canny",gray)
cv2.waitKey(10)