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

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

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

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

Python 3.x

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

Q&A

解決済

2回答

1255閲覧

python 三重ループの値が更新されない

H4shikaN

総合スコア1

OpenCV

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

Python 3.x

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

0グッド

1クリップ

投稿2021/07/23 08:08

実現したいこと・問題点

PythonでOpenCVを用いて画像からRGB値により特定の色を精度良く抽出したいです。
そのため、最も精度良く抽出できている最適なパラメータを取得するために、下限のパラメータを1ずつ増加させて画像を保存させています。

そのとき、ファイル名からパラメータがわかるよう画像を保存しているのですが、変数a,b,cがなぜか更新されません。
その結果、同じ画像名の画像が連続で出力され続けています。
しかし、フォルダを見ていると画像は少しずつ変化しているのでパラメータはおそらく更新できているはずです。

どなたか原因が分かる方教えていただけないでしょうか。

該当のソースコード

python3.8.5

1import os 2import cv2 3import shutil 4import glob 5import numpy as np 6from time import sleep 7from PIL import Image 8 9cwd = os.getcwd() 10 11#file name 12img_dir = "E:/b/" 13out = "output" 14 15#Lower param 16lb = 34 17lg = 3 18lr = 53 19 20#Upper param 21ub = 114 22ug = 75 23ur = 150 24 25#Threshold 26lower = 200 27upper = 1500 28 29def test(): 30 path = glob.glob(img_dir + "/*png") 31 outPath = img_dir + "/" + out 32 os.makedirs(outPath, exist_ok=True) 33 for aaa in range (55): 34 for bbb in range(36): 35 for ccc in range(48): 36 for i in path: 37 a = lb + aaa 38 b = lg + bbb 39 c = lr + ccc 40 name = os.path.basename(i) 41 image = cv2.imread(i) # ファイル読み込み 42 bgrLower = np.array([a, b, c]) # 抽出する色の下限 43 bgrUpper = np.array([ub, ug, ur]) # 抽出する色の上限 44 bgrResult = bgrExtraction(image, bgrLower, bgrUpper) 45 w,h,c = bgrResult.shape 46 47 count = 0 48 #全画素を探索してクロ以外の画素をカウント upper以上になったらストップ 49 for i in range(w): 50 for j in range(h): 51 imgdata = bgrResult[i,j] 52 b,g,r = imgdata 53 if b != 0 and g != 0 and r !=0: 54 count += 1 55 elif count == upper: 56 break 57 else: 58 continue 59 break 60 61 #lower以上 uppr以下 であれば画像を保存 62 if count < lower and count > upper: 63 continue 64 cv2.imwrite(os.path.join(outPath , str(a) + "." + str(b) + "." + str(c) + "-" + name ),bgrResult) 65 print(os.path.join(outPath , str(a) + "." + str(b) + "." + str(c) + "-" + name )) 66 67# BGRで特定の色を抽出する関数 68def bgrExtraction(image, bgrLower, bgrUpper): 69 img_mask = cv2.inRange(image, bgrLower, bgrUpper) # BGRからマスクを作成 70 result = cv2.bitwise_and(image, image, mask=img_mask) # 元画像とマスクを合成 71 return result 72 73if __name__ == '__main__': 74 test()

試したこと

下から二行目のところで計算式を入れていたのがいけないのかと思い、変数に代入してからファイル名に入力:結果は変わらず
ファイル名に連番を追加:画像は別々に保存できるが肝心のパラメータがわからないため失敗

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

コードを見た上での見解

少なくともb,cに関して言えば、ループ内の処理で上書きが起こりうるコードになっています。

質問上に書かれているコードから抜粋して、コメントとして状況を説明しています。

python

1for i in path: 2 a = lb + aaa 3 b = lg + bbb 4 c = lr + ccc 5 # (略) 6 w,h,c = bgrResult.shape # <- ここで、cを上書きしている 7 8 count = 0 9 for i in range(w): 10 for j in range(h): 11 imgdata = bgrResult[i,j] 12 b,g,r = imgdata # <- このブロックに入ると、bを上書きする

aが更新されない可能性はこのコードからは読み取れませんでしたが、
bbb,cccまでのループ内での処理時点でb,cに変化がないことに気づいて処理をやめているだけで、
最後までループさせ続けるとaは変化している可能性があります。
(bbb,cccのループだけで1728周あることから、自分なら事象に気づいた時点で止めるかなと想像しています)

どうするべきか

  • それぞれに意味の通りやすい変数にする
  • 変数にする必要のない箇所を変数にしない

それぞれに意味の通りやすい変数にする

一例ですが、a = lb + aaaのような書き方だと「aは何か?」「aaaは何か?」がわかりにくくなります。
変数には役割があるはずなので、役割に応じた命名を適切にすることで、
「違う役割の変数には違う役割が割り当てられる」ため、重複が起きにくくなります。

python

1for plus_b in range(36): # 加算用の数値であることがわかるように、仮でplus_という接頭辞にする 2 # (略) 3 cur_lb = lb + plus_b #「ループ内の現在のlowerなbをlbとループ時に使うbの補正値」

変数にする必要のない箇所を変数にしない

for i in pathのループ内の最小に定義しているa,b,cは下限値用のbgrLowerのためだけに使っているように見えます。
であれば、わざわざ一度変数にするのではなく、直接bgrLowerを用意してしまったほうがわかりやすいケースがあります。

diff

1for i in path: 2- a = lb + aaa 3- b = lg + bbb 4- c = lr + ccc 5 name = os.path.basename(i) 6 image = cv2.imread(i) # ファイル読み込み 7- bgrLower = np.array([a, b, c]) # 抽出する色の下限 8+ bgrLower = np.array([lb + aaa, lg + bbb, lr + ccc])

投稿2021/07/23 10:04

attakei

総合スコア2738

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

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

H4shikaN

2021/07/24 03:28

うまく処理が回りました! ありがとうございます!! 自分の中で誰かに渡すプログラムでもないから、変数名を適当に決めてしまっていたのですが、こういった重複に気づけなかったりといいことがないのでこれからはきちんと役割に応じた変数名をつけるようにしていきます。 ご回答いただきありがとうございました????
guest

0

ループで上書きが起こっています

python

1a = lb + aaa 2b = lg + bbb #bに代入 3c = lr + ccc #cに代入

ここで定義をしていますが、

python

1w,h,c = bgrResult.shape #cを上書きしている

や、

python

1b,g,r = imgdata #bを上書きしている

で上書きをしています。
変数名の重複を防ぐため、変数名を変えてみてはどうでしょうか。

投稿2021/07/23 22:35

編集2021/07/23 22:44
beatbox4108

総合スコア48

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問