質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

6393閲覧

Python OpneCV 輪郭抽出について

vibrato

総合スコア52

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/12/06 15:16

編集2017/12/06 15:59

https://blanktar.jp/blog/2015/07/python-opencv-crop-box.html
こちらのページを参考に輪郭抽出のコードを勉強しています。

実行結果がエラーになるので原因を探ってみると

Python

1 # 一部抜粋 2 while True: 3 orig = cam.read()[1] 4 5 lines = orig.copy() 6 7 # 輪郭を抽出する 8 canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY) 9 canny = cv2.GaussianBlur(canny, (5, 5), 0) 10 canny = cv2.Canny(canny, 50, 100) # 輪郭を抽出 11 cv2.imshow('canny', canny) 12 13 cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0]

下記は上記のうちの二行

Python

1 # ここまでは各要素にそれらしい値が入っている 2 canny = cv2.GaussianBlur(canny, (5, 5), 0)

Python

1 # ここで全要素が「0」になる 2 canny = cv2.Canny(canny, 50, 100)

Canny()を通るとnumpyの二次元配列480*640の全要素が「0」になってしまい、その後の計算に支障をきたしているようです。

原因は何なのでしょうか?ご教授お願いいたします。

###追記
エラー箇所( line 52 )

python

1 while True: 2 orig = cam.read()[1] 3 4 lines = orig.copy() 5 6 # 輪郭を抽出する 7 canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY) 8 canny = cv2.GaussianBlur(canny, (5, 5), 0) 9 canny = cv2.Canny(canny, 50, 100) # 輪郭を抽出 10 cv2.imshow('canny', canny) 11 12 cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0] 13 14 cnts.sort() 15 16 warp = None 1751 for i, c in enumerate(cnts): 1852 arclen = cv2.arcLength(c, True)

C:\Users\○○○\Desktop>contour_extraction.py
OpenCV Error: Assertion failed (count >= 0 && (depth == 5 || depth == 4)) in cv::arcLength, file D:\Build\OpenCV\opencv-3.3.1\modules\imgproc\src\shapedescr.cpp, line 284
Traceback (most recent call last):
File "C:\Users\○○○\Desktop\contour_extraction.py", line 52, in <module>
arclen = cv2.arcLength(c, True)
cv2.error: D:\Build\OpenCV\opencv-3.3.1\modules\imgproc\src\shapedescr.cpp:284: error: (-215) count >= 0 && (depth == 5 || depth == 4) in function cv::arcLength

###補足
質問トップにあるURLをコピペしただけなので、そちらのソースコードを見ていただけると詳しくわかると思いますが、webカメラのキャプチャからイメージを取得してます。
今回キャプチャしたものは自身の顔含むプライベートな画像(映像)であるため、大変申し訳ないですが、こちらに張り付けることはしないつもりです。
ただそのような画像(映像)を使った上でのエラーであると認識していただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2017/12/06 15:28

具体的にどのようなエラーが生じているのでしょうか?また、差し支えなければ、実際に処理している画像をお貼りください。
vibrato

2017/12/06 16:00

追記させていただきました。よろしくお願いいたします。
guest

回答1

0

ベストアンサー

エラーの原因

ご提示のリンク先のページと今とでは、findContoursの返り値が異なるようです。

Python

1cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[0] 2cnts.sort()

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

Python

1cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1] 2# cnts.sort()

Cannyエッジ検出器が上手く動作しない

私の環境では再現しませんでした。適宜閾値を調節してみてください。

動いたコード

一応、私の環境で動作するコードがこちら。ほぼコピペですが。

Python

1import cv2 2import numpy as np 3 4 5def transform_by4(img, points): 6 """ 4点を指定してトリミングする。 """ 7 8 points = sorted(points, key=lambda x:x[1]) # yが小さいもの順に並び替え。 9 top = sorted(points[:2], key=lambda x:x[0]) # 前半二つは四角形の上。xで並び替えると左右も分かる。 10 bottom = sorted(points[2:], key=lambda x:x[0], reverse=True) # 後半二つは四角形の下。同じくxで並び替え。 11 points = np.array(top + bottom, dtype='float32') # 分離した二つを再結合。 12 13 width = max(np.sqrt(((points[0][0]-points[2][0])**2)*2), np.sqrt(((points[1][0]-points[3][0])**2)*2)) 14 height = max(np.sqrt(((points[0][1]-points[2][1])**2)*2), np.sqrt(((points[1][1]-points[3][1])**2)*2)) 15 16 dst = np.array([ 17 np.array([0, 0]), 18 np.array([width-1, 0]), 19 np.array([width-1, height-1]), 20 np.array([0, height-1]), 21 ], np.float32) 22 23 trans = cv2.getPerspectiveTransform(points, dst) # 変換前の座標と変換後の座標の対応を渡すと、透視変換行列を作ってくれる。 24 return cv2.warpPerspective(img, trans, (int(width), int(height))) # 透視変換行列を使って切り抜く。 25 26 27if __name__ == '__main__': 28 cam = cv2.VideoCapture(0) 29 30 while cv2.waitKey(10) == -1: 31 orig = cam.read()[1] 32 33 lines = orig.copy() 34 35 # 輪郭を抽出する 36 canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY) 37 canny = cv2.convertScaleAbs(orig) 38 canny = cv2.GaussianBlur(canny, (5, 5), 0) 39 canny = cv2.Canny(canny, 50, 100) 40 cv2.imshow('canny', canny) 41 42 cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1] # 抽出した輪郭に近似する直線(?)を探す。 43 cnts.sort(key=cv2.contourArea, reverse=True) # 面積が大きい順に並べ替える。 44 45 warp = None 46 for i, c in enumerate(cnts): 47 arclen = cv2.arcLength(c, True) 48 approx = cv2.approxPolyDP(c, 0.02*arclen, True) 49 50 level = 1 - float(i)/len(cnts) # 面積順に色を付けたかったのでこんなことをしている。 51 if len(approx) == 4: 52 cv2.drawContours(lines, [approx], -1, (0, 0, 255*level), 2) 53 if warp is None: 54 warp = approx.copy() # 一番面積の大きな四角形をwarpに保存。 55 else: 56 cv2.drawContours(lines, [approx], -1, (0, 255*level, 0), 2) 57 58 for pos in approx: 59 cv2.circle(lines, tuple(pos[0]), 4, (255*level, 0, 0)) 60 61 cv2.imshow('edge', lines) 62 63 if warp is not None: 64 warped = transform_by4(orig, warp[:,0,:]) # warpが存在した場合、そこだけくり抜いたものを作る。 65 cv2.imshow('warp', warped) 66 67 cam.release() 68 cv2.destroyAllWindows()
  • Python 3.6.2
  • opencv 3.3.0
  • Windows 10

投稿2017/12/06 16:56

編集2017/12/06 17:13
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vibrato

2017/12/06 17:25

おおぉ!エラー出ませんでした!!わざわざ修正して下ってありがとうございます!! 恥ずかしながら、全容を理解しないままいじっていたので、全要素0だのなんだのと的外れな質問をしていたようです;Cannyの話も忘れていただければと思います。 このコードやそれに準ずる疑問がまだあり、他にも質問を投稿させていただこうかと思っておりますので、今後見かけた際には、是非ともまた、ご教授のほどよろしくお願いいたします。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問