opencv チュートリアルチャンレンジ 81 画像のノイズ除去
画像のノイズ除去 — OpenCV-Python Tutorials 1 documentation
#!/usr/bin/env python # -*- coding: utf-8 -* import sys import cv2 import numpy as np img = cv2.imread('170523-170301.jpg') #img = cv2.imread('170519-174830.jpg') #img = cv2.imread('170519-144402.jpg') #img = cv2.imread('chessboard.jpg') cv2.imshow('goodFeaturesToTrack',img) dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21) cv2.imshow('fastNlMeansDenoisingColored',dst) cv2.imwrite('fastNlMeansDenoisingColored.png',dst) cv2.waitKey(0) cv2.destroyAllWindows()
やってみる
opencv チュートリアルチャンレンジ 43 Shi-Tomasiのコーナー検出とGood Features to Track(追跡に向いた特徴)
Shi-Tomasiのコーナー検出とGood Features to Track(追跡に向いた特徴) — OpenCV-Python Tutorials 1 documentation
#!/usr/bin/env python # -*- coding: utf-8 -* import sys import cv2 import numpy as np img = cv2.imread('170523-170301.jpg') #img = cv2.imread('170519-174830.jpg') #img = cv2.imread('170519-144402.jpg') #img = cv2.imread('chessboard.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(gray, 25, 0.01, 10) corners = np.int0(corners) for i in corners: x,y = i.ravel() cv2.circle(img, (x,y), 3, [0,0,255], -1) cv2.imshow('goodFeaturesToTrack',img) cv2.imwrite('goodFeaturesToTrack.png',img) cv2.waitKey(0) cv2.destroyAllWindows()
opencv チュートリアルチャンレンジ 42 Harrisコーナー検出
Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation
#!/usr/bin/env python # -*- coding: utf-8 -* import sys import cv2 import numpy as np img = cv2.imread('170523-170301.jpg') #img = cv2.imread('170519-174830.jpg') #img = cv2.imread('170519-144402.jpg') #img = cv2.imread('chessboard.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) gray = np.float32(gray) #dst = cv2.cornerHarris(gray, 2, 3, 0.04) dst = cv2.cornerHarris(gray, 4, 5, 0.04) #result is dilated for marking the corners, not important dst = cv2.dilate(dst, None) tmp = np.zeros(dst.shape[:2], np.uint8) tmp[ dst > 0.01*dst.max() ] = [255] tmp[ dst <= 0.01*dst.max() ] = [0] cv2.imshow('cornerHarrisMask',tmp) cv2.imwrite('cornerHarrisMask.png',tmp) # Threshold for an optimal value, it may vary depending on the image. img[ dst > 0.01*dst.max() ] = [0,0,255] cv2.imshow('cornerHarris',img) cv2.imshow('cornerHarris.png',img) cv2.waitKey(0) cv2.destroyAllWindows()
Harrisのコーナー検出を適用した結果は各画素が上記のスコア( R )を表すグレースケール画像になります.適切な閾値処理を施すと,画像中のコーナーを検出できます.
やってみる
cv2.cornerHarris で出てきた結果をゴニョゴニョ(適切な閾値処理)した結果を、コーナーとみなすらしい。
元画像
cv2.cornerHarris の結果
cv2.cornerHarris の閾値処理後
適用結果
opencv チュートリアルチャレンジ14 ハフ変換による円検出
ハフ変換による円検出 — OpenCV-Python Tutorials 1 documentation
void HoughCircles(Mat& image, vector<Vec3f>& circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0) ハフ変換を用いて,グレースケール画像から円を検出します. パラメタ: image – 8ビット,シングルチャンネル,グレースケールの入力画像. circles – 検出された円を出力するベクトル.各ベクトルは,3要素の浮動小数点型ベクトル (x, y, radius) としてエンコードされます. method – 現在のところ, CV_HOUGH_GRADIENT メソッドのみが実装されています.基本的には 2段階ハフ変換 で,これについては Yuen90 で述べられています. dp – 画像分解能に対する投票分解能の比率の逆数.例えば, dp=1 の場合は,投票空間は入力画像と同じ分解能をもちます.また dp=2 の場合は,投票空間の幅と高さは半分になります. minDist – 検出される円の中心同士の最小距離.このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります.逆に大きすぎると,検出できない円がでてくる可能性があります. param1 – 手法依存の 1 番目のパラメータ. CV_HOUGH_GRADIENT の場合は, Canny() エッジ検出器に渡される2つの閾値の内,大きい方の閾値を表します(小さい閾値は,この値の半分になります). param2 – 手法依存の 2 番目のパラメータ. CV_HOUGH_GRADIENT の場合は,円の中心を検出する際の投票数の閾値を表します.これが小さくなるほど,より多くの誤検出が起こる可能性があります.より多くの投票を獲得した円が,最初に出力されます. minRadius – 円の半径の最小値. maxRadius – 円の半径の最大値.
やってみよう
#!/usr/bin/env python # -*- coding: utf-8 -* import sys import cv2 import numpy as np from matplotlib import pyplot as plt cimg = cv2.imread('170523-170301.jpg') img = cv2.cvtColor(cimg,cv2.COLOR_BGR2GRAY) img = cv2.medianBlur(img,15) circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20, param1=50,param2=30,minRadius=0,maxRadius=0) circles = np.uint16(np.around(circles)) for i in circles[0,:]: # draw the outer circle cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) # draw the center of the circle cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) cv2.imshow('HoughCircles',cimg) cv2.imwrite('HoughCircles.png',cimg) cv2.waitKey(0) cv2.destroyAllWindows()
これが
こう
なんだろうか、この検出結果は。
よくみると、複数の光源によって、ゴルフボールに複数の影ができていて、その影を検出しているようだ。
また、テカリ?も検出しているようにみえる。
opencv チュートリアルチャレンジ12 テンプレートマッチング
テンプレートマッチング — OpenCV-Python Tutorials 1 documentation
void matchTemplate(const Mat& image, const Mat& templ, Mat& result, int method) テンプレートと,それに重なった画像領域とを比較します. パラメタ: image – テンプレートの探索対象となる画像.8ビットまたは32ビットの浮動小数点型. templ – 探索されるテンプレート.探索対象となる画像以下のサイズで,同じデータ型でなければいけません. result – 比較結果のマップ.シングルチャンネル,32ビット,浮動小数点型. image が W x H で, templ が w x h とすると result は (W-w+1) x (H-h+1) となります. method – 比較手法の指定(以下の説明を参照してください).
やってみる
#!/usr/bin/env python # -*- coding: utf-8 -* import sys import cv2 import numpy as np from matplotlib import pyplot as plt imgOrg = cv2.imread('mario.png') img = cv2.cvtColor(imgOrg, cv2.COLOR_BGR2GRAY) template = cv2.imread('mario.coin.png',0) w, h = template.shape[::-1] res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED) threshold = 0.99 loc = np.where( res >= threshold) for pt in zip(*loc[::-1]): cv2.rectangle(imgOrg, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1) cv2.imshow('matchTemplate',imgOrg) cv2.imwrite('matchTemplate.png',imgOrg) cv2.waitKey(0) cv2.destroyAllWindows()
検索対象画像
テンプレート画像
マッチ結果
なんというか、ほぼぴったり一致しないとヒットしない。
「顔」のような抽象的な検索ではない。
opencv チュートリアルチャレンジ6 画像の勾配
画像の勾配 — OpenCV-Python Tutorials 1 documentation
Laplacian, sobelx, sobely
やってみよう
#!/usr/bin/env python # -*- coding: utf-8 -* import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('170519-144402.jpg', 0) img = cv2.imread('sudoku-original.jpg', 0) #img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 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([]) cv2.imwrite('Laplacian.png', img) plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) cv2.imwrite('sobelx.png', img) plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray') plt.title('Sobel Y'), plt.xticks([]), plt.yticks([]) cv2.imwrite('sobely.png', img) plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
あれ?
こうなった・・・。
公式のサンプルは、
こうだ。
随分違うぞ?
調べた所、勝手に正規化しているせいらしい。
pyplot — Matplotlib 2.0.2 documentation
正規化しないように指定します。
#!/usr/bin/env python # -*- coding: utf-8 -* import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('170519-144402.jpg', 0) img = cv2.imread('sudoku-original.jpg', 0) plt.subplot(2,2,1),plt.imshow(img, cmap='gray', vmin=0, vmax=255) plt.title('Original'), plt.xticks([]), plt.yticks([]) laplacian = cv2.Laplacian(img,cv2.CV_64F) plt.subplot(2,2,2),plt.imshow(laplacian, cmap='gray', vmin=0, vmax=255) plt.title('Laplacian'), plt.xticks([]), plt.yticks([]) cv2.imwrite('Laplacian.png', img) sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) plt.subplot(2,2,3),plt.imshow(sobelx, cmap='gray', vmin=0, vmax=255) plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) cv2.imwrite('sobelx.png', img) sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5) plt.subplot(2,2,4),plt.imshow(sobely, cmap='gray', vmin=0, vmax=255) plt.title('Sobel Y'), plt.xticks([]), plt.yticks([]) cv2.imwrite('sobely.png', img) plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
まだ、Laplacian の結果がおかしい。
なにかあるのだろうか・・・。
opencv チュートリアルチャレンジ5 モルフォロジー変換
モルフォロジー変換 — OpenCV-Python Tutorials 1 documentation
モルフォロジー変換
とりあえず、カーネルはこれでテスト。
kernel = np.ones((5,5),np.uint8) [ [ 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1 ], [ 1, 1, 1, 1, 1 ] ]
ということだ。
[ [ 0, 0, 1, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 1, 0, 0 ] ]
とすれば、縦方向にだけ評価して適用してくれる、、、のかな。
元画像はこれ
おそらく、黒い背景
が前提の処理だと思う。
収縮(Erosion)
img = cv2.erode(img,kernel,iterations = 1)
膨張(Dilation)
dilation = cv2.dilate(img,kernel,iterations = 1)
オープニング(Opening)
オープニング処理は 収縮の後に膨張 をする処理です.上述したようにノイズ除去に有効です
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
クロージング(Closing)
クロージング処理はオープニング処理の逆の処理を指し, 膨張の後に収縮 をする処理です.前景領域中の小さな(黒い)穴を埋めるのに役立ちます
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
モルフォロジー勾配
膨張した画像と収縮した画像の差分をとる処理です.
結果として物体の外郭(境界線)が得られます.
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
トップハット変換
ブラックハット変換
この2つは、使いみちが分かっらない・・・
カーネルの変更
カーネルを変えてみた。
kernel = np.array([ [ 0, 0, 1, 0, 0], [ 0, 0, 1, 0, 0], [ 0, 0, 1, 0, 0], [ 0, 0, 1, 0, 0], [ 0, 0, 1, 0, 0] ], dtype = np.uint8) img = imgOrg img = cv2.erode(img,kernel,iterations = 1) cv2.imshow('erode2', img) cv2.imwrite('erode2.png', img)
全部1と比較してみる。
全部1
縦に1