3

画像をグレースケールに変換する公式があるように、画像の明るさを上げて同じレベルで下げる公式はありますか? r、g、bの各ピクセルに値を追加してみました。明るさは上がりますが、同じ値を下げると元の値に戻りません。

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]+100;
p[i+1] = p[i+1]+100;
p[i+2] = p[i+2]+100;

これにより、画像が明るくなります。しかし、すべてのピクセルから 100 を減らすと、元の画像は元に戻りません。

これを正しく計算するための特定の式があることをウェブで読みました。誰でも説明できますか?コントラストとガンマについても同様ですか?

アップデート:

提案をありがとう。以下の投稿のいくつかを調べた後、これを試しました。

明るさを上げるには:

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]+100 < 255 ? p[i]+100 : 255;
p[i+1] = p[i+1]+100 < 255 ? p[i+1]+100 : 255;
p[i+2] = p[i+2]+100 < 255 ? p[i+2]+100 : 255;

そして明るさを減らすために:

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]-100 >= 0 ? p[i]-100 : 0;
p[i+1] = p[i+1]-100 >= 0 ? p[i+1]-100 : 0;
p[i+2] = p[i+2]+100 >= 0 ? p[i+2]-100 : 0;

インクリメントが正常に機能していることはわかりますが、デクリメントしても元の画像は得られません。元の画像と明るくした画像には少し違いがあります。

私は何を間違っていますか?

4

2 に答える 2

5

グーグルでのクイック検索は示しました:

C++を使用してビットマップ画像の明るさ/コントラストを調整します

リンク:

http://www.kweii.com/site/color_theory/2007_LV/BrightnessCalculation.pdf

https://web.archive.org/web/20140825114946/http://bobpowell.net/image_contrast.aspx

投稿する前に、同様の質問を探すことを忘れないでください:)。

編集:

さらに2つのリンク:

画像処理アルゴリズムパート5:コントラスト調整:

http://thecryptmag.com/Online/56/imgproc_5.html

画像処理アルゴリズムパート4:明るさの調整:

http://www.dfstudios.co.uk/articles/image-processing-algorithms-part-4/

編集:

投稿したコードの2番目のブロックにエラーがあります。

var pixels = context.getImageData(...);

//loop over the pixel data and add a value
p[i] = p[i]-100 >= 0 ? p[i]-100 : 0;
p[i+1] = p[i+1]-100 >= 0 ? p[i+1]-100 : 0;
p[i+2] = p[i+2]+100 >= 0 ? p[i+2]-100 : 0; // <- Tha p[i+2]+100 should be a p[i+2]-100 right?

Johannes Jendersieが言っていることは真実です、あなたの問題はこれです:

この値のピクセルがあると言わないでください

R = 100;
G = 210;
B = 20;

そして、各色に100を追加すると、次のようになります。

R = 200;
G = 255; // It was 310 but you have to clamp it to 255.
B = 120;

今、あなたはそれらの同じ100を引きます:

R = 100; // same
G = 155; // different!, this have to be 210!!
B = 20;  // same

そのため、この操作は元に戻せません。常に元の画像のコピーを用意し、値を変更するたびに明るさ補正を再適用することができます。

したがって、100を加算する操作を元に戻す方法は、100を減算するのではなく、明るさ補正値を0に設定することです。これは、画像編集プログラムが機能する数であり、スライダーがあり、スライダーウィンドウで値を変更できます。 0に設定すると、常に元の画像が取得されますが、修正を「適用」すると元に戻すことはできません。スライダーウィンドウを再度開くと、「0」が以前にフィルタリングされた画像になります。

したがって、画像とbrightnesCorrection値のバックアップをどこかに保持し、値が変更されるたびに、画像に修正を再適用するか、復元できないという事実を受け入れる必要があります。以前の栄光のxDへの画像(少なくともこの種の明るさ補正では、より良い方法があるかどうかはわかりません)。

それが役に立てば幸い。

于 2012-12-18T18:54:48.717 に答える
5

画像に対する多くの操作は、値の丸めとクランプのため、元に戻すことができません。

あなたの各カラーチャンネルp[i]はおそらくバイト型ですか?その場合、0 から 255 までの値しか保存できません。たとえば 223 に 100 を追加すると、1 バイトに保存できない 323 になります。これにより、67 へのオーバーフローが発生するか、255 (可能な最大数) にクランプされます。100 を引いても 223 にはなりませんが、結果は 155 になります。

オフセットを追加する代わりに、色を掛けてみてください。しかし、それは AngelCastillo の回答でカバーされています。(そこでも情報が失われますが、結果はより良くなります)


アップデートへの反応:

つまり、クランプ値 (実際の実装など) によってデータが失われるということです。上記の例のように、大きすぎる値は 255 になります。そのため、100 を再度引くと、すべての色が 155 に設定されます。これは、元の色では 155以上でした。明るい色 (>155) の情報は失われます。

他の場合 (コントラストとガンマの変更) では、丸めにより以前の異なる色が同じ値に設定されるため、情報も失われます。

これを回避する唯一の方法は、チャネルごとにより多くの情報を持つ他の形式を使用することです。例: >16 ビットの符号付き整数または浮動小数点。キャンバスにそれを行うオプションがあるとは思えないので、独自のバックグラウンド コピーを保持する必要があります (より高い値の範囲で)。コピーに対してすべての変換を行い、キャンバスに固定された画像を表示するだけです。

于 2012-12-18T19:01:51.503 に答える