質問するログイン新規登録
OpenCV

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

Python 3.x

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

Q&A

1回答

547閲覧

cv2.thresholdを一部改造した画像処理がしたい

20230201a

総合スコア0

OpenCV

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

Python 3.x

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

0グッド

0クリップ

投稿2023/02/01 13:16

0

0

実現したいこと

cv2.thresholdを一部改造した画像処理がしたい

前提

約3000*5000のグレー画像の画像処理で、cv2.adaptivethresholdを使ってきた。
しかし、"各座標で計算時の、カーネル内の全座標のうち、256階調値(0~255)が一定値(例…200)以下のみで平均をとる(一定値より上は外れ値として無視したい)"ように改造したい

発生している問題

(1) 下記参考に、”一定値”以下のみで平均”を追加し、pythonで実行⇒時間がかかりすぎる
https://algorithm.joho.info/programming/python/opencv-adaptive-thresholding-py/

(1)’ 下記参考に、cythonを使ったが、やはり時間がかかりすぎる
https://sites.google.com/site/yusukekikuchiwebsite/memo/cythonlooptest

(2) cで書けないか(ソースコードをgithubから調べて実行)⇒よくわからず
https://style.potepan.com/articles/33553.html

該当のソースコード

試したこと

(1)(後ほど追記)

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

windows10
visual studio code
python 3.7
cython 0.29

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

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

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

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

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

guest

回答1

0

下記参考に、”一定値”以下のみで平均”を追加し、pythonで実行⇒時間がかかりすぎる
Cythonでどうやったのかわかりませんが、少なくとも素のPythonでfor文のfor文は良くありません。
体感された通りものすごく遅くなります。

筋の良い方法は、「何とかしてNumpyArrayのまま捌く(for文は一度も使わない)」「C++などで書かれたライブラリをなるべくそのまま使う」です。

しかし、"各座標で計算時の、カーネル内の全座標のうち、256階調値(0~255)が一定値(例…200)以下のみで平均をとる(一定値より上は外れ値として無視したい)"ように改造したい

cv2.AdaptiveThresholdについての記事の引数Cが正に「一定値より上は外れ値として無視したい)」なようにも見えます。

トンチンカンな回答であった場合コメントください。回答を考えます。

投稿2023/02/02 04:48

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

20230201a

2023/02/02 10:56

早急なご回答ありがとうございます。 >少なくとも素のPythonでfor文のfor文は良くありません。 cythonでもfor文2個使っていました。 純粋に画像の縦y、横x方向を変数にして、です。 無理矢理でも1変数にしてfor1個の方が良いのでしょうか? (for i in range(0, 3000×5000) 。 背反は、平均取る四角の配列を作るときに、yとxをiという1つの変数に置き換えるか、ですかね? ) >「何とかしてNumpyArrayのまま捌く(for文は一度も使わない)」 これでできないか考えてみたのですが、上手いのを思いつけず。。 (np.array(画像))で、 i<220と要素を条件に入れられるものでしょうか? ※np.whereを使って、220以下とそれより上で分ける? https://www.sejuku.net/blog/73049 >Cが正に「一定値より上は外れ値として無視したい) 画像の元座標の値から、計算して平均を引いて、さらにCで引いた際に、0より上だったら、白に、そうでなかったらくろにする2値化が、元々のロジックです。 それだと、平均の計算の際、ハズレ値の真っ白部分が平均計算に含まれ、意図せず閾値が高くなる困りごとがありました。そこで、平均計算の時から、256階調値が高い座標は平均計算時に除外したい次第です。 わかりづらくて申し訳ございません。。
退会済みユーザー

退会済みユーザー

2023/02/03 06:51 編集

元になる画像(元の画像で差支えがある場合には同じことが検証できる偽画像)をアップロードできますか? 「本当の課題」があり、その一つの解法として「質問の課題」があるように思います。 もしかしたら質問に挙げている解法しかないのかもしれませんが、 もっとシンプルに別の解法で(藪に突っ込むことなく)「本当の課題」が解ける可能性もあります。 画像のアップロードを勧める理由は、 この可能性を探りたいのと、文字だけでは伝わりにくい何をしたいかを見えるようにするための2点です。 --- > 平均の計算の際、ハズレ値の真っ白部分が平均計算に含まれ、意図せず閾値が高くなる困りごとがありました。そこで、平均計算の時から、256階調値が高い座標は平均計算時に除外したい次第です。 乱暴なやり方かもしれませんが、 別解案1:マスク画像を適当に作る 1. cv2.AdaptiveThresholdの引数Cを「大体OKな感じ」で処理(外れ値部分に引っ張られて「白めな画像」になるはず。要引数Cの調整) 2. cv2.AdaptiveThresholdの引数Cを「大き目」で処理(外れ値部分が黒い側に引っ張られて「黒めな画像」になるはず。要引数Cの調整) 3. 白めな画像と黒めな画像から3値化マスクを生成。3値化画像の灰色部分をどっちに振るか調整して狙った二値化をする。(要三値化の灰色部分の扱いの調整) 別解案2:元画像のノイズっぽい部分を消す ・ ガウシアンフィルタなり平均化フィルタなりを適用(ノイズが薄くなるハズ) ・ cv2.AdaptiveThresholdを素直に適用 別解案3:明るいピクセルだけ抑える ・ cv2.LUTでガンマ補正テーブルを作成 ・ LUTに基づき明るいものほど暗くし、もともと暗いところはなるべくそのままにする ・ cv2.AdaptiveThresholdを素直に適用
20230201a

2023/02/07 14:37

返事が遅れて申し訳ありません。 >元になる画像(元の画像で差支えがある場合には同じことが検証できる偽画像)をアップロードできますか? 元画像ではなく恐縮ですが、下記の画像でご確認お願いします。(URL先はカラーですが、グレー済としてお考え下さい) https://publicdomainq.net/sunshine-sea-summer-0057404/ 本来は、日差し(白)が無く、波の部分をadaptivethresholdで模様を描けていた(波の中でもエッジが出せていた)(カーネルサイズはこの画像の縦1/10、横1/10程度でお考え下さい)。一方、日差しが入るため、日差し付近の、座標のカーネルでは、領域内に日差しの白があるため、adaptivethresholdで計算の際、カーネル内の256階調値の平均値が上がってしまい、波の部分でエッジが出にくく、黒画素が多めになってしまう。 >乱暴なやり方かもしれませんが、 様々なご提案ありがとうございます。 別解案1の、3値化マスクのイメージがわかず、、 >別解案2:元画像のノイズっぽい部分を消す URL先の画像のように、白っぽい面積は広めです(=ノイズのように小さい面積が沢山、ではない)。先にお伝えせず、申し訳ございませんでした。 >別解案3:明るいピクセルだけ抑える イメージですが、 https://pystyle.info/opencv-tone-transform/#outline__3 ページ下部の”ガンマ補正”内の表のピンク線、4でしょうか? (入力が高くても、出力を抑える)
退会済みユーザー

退会済みユーザー

2023/02/07 21:45 編集

画像連絡ありがとうございます。こちらでも時間を見て試します。 > 別解案1の、3値化マスクのイメージがわかず、 一般的な3値化の例:https://www.stjun.com/entry/2020/02/14/173428 ※方法はこれとは違い、AdapticeThresholdの結果で3値化しようというのを提案しました。 先のコメントでウダウダ書きましたが、やりたいことは 1. 設定を変えたAdapticeThresholdの結果を複数個用意 2. 複数個のAdapticeThresholdの結果をうまく組み合わせてセグメンテーションできないかな というだけの話です。 「特に凝ったことはせず、場当たり的に都合の良い条件を決定木のようにさぐれないかな」という考えを そのまま画像処理に持ち込んだだけです💦 > ページ下部の”ガンマ補正”内の表のピンク線、4でしょうか? そうなります。明るい部分を狙い撃ちして暗くしてしまえば、「白い部分に引っ張られて―」がいくらかましになるだろう、と思った次第です。こちらも場当たり的に都合の良い条件を洗い出す必要があるのは同じです💦
20230201a

2023/02/08 00:26

ご返信ありがとうございます。 >こちらでも時間を見て試します。 すみません、ありがとうございます。 >一般的な3値化の例:https://www.stjun.com/entry/2020/02/14/173428 >AdapticeThresholdの結果で3値化しようというのを提案しました。 >3. 白めな画像と黒めな画像から3値化マスクを生成。 >2. 複数個のAdapticeThresholdの結果をうまく組み合わせてセグメンテーションできないかなというだけの話です。 AdapticeThresholdでできるのは、白と黒だと認識しています。 3値化の灰は今回、どうつくるのでしょうか? (白めな画像と黒めな画像の差をとる? -255, 0, 255の3種?) >明るい部分を狙い撃ちして暗くしてしまえば、「白い部分に引っ張られて―」がいくらかましになるだろう、と思った次第です。 アドバイスありがとうございます。 確かに、厳密に指定した256階調値以上はカーネル内の平均計算時に無視する、が複雑な場合、 代用手法として、明るい部分を低くしてしまおう、も手だと思いました。 改めまして、ありがとうございました。
退会済みユーザー

退会済みユーザー

2023/02/08 03:01

>3値化の灰は今回、どうつくるのでしょうか? 2値化画像Aと2値化画像Bがあった時に、それぞれ違う閾値で処理したとすると、 ピクセルごとに以下の3種類の組み合わせができます。 A:0 B:0 A:0 B:255 A:255 B:255 (やっていないので厳密なことは言えませんが、恐らく「A:255 B:0」は発生しないはずです) あとはピクセル単位で、 A==0かつB==0ならば0 A==0かつB==255ならば128 A==255かつB==255ならば255 といった具合で処理できますね。 たとえば、 img_ans = np.zeros((255,255)) img_ans[ img_a == 0 & img_b == 0 ] = 0 img_ans[ img_a == 0 & img_b ==255 ] = 128 img_ans[ img_a ==255 & img_b ==255 ] = 255
20230201a

2023/02/08 23:04

早急な返信ありがとうございます。 >恐らく「A:255 B:0」は発生しないはずです) たしかに、A,Bの違いが引数Cならば、発生しなさそうですね。 >img_ans[ img_a == 0 & img_b == 0 ] = 0 なるほど、npはこういう使い方もあるのですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問