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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

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

Q&A

解決済

1回答

1350閲覧

LUT for 16bit image

k5kkkkk

総合スコア102

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

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

Python

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

0グッド

0クリップ

投稿2023/03/06 10:31

編集2023/03/07 06:20

実現したいこと

openCVのcv.LUT()と同等の処理を8bpcではなく16bpcなどで行いたい

前提

openCVのcv.LUT()のように、src の値から dst の値を一律の方式で変換したいです
この時、srcが dtype=CV_8U 以外では実行できないようで困っています

試したこと

とりあえずPythonの for-loopでpixcel を回して処理していますが、実行速度が遅く困っています
Numpy などに代用可能な処理があるのではないかと思うのですが、見つけられずにいます
8bpc 以外の画像を扱われる方は、一般にどのような処理を行われているのでしょうか?

8bpc版ベンチマーク

稚拙ですがベンチを書いてみました

python

1import cv2 2import numpy as np 3import random,time 4 5HEIGHT,WIDTH= 1080,1920 6 7lut_list = [random.randrange(0,2**8) for i in range(2**8)] 8lut_np = np.array(lut_list,dtype=np.uint8) 9src = np.empty((HEIGHT,WIDTH),dtype=np.uint8) 10dst = np.empty((HEIGHT,WIDTH),dtype=np.uint8) 11 12def by_cv2LUT(src,dst,lut_np): 13 return cv2.LUT(src,lut_np) 14 15def by_loopD2_np(src,dst,lut_np): 16 for y,line in enumerate(src): 17 for x,pix in enumerate(line): 18 dst[y,x]=lut_np[pix] 19 return dst 20 21def by_loopD2_list(src,dst,lut_list): 22 for y,line in enumerate(src): 23 for x,pix in enumerate(line): 24 dst[y,x]=lut_list[pix] 25 return dst 26 27def by_loopD1_np(src,dst,lut_np): 28 tmp = dst.flatten() 29 for i,pix in enumerate(src.flatten()): 30 tmp[i]=lut_np[pix] 31 return tmp.reshape([HEIGHT,WIDTH]) 32 33def by_np_array_indexing(src,dst,lut_np): 34 return lut_np[src] 35 36if __name__ == '__main__': 37 exp_val = by_cv2LUT(src,dst,lut_np) 38 funcs = [ 39 by_cv2LUT, 40 by_loopD2_np, 41 by_loopD2_list, 42 by_loopD1_np, 43 by_np_array_indexing, 44 ] 45 46 for func in funcs: 47 t0 = time.time() 48 for i in range(10): 49 res = func(src,dst,lut_np) 50 print(func.__name__,(time.time()-t0)/10) 51 assert np.all(res==exp_val),"error" 52 53
by_cv2LUT 0.0005998373031616211 by_loopD2_np 0.40140058994293215 by_loopD2_list 0.4011006116867065 by_loopD1_np 0.3491004467010498 by_np_array_indexing 0.004999876022338867

結論

やはり openCVのLUTが優位に速いです
numpyの array indexing ? を使用することで、openCVに迫ることが出来ました
こちらであれば8bpc以外の画像も処理可能です

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

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

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

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

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

k5kkkkk

2023/03/06 13:20

コメントありがとうございます。 元々cv2.LUT()が実装されていることを知らず、8bpcでは ・1pixずつ計算して変換 ・pythonでLUTを実装 ・cv2.LUT()での実装 と、それぞれ体感では実行速度の改善が行えました。 可能であれば、16bpcなどでもcv2.LUT()と同等の実行速度をだしたく質問いたしました。
PondVillege

2023/03/06 13:54

では,C/C++で同等の処理を記述してPythonからデータを渡すと良いのでは無いでしょうか?
k5kkkkk

2023/03/07 02:18

既存のフレームワークを利用できるのがベストなのですが、やはりマッチするものは存在しないのでしょうね C/C++での処理にもチャレンジしたいと思います アドバイスありがとうございます
bsdfan

2023/03/07 05:25 編集

stackoverflow の回答が、ごちゃごちゃ書かれていてわかりにくいのですが、その要旨は cv2.LUT(image, table) 相当のことが、numpyの integer array indexing を使って、table[image] と書くだけでできるということです。
k5kkkkk

2023/03/07 05:31

コメントありがとうございます。質問が言葉足らずだったと反省しています。 stackoverflow の回答は 追記したベンチの by_loopD1_np() と同等と考えています。 全く同じ戻り値を得ることは出来ていますが、cv2.LUT()と比較すると実行速度が遅いのが難点です。 10bpc,12bpc,16bpcでも同等の実行速度で変換したいというのが趣旨です
bsdfan

2023/03/07 05:35

同等ではないですよ。ループは不要です。 その関数で言うならば、 dst[:] = lut_np[src] とだけ書けばOKです。
k5kkkkk

2023/03/07 05:41

ご指摘いただいた通りの記述としたところ、 0.0052 s 程度で処理ができました。 ありがとうございます!!
guest

回答1

0

ベストアンサー

Numpy などに代用可能な処理があるのではないかと思うのですが

OpenCV Python: LUT for 16bit image?といったほぼ同じ問題に対する回答を見つけましたので情報提供します。
1ch または 3(以上)chそれぞれでのコード例が記載されています。

投稿2023/03/06 11:23

can110

総合スコア38266

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

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

k5kkkkk

2023/03/06 13:15

回答ありがとうございます。 提供いただいたコードとは少し異なるのですが、8bpcの画像を変換する際、HeightとWidthの2重のforで同様にLUTを引いたところ実行速度はそれなりにかかっていました。 こちらをcv2.LUT()での実装に変更したところ、体感では大幅に実行速度が改善されました。 そのため、Pythonでforを回すことは可能であれば避けたいです。 時間が取れ次第、8bpcでのベンチマークを取り共有します
k5kkkkk

2023/03/07 06:14

bsdfan さんにご指摘いただき、stackoverflow の回答で実現できることが確認できました。 numpyのスライスとして2次元の配列を与えてLUTとして動作させるというのが予想外で理解できていませんでした。 can110 さん、ps_aux_grep さん ご回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問