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

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

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

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

Python

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

Q&A

2回答

2522閲覧

python 座標値をiou値に変換し比較する

izm2192

総合スコア12

YOLO

YOLOとは、画像検出および認識用ニューラルネットワークです。CベースのDarknetというフレームワークを用いて、画像や動画からオブジェクトを検出。リアルタイムでそれが何になるのかを認識し、分類することができます。

Python

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

0グッド

0クリップ

投稿2021/01/06 02:20

編集2021/01/07 15:33

前提・実現したいこと

下に記載するコードを合わせて各行のiou値を比較して一定範囲内なら同じID似直すというプログラムを作りたい

該当のソースコード

python

1import pandas as pd 2import csv 3 4def iou(a, b): 5 # a, bは矩形を表すリストで、a=[xmin, xmax, ymin, ymax] 6 ax_mn, ay_mn, ax_mx, ay_mx = a[2], a[3], a[4], a[5] 7 bx_mn, by_mn, bx_mx, by_mx = b[2], b[3], b[4], b[5] 8 9 a_area = (ax_mx - ax_mn + 1) * (ay_mx - ay_mn + 1) 10 b_area = (bx_mx - bx_mn + 1) * (by_mx - by_mn + 1) 11 12 abx_mn = max(ax_mn, bx_mn) 13 aby_mn = max(ay_mn, by_mn) 14 abx_mx = min(ax_mx, bx_mx) 15 aby_mx = min(ay_mx, by_mx) 16 w = max(0, abx_mx - abx_mn + 1) 17 h = max(0, aby_mx - aby_mn + 1) 18 intersect = w*h 19 20 iou = intersect / (a_area + b_area - intersect) 21 return iou 22 23def check_ID(IDs, data): 24 for k in IDs:#IDsから登録済みIDを一つずつ呼び出し 25 if iou(k, data) <= 0.8:#diffで差分の取得 26 return k[0] 27 return False 28 29 30IDs = list()#今までに出てきたIDをkey, それに付随する数値をvalueにして格納する 31with open('out1.csv', 'r', encoding='UTF-8') as f: 32 reader = csv.reader(f) 33 with open('inp.txt','w', encoding='UTF-8', newline="") as i: 34 writer = csv.writer(i) 35 for data in reader: 36 if "ID:" in data[0]:#一要素目がID番号なら 37 result = check_ID(IDs, data)#重複判定 38 if result: 39 #ヒットすれば、resultに IDが入っているので、dataを書き換える 40 data[0] = result 41 else: 42 IDs.append(data) #IDsにまるごと登録 これをelseでなくてに出せば全部登録になります。 43 writer.writerow(data)#csv形式で書き込み

試したこと

上のプログラムは各業の座標値を比較して指定した範囲内なら同じID番号にするというプログラムです
下のプログラムはiou値の計算をするプログラムですこれらを合わせて各行のiou値を出しそれを決められた範囲内なら同じIDにするという感じにしたいです

補足情報(FW/ツールのバージョンなど)

iouの計算式はこのサイトから抜粋いたしました
https://aipy2020.hatenablog.com/entry/IoU

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

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

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

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

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

TakaiY

2021/01/06 08:04

iou値というのは、2つの行の値を比較することで得られるようですが、比較対象になるのはどの行ですか? もし全ての行が対象ということであれば、例えば10行あれば、45通り確認する必要があります。 aとbが範囲内だった場合、どちらのIDにしますか? aとbが範囲内、bとcが範囲内、でもaとcは範囲外となった場合、どのように扱いますか?
izm2192

2021/01/07 03:29

比較対象はID:と記述されている行になります。 上のプログラムだと一つ目のID:と書かれている場所に対して全てのIDと書かれている行を比較します、それが終わると次のIDとかからている行という感じになります aとbが範囲内だと最初に出てきたaになります。なのでbがaになる感じです その場合でもcはaになります いわば下のソースの計算を上のソースのdiff = [abs(int(v)-int(d)) for v, d in zip(IDs[k], data[2:])]#登録済みのIDと対象のIDの座標の差分をリストに格納(data[2:]はその要素以降の要素)(absで絶対値) の部分に代入してあげたらいけるのではないのかと思っています
TakaiY

2021/01/07 06:10

データの処理方式そのもののアルゴリズムをちゃんと考えないとできないと思いますね。 たとえば、 とあるデータの各行のデータを順にx, y, z として、xとz、yとzが範囲内だけど、xとyは範囲外だとします。 あなたの想定だとすべてxにならなければなりませんが、上から順に見ていく方式だと、 1. xとyを比較。範囲でない。 2. xとzを比較。 範囲なので、zはxになる。 3. yとz(xになってますが)を比較。、範囲なので、zはxになる。 ということで、x, y, yになってしまいます。 これでOKでしょうか? 、
izm2192

2021/01/07 13:41

ID:1,A,938,841,1062,958 ID:1,A,938,841,1062,958 ID:5,A,956,905,1094,991 ID:5,A,956,905,1094,992 このような場合だと全てID1になるという感じになっています ID:7,A,980,913,1151,1008 ID:7,A,982,914,1151,1007
TakaiY

2021/01/07 13:52

僕の質問あまり理解いただけていないようなので、もう一度だけ同じ質問をします。 以下のようなデータだとして、 1行目と3行目、2行目と3行目がそれぞれ範囲内で、1行目と2行目が範囲内でなかったとした場合、IDはどのようになる想定ですか? ID:1,A,938,841,1062,958 ID:5,A,982,914,1151,1007 ID:7,A,956,905,1094,991
izm2192

2021/01/07 14:04

上から逐次処理?でやっているのでまず1回目の処理でID7がID1になります。 2回めの処理でID5とID7(1)が同じなのでID7はID5になります なので質問のとおりだと ID1 ID5 ID5 になってしまいます しかし今回自分がやっている実験ではそのような範囲になることがほぼないので数値の範囲を広く設定しています 不十分な文章ですがすいません
TakaiY

2021/01/07 14:15

ということは、そういう処理でも問題ないってことですね?
izm2192

2021/01/07 14:21 編集

ですね! このソースの最終目的は上でいうとID1をまず格納しそれとその他の行をiou関数で計算していきrenumber関数のdiffの範囲以上ならIDを同じものに書き換えるという感じですね それが終わると次のIDとそれの下のIDを同じように処理するといった感じにしたいです
TakaiY

2021/01/07 14:29

同じ内容について別の質問を作るのはマナー違反だと思います。
izm2192

2021/01/07 14:33

すいません!もう一つの方は消しておきます! ありがとうございます ソースを今書いていたやつに更新察せていただきました 回答いただいたソースなのですがrenumber関数のdiffの場所にかけばいいのかなと思うのですがその場合どのようにしてiouの関数は呼び出せばいいですか?
izm2192

2021/01/07 14:52

回答ありがとうございます。 今書き直してやってみたのですが書き直し方が悪いのかうまく行きません。。。 上のコードに入れるとしたらどのような感じで入れればいいでしょうか 遅い時間に何度もすいません
TakaiY

2021/01/07 14:52

あ、 なんか、ソースの構造が変ってますね。 こちらで考えたアルゴリズムと違うので、僕の回答があてはまるところはありません。 アルゴリズムを見直したほうがいいように思いますよ。何をどこでどのように比較するのか。
izm2192

2021/01/07 14:55

はい。 なかなか難しいです。。
guest

回答2

0

★ ソースの構造が初期と変っているので、以下はあまり参考になりません。

扱うデータの容量があまりに多いとできなくなりますが、同じデータを何度も使って処理する必要があるので、ファイルの中身を一度すべて読み込んでそれを処理するのがいいと思います。

読み込んだデータはpandasのDataFrameにするのもいいでしょうし、リストのリストにしてもいいでしょう。
後は二重ループでぐるぐる回しながら処理すればそれほど難しくないでしょう。

コードのイメージはこんな感じでしょうか。
★ 修正版その1
dataに以下のようにデータが入っているとして

text

1[["ID:1","A",938,841,1062,958], 2 ["ID:1","A",938,841,1062,958]]

iou関数の呼び出しはこんな感じです。

python

1# dataに入力を全て読み込んでおく。 2for k in range(0, len(data): 3 for t in range(k+1, len(data): 4 # data[k] と data[t] を比較 5 result = iou(data[k], data[t]) 6 # 範囲内なら data[t]のIDを変更する

投稿2021/01/07 14:24

編集2021/01/07 14:53
TakaiY

総合スコア13790

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

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

0

アルゴリズムが変ったので別回答にします。

アルゴリズムは、チェック対象のデータと保存してあるデータを比較して範囲内にあるものがあれば、保存シエアルデータのIDで書き換える。というものですよね?

今のremenber関数は、距離の計算と、データの保存を一緒にやろうとしているので使いにくいです。
この2つば別の処理、というか、比較はすべにiou関数があるのでそれでやるべきでしょう。


追記です。

IDsは、dictでなくて、リストのリストでいいでしょう。
renumber(名前を変えちゃいましたが)でのデータの扱いなど、そのほうが使いやすいです。

renumber関数はチェックするだけの関数にしましょう。ここで何かを修正するのは使いにくいです。
IDsに含まれなければFalseを、含まれればIDを返すことにします。名前も替えたほうがいいかな。

python

1def check_ID(IDs, data): 2 for k in IDs:#IDsから登録済みIDを一つずつ呼び出し 3 if iou(k, data) <= 0.8:#diffで差分の取得 4 return k[0] 5 return False

呼ぶ側ははこれを使うことになるので、こんな感じでしょうか。

python

1 for data in reader: 2 if "ID:" in data[0]:#一要素目がID番号なら 3 result = check_ID(IDs, data)#重複判定 4 if result: 5 #ヒットすれば、resultに IDが入っているので、dataを書き換える 6 data[0] = result 7 else: 8 IDs.append(data) #IDsにまるごと登録 これをelseでなくてに出せば全部登録になります。 9 writer.writerow(data)#csv形式で書き込み

投稿2021/01/07 15:03

編集2021/01/07 15:28
TakaiY

総合スコア13790

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

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

izm2192

2021/01/07 15:09

少し近づけてみたんですがまだ正常に動きません。。 ソースを替えてみたので見ていただけると助かります
TakaiY

2021/01/07 15:30

みてみました。 修正案を提案します。 動かしていないので、バグってるかもですが。
izm2192

2021/01/07 15:32

まだ少しエラーが吐かれてしまってますね。。 言われた感じに改善してみました
TakaiY

2021/01/07 15:34

どんなエラーですか?
izm2192

2021/01/07 15:40

TypeError Traceback (most recent call last) <ipython-input-128-2e3dd0b68805> in <module> 35 for data in reader: 36 if "ID:" in data[0]:#一要素目がID番号なら ---> 37 result = check_ID(IDs, data)#重複判定 38 if result:#ヒットすれば、resultに IDが入っているので、dataを書き換える 39 data[0] = result <ipython-input-128-2e3dd0b68805> in check_ID(IDs, data) 23 def check_ID(IDs, data): 24 for k in IDs:#IDsから登録済みIDを一つずつ呼び出し ---> 25 if iou(k, data) <= 0.8:#diffで差分の取得 26 return k[0] 27 return False <ipython-input-128-2e3dd0b68805> in iou(a, b) 7 bx_mn, by_mn, bx_mx, by_mx = b[2], b[3], b[4], b[5] 8 ----> 9 a_area = (ax_mx - ax_mn + 1) * (ay_mx - ay_mn + 1) 10 b_area = (bx_mx - bx_mn + 1) * (by_mx - by_mn + 1) 11 TypeError: unsupported operand type(s) for -: 'str' and 'str' こんなかんじですね
TakaiY

2021/01/07 15:44 編集

csv.readerはすべてを文字列として扱うので、"928"などを数値に変換してやらないといけないってことですね。 どこで数値にするべきかについては、いろんな考えかたがあるのでお好きなところで。
izm2192

2021/01/07 15:50

重ね重ねすいません どのように記述すればいいですかね。 調べてみたんですがいまいちわからなくて
TakaiY

2021/01/07 15:51

「python 文字列 数値 変換」あたりで検索すれば、いろいろ出てきますよ。
izm2192

2021/01/07 15:56

intとかfloatとかでやってみたんですができないです。。
TakaiY

2021/01/07 16:07

数値でなければならないのに、文字列になってしまっているもの(変数とか)がどれなのか わかっていますか? a_area = (ax_mx - ax_mn + 1) * (ay_mx - ay_mn + 1) この式の右辺の変数全部です。 他にもありますよ。 で、これらを直接数値にするか、元のデータの値を数値にするか考えてみればよいかと。
izm2192

2021/01/07 16:14

a_area = (a[4] - a[2] + 1) * (a[5] - a[3] + 1) b_area = (b[4] - b[2] + 1) * (b[5] - b[3] + 1) こういうかんじってことですかね?
TakaiY

2021/01/08 09:13 編集

もう回答するのはやめます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問