2.1K Views
April 12, 22
スライド概要
次のイベントの講演資料です。
https://sciencepark.connpass.com/event/241381/
サイエンスパークの勉強会の資料を公開します。勉強会は2022/3現在、connpassで公開しています。 https://sciencepark.connpass.com
ミニWDDDS AIを使わない?!物体検出 Deep Learning・機械学習を使わない 純粋な画像処理による物体検出 © SCIENCEPARK CORPORATION. 2022/04/07 画像システム課 原英明 SP2204-E03
ミニWDDDS 目次 1. なぜAIを使わないのか? 2. 純粋な画像処理のメリット 3. 物体検出 4. デモ 5. おうちでも試してみよう 2
ミニWDDDS なぜAIを使わないのか? 1. 学習データを用意するコストが高い →精度の高い学習データを大量に用意する必要あり 2. 出力に対して明確な説明ができない →出力プロセスについて確実なことが言えない 3
ミニWDDDS 純粋な画像処理のメリット 1. 学習データが不要 →数枚の画像データから始めることが可能 2. 出力に対して明確な説明が可能 →プロセスが単純明快 4
ミニWDDDS 物体検出 環境 前提条件 硬貨(コイン)検出 environments Prerequisites Coin detection 5
ミニWDDDS 環境 • Python 3.10.4 →https://www.python.org/downloads/ • OpenCV 4.5.5 →https://opencv.org/releases/ or →pip install opencv-python==4.5.5.64 6
ミニWDDDS 前提条件 ✓ 各硬貨同士が重なるまたは隣接(15ピクセル以内)して置かれることはない。 ✓ 硬貨を正面から撮影した画像である。 ✓ 画像には背景と硬貨のみが写っている。 ✓ 背景は模様の少ない黒一色で硬貨に対する白飛びはないものとする。 ✓ 画像に対する硬貨の大きさは画像の100分の1以上、5分の1以下とする。 硬貨の種類は2022年4月現在、日本銀行から発行されている有効な硬貨6種類(500円硬 ✓ 貨,100円硬貨,50円硬貨,10円硬貨,5円硬貨,1円硬貨)を対象とする。ただし、令和3年発行 の新500円硬貨は除く。 7
ミニWDDDS 硬貨(コイン)検出 グレース ケール 1 描画 2値化 2 ガウシアン フィルタ 3 4 5 輪郭抽出 8
ミニWDDDS 元画像 import cv2 src_img = cv2.imread(in_img) if src_img is None: return • 画像読み込み • エラーチェック • cv2.imread()で画像を読み込むことができる →ただし、日本語が含まれるパスはエラーになるので、要注意! • 「画像パスが間違っている」または「読み込みができていない」 →Noneが入る(この時点ではエラーにならないことに注意) 9
ミニWDDDS グレースケール • グレースケール変換 gray = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY) • cv2.cvtColor()で画像を様々な形式に変更できる →今回は引数にcv2.COLOR_BGR2GRAYを与えることでグレー画像に変換 →グレースケールの重み付けは「0.299*R+0.587*G+0.114*B」 →ちなみにOpenCVではチャンネルをBGRの順番で保持することに注意 10
ミニWDDDS ガウシアンフィルタ • ぼかし処理 gaus = cv2.GaussianBlur(gray, (5, 5), 3) • • 指定カーネルの大きさとフィルタ係数に応じて重みが変わるガ ウシアンカーネルが使われる ここでは5*5のフィルタで標準偏差は3 11
ミニWDDDS 二値化 bin_img = cv2.adaptiveThreshold( gaus, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 41, 2 ) • 二値化 • 適応的二値化 →画像内で輝度値の差が大きい場合(明るい部分と暗い部分が両方 ある場合等)は、一律で閾値を決めてしまうと画像全体をうまく二 値化できない。適応的二値化は決められたカーネルサイズごとに閾 値を決めるため、画像全体の輝度値の差に影響されずに二値化でき る • OpenCV 二値化 →http://labs.eecs.tottoriu.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/ py_thresholding/py_thresholding.html 12
ミニWDDDS 輪郭抽出 def find_circle_contours(contours, thresh_area): new_cnt = [] for cnt in contours: area = cv2.contourArea(cnt) if thresh_area[0] > area or area > thresh_area[1]: continue (center_x, center_y), radius = cv2.minEnclosingCircle(cnt) circle_area = int(radius * radius * np.pi) if circle_area <= 0: continue area_diff = circle_area / area if 0.9 > area_diff or area_diff > 1.1: continue new_cnt.append(cnt) return new_cnt def main() -> None: height, width = src_img.shape[:2] max_area = math.ceil((width * height) / 2) min_area = math.ceil((width * height) / 100) contours, hierarchy = cv2.findContours( bin_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE ) • 輪郭検出 • 輪郭抽出 • cv2.findContoursで二値化画像に対して輪郭検出を 行う • 検出した全輪郭から円に近い形の輪郭のみを残す →cv2.contourAreaで輪郭内の面積を計算 →cv2.minEnclosingCircleで輪郭を囲む最小の円の面積 を計算 →面積差が閾値内なら輪郭が円であると推定できる coin_contours = find_circle_contours(contours, (min_area, max_area)) 13
ミニWDDDS 輪郭抽出 検出した輪郭 面積が違う 輪郭を囲む最小の円 面積が違う 面積がほぼ同じ 14
ミニWDDDS 輪郭抽出 • 実際に検出した輪郭 • 図では赤い部分に相当 検出した輪郭 この部分 15
ミニWDDDS 輪郭抽出 • 実際に検出した輪郭 • 図では黒い部分に相当 輪郭を囲む最小の円 この部分 16
ミニWDDDS 輪郭抽出 • 円の形に近い輪郭 閾値内の輪郭 17
ミニWDDDS 描画 • 輪郭を描画 dst_img = src_img.copy() for cnt in coin_contours: cv2.drawContours(dst_img, [cnt], -1, (0, 0, 255), 2) • Cv2.drawContoursで輪郭を描画できる 18
ミニWDDDS デモ こちらのURLから動画(gif)を確認できます。 https://github.com/spc-ehara/coin_detection 19
ミニWDDDS おうちでも試してみよう • Qiita 硬貨(コイン)を検出してみよう →https://qiita.com/spc_ehara/items/e627f5633d0e9d98a39a 硬貨(コイン)の種類を判別してみよう →https://qiita.com/spc_ehara/items/b0c913a89877615d30b2 くっついている硬貨(コイン)を検出してみよう →https://qiita.com/spc_ehara/items/afba011e15392c7851f6 • Github →https://github.com/spc-ehara/coin_detection.git 本日解説したデモ:demo.py 各硬貨の種類判別:coin_detection.py 20
ミニWDDDS ご清聴ありがとうございました!