ビットマップ画像の明るさやコントラスト変更方法

[戻る]
taiping 2008/02/04(月) 11:12:22
いつも参考にさせて頂いています。

現在、ディスクからJPEG画像を読み込み、1秒間に30枚ほど連続的に表示させることで動
画のようにみせる処理を実装しています。

そこで、画質の補正(明るさ調整、コントラスト調整)を追加したところ、1枚の処理に
400ms程かかるようになり、1秒間に30枚のパフォーマンスが出ません。
画質の補正には、CodeProjectで見つけたImageStone
http://www.codeproject.com/KB/graphics/ImageStone.aspx
というライブラリを使っています。

画質の補正をより高速に実現する方法はないでしょうか?
DirectShowを使った方法等でも大丈夫です。

何か良い参考図書、ホームページ等ご存知の方がいらっしゃいましたらご教授をお願い致
します。

たいちう 2008/02/04(月) 13:26:02
直接の回答ではないです。

1.画質の補正をあらかじめ行うことは可能か?

可能ならば補正済みのファイルをどこかに保存しておき、
再生時は表示のみとなります。

2.画像のサイズは?全部で何枚位?マシンスペック等は?

私の力量では最速で補正する為の方法を示すことはできませんが、
この手の処理に明るい人にとっても、より良いアドバイスには
これらの情報が役に立つと思います。
(どのような条件でも同じ方法が最適とは限らないので)

3.JPEG以外のファイル形式に変更することは可能か?

素人考えですが、圧縮されているJPEGを補正するよりも
BMPを補正する方が早い気がする。

4.ImageStoneのソースコードは理解できますか?

ImageStoneは多くのファイル形式に対応しているようです。
自分にとって必要のない処理やチェックを除けば、
速くなる可能性はあります。

Hazard52 2008/02/04(月) 14:28:42
参考になるか分かりませんが、つい最近、同じ様な問題にぶつかりました。
こちらの場合、画像サイズが1600x1200に対し、表示枠が240x180だったので、
StretchBlt()で、表示サイズの画像を作成してから、画質の補正をする事で
対処しました。

taiping 2008/02/04(月) 15:02:24
たいちうさん、Hazard52さん、ご返信ありがとうございます。
>たいちうさん
インラインでコメントさせて頂きます。

>1.画質の補正をあらかじめ行うことは可能か?
画質補正の機能はスライドバーで補正値を動的に設定できるように考えています。
そのため、事前にどのくらいの補正をするのか判断できないため、補正後の画像を作り置
くことはできません。

>2.画像のサイズは?全部で何枚位?マシンスペック等は?
画像は640x480の画像ですが、枚数は決まっていません。
VCでイメージをロード後はCBitmapクラスのオブジェクトとして扱っていますが、1枚当た
り1MBくらいになっているようです。
開発で使っているPCはP4の2.8Gでメモリは1.5GBくらいです。
実際はもっと低スペックでも動作するようにしたいと考えています。

>3.JPEG以外のファイル形式に変更することは可能か?
VCのプログラムからイメージをロードし、CBitmapのオブジェクトとして読み込むと内部
ではビットマップのような扱いの気がしますが、間違っていますか?(消費メモリがJPEG
画像よりも大きいため)

>4.ImageStoneのソースコードは理解できますか?
修正することはできるかもしれませんが、”定石”のような手段が分かればそのような手
法で実装したいと考えています。(例えば、DirectShowを使うとか)

>Hazard52さん
私の場合は、640x480の画像を640x480の枠(PictureControl)内に表示させようとしてい
ます。画質の補正はどのように実現されましたか?

開発環境はVS2005ですが、諸事情でMFCで開発しています。

以上、よろしくお願い致します。

Hazard52 2008/02/05(火) 09:37:32
画質の補正は、自分でグルグル回して計算してます。
「0.299, 0.587」でYahoo等で検索すると、参考になるサイトが
たくさんヒットしますよ。

taiping 2008/02/06(水) 12:07:31
>Hazard52さん
ご返信ありがとうございます。

グルグル回してとは、画像のX方向とY方向にループさせながら、各ピクセルのRGB値を取
得し、輝度等を計算するということですか?

今回は画像サイズが640x480でフレーム数も1秒間に30フレームほどありますが、各点を計
算してもパフォーマンスは問題無いのでしょうか?

また、各点のRGBを操作しなくても良いような、上位のライブラリは無いでしょうか?

PATIO 2008/02/06(水) 14:34:41
横槍になりますが。

> 今回は画像サイズが640x480でフレーム数も1秒間に30フレームほどありますが、各点を計
> 算してもパフォーマンスは問題無いのでしょうか?

これについては実際にやって見たほうが早いような気がします。
計算ロジックがわかっていれば、実測できそうです。
マシンスペックとの兼ね合いもあるので多分実測しないと何ともカナと。


> また、各点のRGBを操作しなくても良いような、上位のライブラリは無いでしょうか?
ライブラリを使ったとしてもパフォーマンスは変わらないと思うのですけれど、
単純に工数削減の為と言う話なのかな?

Hazard52 2008/02/06(水) 14:39:00
こちらはMFCのCImageクラスの変数に、JPEGをロードして、
GetBits()でバイト配列のポインタを取得し、下から上に
高さ×幅×3(BGR分)ループしてRGB値を計算しています。

パフォーマンスに関しては、申し訳ありませんが、
実行してみないと分からないと思います。。。

以前ネット検索した時に、サードパーティー製のライブラリも
有りましたが、パフォーマンスが良いかは不明です。
勝手な憶測ですが、たぶん内部的には同じ様にループして計算している
だけではないでしょうか?

taiping 2008/02/08(金) 17:43:43
PATIOさん、Hazard52さん、アドバイスありがとうございます。

>これについては実際にやって見たほうが早いような気がします。
実装して計測してみたいと思います。計測に関してはCPUクロックを
QueryPerformanceCounterで取得する方法で試してみます。


>単純に工数削減の為と言う話なのかな?
それもありますが、世間で広く使われているライブラリの方が品質も確保できるかと思い
ました。
また、今回のように画像補正の実装が初めてだったため、各ビットのRGB値を変更するよ
りも、一般的な手法が存在しているかどうかも分からなかったので質問させて頂きまし
た。

Hazard52さんに教えて頂いた方法で実装してみます。
結果が分かり次第、またこちらに書かせて頂きます。

名無しのプログラマー@4年目 2008/02/09(土) 10:06:03
単純にルックアップテーブルで高速化できるような…。
VGA画像で補整処理に400msは非常に遅いと思います。

ここでひとつ気になったのですが、下記処理時間はどれぐらい要しますか?
・1枚の画像を取り込む時間
・1枚の画像を表示する時間

30fpsを実現するためには、33ms前後だと思います。(計算あってる?)
マシンスペックによると思いますが、画像取得・表示だけで33msのうち
大半を占めるのでは無いでしょうか?

目標としては、10ms以下になるように高速化する必要があります。
C/C++だけで高速化が難しいならばインラインアセンブラでSIMDを利用し
高速化するのもありかと思います。(メモリのアライメントなど条件付き)

UXGA画像(1600x1200)でエッジ抽出(1次微分)で2〜3ms前後ですので、
このあたりまでは高速化できるはずです。
(※SSE2整数でアセンブラ化した場合.)

2008/02/09(土) 19:41:13
>インラインアセンブラでSIMDを利用
横から補足しておきますと、CPUによって使える命令が異なったりするので、CPU
によって処理を差し替えられるようにするなどの工夫も必要です。
また、最近のマルチコアやHT対応CPUなどもあるので、そういう環境ではアセン
ブリでゴリゴリ書く前に読み込みと補正を行うスレッドを複数作るという方法も取
れるはずです。

ディスクアクセスが早いならばJPEGをあらかじめ展開する事も出来ます。
BMPにして読み取りAPIに通すより、都合のいい形式で直接の方がいい場合も
有ります。
ディスクアクセスが遅くともCPUに余裕があるならば、JPEGなどの圧縮を展開す
る処理を自前で(ライブラリから引っ張ってきてもいいが)書いて、展開時に補正も
かけてしまうという方法もあります。

何がボトルネックなのかによるので、見当違いかもしれませんが…

古いスレッドには追加発言できません。