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

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

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

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

Python

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

Q&A

解決済

2回答

2902閲覧

opencvによる検出物の細かい座標の表示

edmonster

総合スコア7

OpenCV

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

Python

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

0グッド

0クリップ

投稿2020/01/03 04:58

編集2020/01/05 16:07

イメージ説明

前提・実現したいこと

つけた輪郭の細かい座標の表示

画像にあるいくつかの白い点の座標を表示したいのですが、かなり決め細かく表示したいです。画像の拡大を試みたのですが、100倍にしてみたのですが、処理したい画像が万とあるのでかなり時間がかかってしまいます。調べてもなかなか良さそうのが出なかったのですが、何かいい方法ありますか。

発生している問題・エラーメッセージ

特になし

該当のソースコード

python

1import cv2 2import matplotlib.pyplot as plt 3import numpy as np 4 5# 画像を読み込んでリサイズ、グレースケール画像に 6img = cv2.imread("./20130707.png") 7img=img[100:785,80:765] 8gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 9threshold=180 10ret,img_thresh=cv2.threshold(gray,threshold,255,cv2.THRESH_BINARY) 11 12#白い点を検出 13# 輪郭を抽出 14contours1, hierarchy = cv2.findContours(img_thresh, cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 15#img=cv2.imread("./20130711.png",0) 16#img=img[100:785,80:765] 17#各輪郭に対する処理 18detect_count=0 19for i in range(0,len(contours1)): 20 21 area=cv2.contourArea(contours1[i]) 22 if area<50.0 or 2000.0<area: 23 continue 24 print('contour:{},area:{}'.format(detect_count,area)) 25 26#矩形をつける 27 if len(contours1[i])>0: 28 rect=contours1[i] 29 x,y,w,h=cv2.boundingRect(rect) 30 cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) 31 cv2.putText(img, "Num:"+str(detect_count),(x,y+h+15), cv2.FONT_HERSHEY_PLAIN, 0.8, (0,255,0),1) 32 33 center_x=x+((w-x)/2) 34 center_y=y+((h-y)/2) 35 print('center of X:{},center of Y:{}'.format(center_x,center_y)) 36 37 38 detect_count+=1 39cv2.imshow("aa",img) 40cv2.waitKey() 41cv2.destroyAllWindows() 42 43 44

試したこと

画像の拡大、cv2.boundingRectによる検出物の中心座標表示

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/01/03 08:50

> かなり決め細かく表示したいです これは1:「1ピクセルも漏れなく拾いたい」なのか、2:「きめ細かく条件を指定してある程度選別したい」なのか、3:「通常の統計処理だけではなく、近隣ピクセルの状況も加味して本当にそれらしいもののみを拾いたい」なのかどれになるのでしょうか? 1であればnumpyでよい話ですし、2であればOpenCVでの選別処理がいると思います。3であればScikit-learnなどの機械学習が必要かもしれませんし、状況次第では1-3を合わせたうえでさらに深層学習でセグメンテーションが必要になるかもしれません。 ズバリそのもののイメージでなくてもよいので、こんな入力に対してこんな出力をしたい、という画像か模式図があると良いと思います。
edmonster

2020/01/05 14:25

返信ありがとうございます。僕が行いたいのは、検出した物体のピクセルの座標を細かく出したいです。1ピクセルが最細なので画像を拡大する以外に細かくする方法はないですよね。
退会済みユーザー

退会済みユーザー

2020/01/05 14:32

ご連絡ありがとうございます。 Q.1 何かサンプルの画像をアップロードしていただくことは可能でしょうか? Q.2 「1ピクセルが最細なので画像を拡大する以外に細かくする方法はない」これは、既にある画像の輪郭を拡大したときにシャープに維持したい、か、拡大しなくても(例えば)1ピクセル単位で抽出できればそれでよい、かどちらでしょうか?
edmonster

2020/01/05 16:19

アップロードしました。 Q2、1ピクセルよりも小さな値を表示させたいです。画像にあるいくつかの白い点が画像のどの位置にあるか出したいです。今は1ピクセルごとに座標を出せていますが、できたら1ピクセルよりも小さい値を出したいのです。ですが、そもそも画像の最小単位がピクセルなのでこれ以上細かい値を出すことができないってことをさっき知ったのでどうしようもないですよね。って感じです。
退会済みユーザー

退会済みユーザー

2020/01/06 13:46

edmonsterさんの意図ははわかりませんが、愚直に「白いピクセルの座標を一ピクセル単位で表示したい」と解釈して回答しました(どう使うかはともかく、自在に調整できる閾値に基づく白いピクセルは根こそぎ列挙して表示させるコードはできました)。 が、本当にやりたいことは「白いピクセルのまとまりを一纏まりとして、その上で『中心(重心?)』座標を一ピクセル単位で表示したい。」ということでしょうか? でしたらfanaさんの指摘の通り、私のやり方は好ましくありませんし、別の解を考えますので、もし必要でしたら解決済を解除してください。
fana

2020/01/07 04:52

> 1ピクセルごと という記述が,やりたいことが何なのかをわからなくしている感ですね. この表現だとたしかに「全ての白い画素を列挙する」が目的だとも読める.
guest

回答2

0

目的に対して,画像を拡大しようとする意図がわかりません.

仮に,「白い点」のサイズが本当に1画素なのであれば,それを拡大しても新たな情報が得られることはありません.
相応の面積を有するのであれば,そこに含まれる画素群の座標と輝度あたりを参照して最終的な「白い点の座標」を決めるしかないでしょう.
例えば,画素の輝度値に基づく重みを用いた画素座標の加重平均等がすぐに思いつく方法でしょう.
もしも「各点の形状は丸いハズ」みたいな前提知識があるならば,相応の形状を表現する関数を当てはめればよいでしょう.

投稿2020/01/06 01:16

fana

総合スコア11660

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

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

fana

2020/01/06 08:04 編集

話がわかりやすいように,【サイズがちょうど1画素のサイズに等しい「白い点」】を撮影した場合を考えてみると…… 撮影対象たる白い点が映る位置が,ある画素位置にちょうどぴったり!であったときに,その画素の画素値が例えば200(それなりに「白い」値)になるとしましょう. 背景の輝度値が128だとすれば,画素値の並びは [128]...[128][200][128]...[128]みたいに,その画素だけが「白く」なります. このときには,結果の「白い点の座標」とは,その白くなった画素の座標になるでしょう. 対して,白い点の映る位置が上記の「ぴったりな位置」から0.314画素ほどずれていたとしたらどうでしょうか. この場合,画素値の並びは,[128]...[128][170][142][128]...[128] のようになるかもしれません. この像から得たい結果の「白い点の座標」とは,一体いくつなのでしょう? 私は,このような場合に [170][142] という輝度値の並びからどうにかして0.314という値を推定したい,というのが本件の内容なのだと思ったのですが,いきなり何も考えずに2値化するような話で解決とされているから全然違う話っぽい…?
fana

2020/01/06 08:07

解決前であれば追記修正依頼あたりで問うような内容だったと思うけれども,すでに解決されている&回答時に想定した内容と質問者がやりたかったことが違うっぽい(?)雰囲気なので,「この回答をどういう話だと思って書いたのか」ということを念のため記した.
edmonster

2020/01/06 16:58

できたら0.314画素ずれている部分を算出したいと考えておりました。 1画素より小さい値を出す方法として、サブピクセルの方法以外にあるとしたら教えてほしいです。
fana

2020/01/07 04:28

> サブピクセルの方法 なる語が何を指しているのかわかりませんが, サブピクセルな値を求める方法に関する回答を行っているつもりです. 例えば輝度値に基づく加重平均で座標を決めるならば,[170][142] という並びに対して「この2画素のちょうど真ん中の位置(2値化してAABBとかだとこうなる)」とかではなく,より左側に寄った結果値が得られるはずです.(0.314という「真値」を得ることはできないにしても)
fana

2020/01/07 04:31

わざわざ明言する必要はない気もしますが, > 輝度値に基づく加重平均 という話は,撮影対象たる白い何かの色が一様に白いことを仮定しています. (当たり前ですが,撮影対象が相応のテクスチャを有するとかだとダメ)
fana

2020/01/07 04:40 編集

> 当てはめ は,輪郭形状を表す関数を領域の輪郭画素群の座標に対して当てはめる処理かもしれませんし,輝度分布を表現する関数を領域の全画素の輝度値に対して当てはめる処理かもしれません. 撮影対象がどのような像(輝度)になるのかという前提知識や,面積を有する領域に関してどの位置を「白い点の座標」としたいのか?という処理の目的次第でやることは変わるでしょう. 画像を100倍に拡大することが本当にあなたのやろうとしていることに対して【理屈の上で】意義があることなのか?というのを考えてみた方が良いのではないでしょうか.(処理速度も問題になっているようですし)
guest

0

ベストアンサー

1ピクセルよりも小さな値を表示させたいです。画像にあるいくつかの白い点が画像のどの位置にあるか出したいです。。

今すぐできる方法は以下の方法になります。

閾値点数座標
1801755[(110, 343), (110, 344), (111, 342),...
1702572[(110, 343), (110, 344), (111, 342),...
1604256[(110, 343), (110, 344), (110, 347),...

上からthreshold=180,170,160
threshold別

カメラに映る1ピクセルより細かい値は、画素の白さに反映されるはずですので、thresholdの値を調整することで取り漏らしは減らせます。

Python3

1import cv2 2import matplotlib.pyplot as plt 3import numpy as np 4 5# 画像を読み込んでリサイズ、グレースケール画像に 6img = cv2.imread("./20130707.png") 7img=img[100:785,80:765] 8gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 9 10 11# 180の場合 12####################################### 13threshold=180 14ret,img_thresh=cv2.threshold(gray,threshold,255,cv2.THRESH_BINARY) 15# cv2.imshow("img_thresh",img_thresh) 16ans = list(zip(*np.where(img_thresh==255))) 17print("Thresh=%s"%(threshold)) 18print("LEN=%s"%(len(ans))) 19print(ans) 20# img_debug = img_thresh 21 22# 170の場合 23####################################### 24threshold=170 25ret,img_thresh=cv2.threshold(gray,threshold,255,cv2.THRESH_BINARY) 26# cv2.imshow("img_thresh",img_thresh) 27ans = list(zip(*np.where(img_thresh==255))) 28print("Thresh=%s"%(threshold)) 29print("LEN=%s"%(len(ans))) 30print(ans) 31# img_debug = np.vstack((img_debug,img_thresh)) 32 33# 160の場合 34####################################### 35threshold=160 36ret,img_thresh=cv2.threshold(gray,threshold,255,cv2.THRESH_BINARY) 37# cv2.imshow("img_thresh",img_thresh) 38ans = list(zip(*np.where(img_thresh==255))) 39print("Thresh=%s"%(threshold)) 40print("LEN=%s"%(len(ans))) 41print(ans) 42# img_debug = np.vstack((img_debug,img_thresh)) 43 44# cv2.imshow("img_debug",img_debug) 45# cv2.imwrite("./img_debug.png",img_debug) 46 47 48###白い点を検出 49### 輪郭を抽出 50##contours1, hierarchy = cv2.findContours(img_thresh, cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 51## 52###img=cv2.imread("./20130711.png",0) 53###img=img[100:785,80:765] 54###各輪郭に対する処理 55##detect_count=0 56##for i in range(0,len(contours1)): 57## 58## area=cv2.contourArea(contours1[i]) 59## if area<50.0 or 2000.0<area: 60## continue 61## print('contour:{},area:{}'.format(detect_count,area)) 62## 63## #矩形をつける 64## if len(contours1[i])>0: 65## rect=contours1[i] 66## x,y,w,h=cv2.boundingRect(rect) 67## cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) 68## cv2.putText(img, "Num:"+str(detect_count),(x,y+h+15), cv2.FONT_HERSHEY_PLAIN, 0.8, (0,255,0),1) 69## 70## center_x=x+((w-x)/2) 71## center_y=y+((h-y)/2) 72## print('center of X:{},center of Y:{}'.format(center_x,center_y)) 73## 74## 75## detect_count+=1 76##cv2.imshow("aa",img) 77cv2.waitKey(0) 78cv2.destroyAllWindows() 79

今は1ピクセルごとに座標を出せていますが、できたら1ピクセルよりも小さい値を出したいのです

OpenCVのresizeにcv2.INTER_LANCZOS4がありますので、これを使うといくらか滑らかに画像を拡大できます。(計算量を減らすために生画像をグレースケールにした後に)これで拡大して同じ処理をすれば、"サブピクセル"に相当する処理ができるはずです。

もっと滑らかに拡大したいのであれば、waifu2x(深層学習を使った滑らかな拡大)を使って拡大することが候補に挙がります。

※いずれにせよ、拡大方法を変えてサブピクセルに相当する処理をするだけで、実際にサブピクセルまで処理をする方法ではありません。

参考)
少なくとも私はOpenCVでのサブピクセルはコーナー検出では聞いたことがありますが、画素値の判定については聞いたことがありません。

投稿2020/01/05 21:59

編集2020/01/05 22:01
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

edmonster

2020/01/06 06:13

回答ありがとうございます。閾値でだいぶ結果が変わりそうですね。 OpenCVのresizeのcv2.INTER_LANCZOS4かなり使えそうです。やってみます。
fana

2020/01/06 06:22

画像を拡大すればサブピクセル相当になるという話の意味(意義,かな?)がわからないので低評価. (何らかの補足説明等が行われてその意味が理解できた場合には取り消します) 拡大してboundingRectの中心を求めたところで何も変わらないように思えます. 例えば,図形を3倍に拡大した世界でAABBの中心を求めてその座標値を1/3にしたら,等倍の世界だけで処理した場合と比較して何かいいことがあるのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問