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

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

ただいまの
回答率

91.36%

  • Python 3.x

    2438questions

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

  • OpenCV

    627questions

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

Python OpneCV 輪郭抽出について

解決済

回答 1

投稿 2017/12/07 00:16 ・編集 2017/12/07 00:59

  • 評価
  • クリップ 0
  • VIEW 70

vibrato

score 12

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

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

    # 一部抜粋
    while True:
        orig = cam.read()[1]

        lines = orig.copy()

        # 輪郭を抽出する
        canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
        canny = cv2.GaussianBlur(canny, (5, 5), 0)
        canny = cv2.Canny(canny, 50, 100) # 輪郭を抽出
        cv2.imshow('canny', canny)

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


下記は上記のうちの二行

        # ここまでは各要素にそれらしい値が入っている
        canny = cv2.GaussianBlur(canny, (5, 5), 0)
        # ここで全要素が「0」になる
        canny = cv2.Canny(canny, 50, 100)


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

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

追記

エラー箇所( line 52 )

    while True:
        orig = cam.read()[1]

        lines = orig.copy()

        # 輪郭を抽出する
        canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
        canny = cv2.GaussianBlur(canny, (5, 5), 0)
        canny = cv2.Canny(canny, 50, 100) # 輪郭を抽出
        cv2.imshow('canny', canny)

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

        cnts.sort()

        warp = None
51      for i, c in enumerate(cnts):
52          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カメラのキャプチャからイメージを取得してます。
今回キャプチャしたものは自身の顔含むプライベートな画像(映像)であるため、大変申し訳ないですが、こちらに張り付けることはしないつもりです。
ただそのような画像(映像)を使った上でのエラーであると認識していただければ幸いです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • LouiS0616

    2017/12/07 00:28

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

    キャンセル

  • vibrato

    2017/12/07 01:00

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

    キャンセル

回答 1

checkベストアンサー

0

エラーの原因

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

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

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

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

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

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

動いたコード

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

import cv2
import numpy as np


def transform_by4(img, points):
    """ 4点を指定してトリミングする。 """

    points = sorted(points, key=lambda x:x[1])  # yが小さいもの順に並び替え。
    top = sorted(points[:2], key=lambda x:x[0])  # 前半二つは四角形の上。xで並び替えると左右も分かる。
    bottom = sorted(points[2:], key=lambda x:x[0], reverse=True)  # 後半二つは四角形の下。同じくxで並び替え。
    points = np.array(top + bottom, dtype='float32')  # 分離した二つを再結合。

    width = max(np.sqrt(((points[0][0]-points[2][0])**2)*2), np.sqrt(((points[1][0]-points[3][0])**2)*2))
    height = max(np.sqrt(((points[0][1]-points[2][1])**2)*2), np.sqrt(((points[1][1]-points[3][1])**2)*2))

    dst = np.array([
            np.array([0, 0]),
            np.array([width-1, 0]),
            np.array([width-1, height-1]),
            np.array([0, height-1]),
            ], np.float32)

    trans = cv2.getPerspectiveTransform(points, dst)  # 変換前の座標と変換後の座標の対応を渡すと、透視変換行列を作ってくれる。
    return cv2.warpPerspective(img, trans, (int(width), int(height)))  # 透視変換行列を使って切り抜く。


if __name__ == '__main__':
    cam = cv2.VideoCapture(0)

    while cv2.waitKey(10) == -1:
        orig = cam.read()[1]

        lines = orig.copy()

        # 輪郭を抽出する
        canny = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
        canny = cv2.convertScaleAbs(orig)
        canny = cv2.GaussianBlur(canny, (5, 5), 0)
        canny = cv2.Canny(canny, 50, 100)
        cv2.imshow('canny', canny)

        cnts = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[1]  # 抽出した輪郭に近似する直線(?)を探す。
        cnts.sort(key=cv2.contourArea, reverse=True)  # 面積が大きい順に並べ替える。

        warp = None
        for i, c in enumerate(cnts):
            arclen = cv2.arcLength(c, True)
            approx = cv2.approxPolyDP(c, 0.02*arclen, True)

            level = 1 - float(i)/len(cnts)  # 面積順に色を付けたかったのでこんなことをしている。
            if len(approx) == 4:
                cv2.drawContours(lines, [approx], -1, (0, 0, 255*level), 2)
                if warp is None:
                    warp = approx.copy()  # 一番面積の大きな四角形をwarpに保存。
            else:
                cv2.drawContours(lines, [approx], -1, (0, 255*level, 0), 2)

            for pos in approx:
                cv2.circle(lines, tuple(pos[0]), 4, (255*level, 0, 0))

        cv2.imshow('edge', lines)

        if warp is not None:
            warped = transform_by4(orig, warp[:,0,:])  # warpが存在した場合、そこだけくり抜いたものを作る。
            cv2.imshow('warp', warped)

    cam.release()
    cv2.destroyAllWindows()
  • Python 3.6.2
  • opencv 3.3.0
  • Windows 10

投稿 2017/12/07 01:56

編集 2017/12/07 02:13

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/07 02:25

    おおぉ!エラー出ませんでした!!わざわざ修正して下ってありがとうございます!!
    恥ずかしながら、全容を理解しないままいじっていたので、全要素0だのなんだのと的外れな質問をしていたようです;Cannyの話も忘れていただければと思います。

    このコードやそれに準ずる疑問がまだあり、他にも質問を投稿させていただこうかと思っておりますので、今後見かけた際には、是非ともまた、ご教授のほどよろしくお願いいたします。
    ありがとうございました!

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

  • 解決済

    wxPythonにおいて、USBカメラの画像表示をしたい

    前提・実現したいこと ここ一週間くらい、teratailの皆様の力を借りながら、python上で動く動画や画像を表示できるGUIを作っています。画像は何とか表示でき、画像とパネル

  • 解決済

    opencv 円検出

    前提・実現したいこと 動画を読み込みその動画から円を検出して描画するプログラムを書こうと思っています。 発生している問題・エラーメッセージ 動画は読み込んで出力することができま

  • 解決済

    opencv 色 円 検出

    前提・実現したいこと 以前にした質問1 以前にした質問2 を使って円検出の精度を上げたいと思っています。 発生している問題 知識不足で申し訳ないですがどう組み合わせればいいかわ

  • 解決済

    opencv python 画像処理

    # -*- coding: utf-8 -*- import cv2 import numpy as np # フレーム差分の計算 def frame_sub(src1, src

  • 解決済

    openCVを用いた画像出力ができません。

    困っていること 素人質問です。 Anaconda Navigator経由でopenCVをインストール後、openCVで画像の出力を行う際にエラーが出てきてしまいます。 エラーの文言

  • 解決済

    PythonとOpenCVを用いて物体を白色で抽出したい

    前提・実現したいこと 最近、趣味でプログラミングを始めました。 PythonとOpenCVを用いて何も映っていない背景と物体を映した前景で差分をとり、物体だけを白色で抽出したいです

  • 解決済

    OpenCVを使った笑顔検出での問題

    前提・実現したいこと OpenCVで元からあるサンプルコード「smiledetect.cpp」を用いて笑顔検出のシステムを作っています。 検出機能を実装中に以下の問題が発生しました

  • 解決済

    ヒストグラムでの画像比較

    前提・実現したいこと ヒストグラムによる画像処理をしたいです。 発生している問題・エラーメッセージ いくつかの画像で試したのですが、出力されるdの値が1.0のまま動きません

同じタグがついた質問を見る

  • Python 3.x

    2438questions

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

  • OpenCV

    627questions

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