🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2432閲覧

pythonによるマス目認識とマス目の座標を扱ったプログラム構築

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/01/07 05:35

編集2020/01/09 10:07

質問は
1、資料の最外輪郭内のみでマス目の輪郭抽出を行う
2、番号を振った各マス目内に「点」があれば、そのマス目のカウントを+1する
方法です。
座標を扱ったプログラムの構築の見当がつかず途方に暮れています。

拙い文章で申し訳ございませんが、よろしくお願いたします。

python

1import cv2 2import numpy as np! 3 4img = cv2.imread('video/frame_109.png') 5 6# BGR -> グレースケール 7gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8# エッジ抽出 (Canny) 9edges = cv2.Canny(gray, 18, 45, apertureSize=3) 10cv2.imwrite('images/aaa/edges.png', edges) 11# 膨張処理 12kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4)) 13edges = cv2.dilate(edges, kernel) 14cv2.imwrite('images/aaa/edges2.png', edges) 15 16 17# 輪郭抽出 18contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 19cv2.imwrite('images/aaa/hierarchy.png', hierarchy) 20# 面積でフィルタリング 21rects = [] 22for cnt, hrchy in zip(contours, hierarchy[0]): 23 if cv2.contourArea(cnt) < 3000: 24 continue # 面積が小さいものは除く 25 if cv2.contourArea(cnt) > 15000: 26 continue 27 if hrchy[3] == -1: 28 continue # ルートノードは除く 29 # 輪郭を囲む長方形を計算する。 30 rect = cv2.minAreaRect(cnt) 31 rect_points = cv2.boxPoints(rect).astype(int) 32 rects.append(rect_points) 33 34# x-y 順でソート 35rects = sorted(rects, key=lambda x: (x[0][1], x[0][0])) 36 37# 描画する。 38for i, rect in enumerate(rects): 39 color = np.random.randint(0, 255, 3).tolist() 40 cv2.drawContours(img, rects, i, color, 2) 41 cv2.putText(img, str(i), tuple(rect[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 3) 42 43 print('rect:\n', rect) 44 45cv2.imwrite('images/aaa/frame_109.png', img)

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

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

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

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

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

fana

2020/01/07 06:17 編集

想定する(サポートする)撮影状況について書いた方が良いように思います. 例えば,提示されている画像で言えば, * 3x5のマス全体が映っていない * 撮影対象をどこかに設置するのではなくて手で持っている * マスは若干傾いている * 撮影対象は平面でなくふにゃふにゃしている …等,その具合がどの程度まで厳しくなるのか?次第で処理も厳しくなりそうな要素が見られます. あと,「点」の意味がわからない.
退会済みユーザー

退会済みユーザー

2020/01/07 06:38

アドバイスありがとうございます。 質問文の不足申し訳ございませんでした。 「点」は資料を読む人の視線の位置で、青い点で動画上に表示されます。 撮影状況は、資料を読む人の頭に小型カメラを装着してもらい撮影しています。(動画はすでに撮影しています) 被験者には基本的にボードに挟んだ資料を真っ直ぐ見てもらうように伝えていますが、手で持ちながらのため、 資料をめくる際に資料がふにゃふにゃになったり、 資料が傾いたり、 資料の端が動画の外にでたり、 また、照明の関係で資料に影ができたり しています。 プログラムで完璧に処理できなくてもいいので、できるだけ高い精度でマス目に入った「点」を自動でカウントできるようにしたいと考えています。 そのため、追加でプログラムで処理できなかった画像フレームを表示するようにし、その画像フレームはプログラムの処理後に自分で確認しようと考えています。 よろしくお願いいたします。
guest

回答1

0

ベストアンサー

1、資料の最外輪郭内のみでマス目の輪郭抽出を行う

いきなりこの話と違ってしまいますが…
もしも,【資料の余白には十分な広さがあって,資料を手で持った場合にも手の像とマス目との間には十分な幅の余白が残る】ことを前提とできるのであれば,輪郭抽出を資料内のみに限定せずとも良いかもしれません.

マス目の他に,(面積とか形状では棄却できなかった)背景領域のその他の領域がまれに残ってしまう,という程度であれば,領域の隣接関係等から「隣のマス目」を判断して,最終的にマス目の集合となるものを残せば良いように思います.

各領域のデータとして{面積,傾き角,長辺の長さ,短辺の長さ}くらいを考えることができるでしょうから,
ある領域に着目してこれがマスの1つだとするとき,その周辺のマス目のあるべき位置や傾き角や面積等が「このくらいであるはず」という仮定をできるでしょう.
例えば,領域群を適当な比率(1.1倍とか?)で拡大した際に着目領域と重複する領域群に関して,それが隣のマス目っぽいかどうかを調べていく感じでグループ化していくような処理を行えばどうでしょうか.
背景の領域群からも相応の処理結果が生成されるでしょうけども,本当のマス目群によって構成される結果と比較すると「それっぽくない」結果になると期待できるでしょうから,最終的に本来のマス目群のグループを選択できるのではないかと思います.
(やること的に,正解グループの範囲は画像の中央付近を含むんじゃないか?みたいな話とかも利用できるかも?)


2、番号を振った各マス目内に「点」があれば、そのマス目のカウントを+1する

「点」の座標が与えられれば,そのフレームにおいてはどの領域に入っているかはどうとでも判定できるでしょうが,
動画を処理するのであれば,「さっきのフレームでのあるマス目が,今のフレームではどの領域なのか?」ということが判断できていないとなりません.
マスが画像範囲から見切れることもあり得るようですから,各フレームだけでは各マス目が3x5のうちのどれなのかが判断できない場合もあるはずですし,フレーム間でマス目を追跡する形の処理が必要そうに思えます.
隣接フレーム間で画像の具合が大きく動かないと仮定すれば,「さっきのフレームと今のフレームとで「近い」やつが同じマス目」みたいな.
(さっきまでいたマス目が見えなくなったり,あるいは新規に見えるようになったりとかがあり得るから,相応に頑張った処理が必要かも… 「3x5のマスの塊」を追跡していくような形になるか…?)

投稿2020/01/07 07:01

編集2020/01/07 07:10
fana

総合スコア11990

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

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

fana

2020/01/07 07:24 編集

「最初のフレームでは必ず3x5の全マスが見えている」みたいな条件とかがあれば楽なんだろうけども, 途中で「資料をめくる」という動作もあるみたいだし…
fana

2020/01/07 07:31 編集

3x5個の「「点」が入った回数カウンタ」が存在するとき,あるフレームにおいてあるマス目と思しき領域に「点」が入った際に,この15個のカウンタのどれに+1すればいいのか? →各フレームにおいて各領域が3x5個のマス目のうちのどれなのか?という判断が必要. →領域を個別に時間方向に追跡しつつ,その領域がどのマスっぽいか?という推定値(例えば15個のbinのヒストグラムみたいな)を更新していく感じでどうか.(提示されている画像で言えば,各領域は2つのbinの値を増やすことになるだろう) 各フレームにおいて,各マス目領域が3x5のうちのどのマスなのか?は,領域群の現在の「ぽさ推定値」を最も満たすように決める,とか.
退会済みユーザー

退会済みユーザー

2020/01/08 13:25

fana様 ありがとうございます。 資料をめくる動作が入ると難しくなりそうなので、資料の各ページごとに動画を分割しようとおもいます。(各ページを見ている時間が長いため) 恥ずかしながらアドバイス頂いたことに対しての知識が薄いため、調べながら解決していこうと思います。
fana

2020/01/09 01:35 編集

まぁ,「こんな雰囲気?」程度の話しかできていませんし… 実際に何が目の前の問題であるのかがあまり明確になっていない段階にあるように思います. (時間とか労力とかの)背景事情的に可能であるならば, 最初は問題を簡単化したものに取り組んでみる段階を設けても良いのではないかと思います. 例えば,「各フレームでは必ず3x5の全てのマスが完全に写っている」みたいな条件であればできるのか?とか. (この条件の場合だと,2側の処理はある程度簡単になるでしょうから,1側の解決にまずは注力できるでしょう)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問