ImageMagick 使用例 -- 色の基礎とチャンネル
- 色とは何か?
- RGB 色空間
- CMY 色空間
- CMYK 色空間
- ガンマ補正
- モニターのガンマ
- sRGB 色空間補正
- 色名の衝突
- チャンネル画像の分離
- 色空間からのグレースケールチャンネル
- その他のチャンネル分離手法
- RGB チャンネル画像の結合
- 非 RGB チャンネル画像の結合
- HSL カラーホイールの生成
- 知覚的色空間 (Lab, Luv)
-
画像内の色の置換 (特定の色を置き換える)
- 画像内の色で置換する
- 塗りつぶし描画 (Floodfill Draw)
- 塗りつぶし演算子 (Floodfill Operator)
- ファズ係数 — 近い色のマッチング
- ファズ係数の距離
- ファズ係数と透明色
ImageMagick が扱う(一般的に)ラスター画像とは、基本的には個々の点、すなわち色を持つピクセルの配列です。個々の点と、それがどう表現されるかを変更する方法を、このセクションで見ていきます。次のセクションでは、画像全体を通したより一般的な大域的な色の変更を見ていきます。
色とは何か?
色を本当に理解するには、色とは正確には何なのかを知る必要があります。物理世界では、色は実は錯覚です。私たちが色を見ているのは、目が物理世界を非常に特殊で限定的な方法で感知しているからです。基本的に私たちの目には、赤・緑・青を感知する特別なセンサーがあり、それに加えて周辺視野や暗所条件のための、やや劣った副次的なセンサーがあります。後者があるために、夜間にはグレーの色しか見えないのです。
詳しくは Wikipedia, Cone Cells を参照してください。右のグラフは、典型的な人間の目が異なる波長の光に対して示す応答です。このため私たちは赤・緑・青の電磁波の波長という形でしか世界を感知しておらず、これが画像と画像処理が一般に赤・緑・青、すなわち RGB を中心に語られる理由です。ただし、話はそれほど単純でもありません。それぞれの色センサーは、実際にはある範囲の波長に応答します。例えば黄色の光を見るとき、私たちは実際には赤と緑の両方のセンサーでその光を感知しています。もし色センサーが純粋な赤と緑だけを検出するものであれば、黄色の色は一切見えないことになります。実際、虹に「すき間」が見えてしまうでしょう。つまり、テレビやコンピューターのディスプレイは、本物の黄色の光ではなく、ちょうどよい割合の赤と緑の光を発することで、黄色を見ていると私たちを錯覚させているのです。色センサーは純粋な黄色の光に対するのと同じ強度を感知し、その結果として、現実には2つの異なる色の周波数を見ているにもかかわらず、私たちは黄色を見ます。純粋な黄色と、赤と緑の光の混合との区別はつきません。同じように、青と赤の色(紫)は単一の特定の波長としては実在せず、少なくとも2つの色の周波数の混合としてのみ存在します。もっとも、厳密には菫色(violet)は私たちが反応する特定の周波数であり、主に青で、ごくわずかに他の2つのセンサーでも反応します。なお、私たちには実は4つ目の視覚センサーがありますが、これは色ではなく低照度の検出器で、錐体センサーがうまく働かなくなる夜間視に使われます。これが夜間が単色に見え、月明かりがすべて灰色に見える理由です。このセンサーは、おそらく sRGB 色空間(後述)が非常に暗い色に対して奇妙な線形成分を持つ理由でもあります。余談: 他の動物は私たちとは異なるセンサーを持っています。ハチやその他多くの昆虫は紫外線のセンサーを持っており、彼らにとって私たちの印刷した画像やテレビ、看板などはおそらくほとんど意味をなさないでしょう。これらの人工的な画像は、私たち人間が騙されて見ているほぼ完璧な色というよりも、むしろかなりひどい偽色画像のように見えるでしょう。4つの色センサーを持つ動物もいれば、1つ(白黒)や2つしか持たない動物もいます。また、特定の色よりも動きをはるかによく見分ける動物もいます。例えば雄牛は赤を見ることはできませんが、青-菫色と緑の波長は見え、はためく布は「動き」の色の閃光として映ります。雄牛にとって、モニターの 50/60Hz の更新サイクルは、何かまともな画像というよりも「動き」の閃光のように見えることでしょう! 詳しくは Wikipedia, Color Vision および Wikipedia, Color を参照してください。
RGB 色空間とチャンネル
つまり RGB 色空間とは、赤・緑・青の3つの値を用いて画像を表現する方法であり、これによって私たちは現実世界の何かを見ていると錯覚させられます。したがって画像は3つの値の配列として格納でき、3つの値それぞれが1つのピクセル、すなわち表示される色の点を形成します。3つの値の配列それぞれはチャンネルとして知られ、これは私たちの色センサーの1つ分の光をどれだけ生成すべきかを表す、単なるグレースケール画像です。例えば、これがバラの画像の赤・緑・青の成分です。 ![[IM Output]](../static/img/images/rose.gif)
バラ | | ![[IM Output]](../static/img/color_basics/separate_RGB_0.gif)
赤 | ![[IM Output]](../static/img/color_basics/separate_RGB_1.gif)
緑 | ![[IM Output]](../static/img/color_basics/separate_RGB_2.gif)
青
---|---|---|---|---
バラを表示するための「赤」の画像が、他の2つの色成分よりもはるかに明るいことに注目してください。しかし3つの画像はすべて、下の方にある白いパッチに対しては明るくなっています。RGB は加法色である さて、赤・緑・青の色は「加法」色と呼ばれます。つまり、これらの色を足し合わせて最終的な色画像を形成します。これは、これらが私たちの目が見る支配的な色であり、それらを組み合わせることで、私たちの目が見えるほぼすべての色を実質的に生成できるからです。黒、例えば何も映っていないモニターから始めて、私たちが見る画像に対して適切な色を生成するために、赤・緑・青の光を加えていく、という意味で加法的です。その鍵は、黒、すなわち光の不在から始め、そこに適切な量の赤・緑・青を加えていくことです。暗い部屋で、端に赤・緑・青のセロハンを貼った3つの懐中電灯を照らしても同じ効果が得られます。3つの色が、例えば白い壁の同じ場所に当たると、私たちには白が見えます。これは、私たちの目がこうした「原」色を実際にどう見ているかによるもので、色画像が一般に RGB 値(「色チャンネル」とも呼ばれる)で表現される理由です。
CMY 色空間
印刷では別の問題が生じます。紙は光を生成できず、反射するだけです。そのため、当たった光をあらゆる方向に全反射する表面から始める必要があります。それが白い表面です。願わくば、その反射している光自体が、窓から差し込む太陽光や人工照明の部屋の照明によって生成された純粋な白色光であってほしいものです。さて、その紙の上に画像を作るには、その表面にインクを塗布する必要があり、これは実際には特定の波長の光を取り除きます。私たちは赤・緑・青の色を「感知」するので、それらが白い紙から反射する光から選択的に取り除きたい色です。したがって、赤い光を取り除くためにシアンインクを、緑の光を取り除くためにマゼンタを、青い光を取り除くためにイエローを使います。特定の色を生成するために必要なシアン・マゼンタ・イエローのインクの量が、CMY 色空間と呼ばれるものを生み出します。ここでは、シアン・マゼンタ・イエローのインクだけ(インクが「線形」であると仮定して)を使ってバラの画像を生成するために必要なインクのマスクを生成します。 ![[IM Output]](../static/img/images/rose.gif)
バラ | | ![[IM Output]](../static/img/color_basics/separate_CMY_0.gif)
シアン | ![[IM Output]](../static/img/color_basics/separate_CMY_1.gif)
マゼンタ | ![[IM Output]](../static/img/color_basics/separate_CMY_2.gif)
イエロー
---|---|---|---|---
つまり、シアンのマスク値が明るいほど、より多くの赤を取り除くためにより多くのシアンインクが必要になります。言い換えれば、シアンのマスクは、紙に反射させたい赤い光の量のちょうど反転(ネガ)です。実際、上の3つのチャンネル画像はすべて、RGB 色空間で生成されたもののちょうどネガになっています。ですから、RGB 画像を CMY 画像に変換するには、画像をネガ化してから、その画像を CMY 色空間にあると宣言するだけです。波長を選択的に取り除いているので、シアン・マゼンタ・イエローは「減法色」として知られます。
CMYK 色空間
波長を選択的に取り除くことの大きな問題は、シアン・マゼンタ・イエローの3つすべてのインクを塗布して赤・緑・青の光をすべて取り除いても、実際には反射されている光すべてを取り除けないことです。その結果、黒い色ではなく、ひどく見える濁った茶色が残ってしまいます。私たち自身の目が完璧でないのと同様に、インク(や光のフィルター)も完璧ではありません。前述したように、私たちの色センサーはそれぞれ単一の波長の光だけを見ているのではなく、「赤」「緑」「青」(またはそれらの色の混合)と解釈する波長の範囲を見ています。それほどまでに、私たちの「青」の光センサーは(あまりよくはありませんが)わずかな紫外線まで実際に見ることができます。余談: 「ブラックライト」のフィルターは意図的に不完全に作られており、それによって私たちはそのランプの光を「かろうじて見る」ことができ、点いているかどうかを知ることができます。CMY インクからのこうした色の「漏れ」と、私たち自身の不完全な目があるために、混合に純粋な黒のインクも加え、それを使って紙から反射されうるすべての光を消し去ることができるようにします。青(Blue)と混同されないように、黒のインクまたはチャンネルには K の文字が割り当てられます。したがって印刷では、シアン(Cyan)・マゼンタ(Magenta)・イエロー(Yellow)・黒(blacK)の4色のインクを使い、これらのインクを用いて画像を定義し、CMYK 色空間を形成します。例えば、これがこの画像から分離された適切な CMYK 成分です。 ![[IM Output]](../static/img/images/rose.gif)
バラ | | ![[IM Output]](../static/img/color_basics/separate_CMYK_0.gif)
シアン | ![[IM Output]](../static/img/color_basics/separate_CMYK_1.gif)
マゼンタ | ![[IM Output]](../static/img/color_basics/separate_CMYK_2.gif)
イエロー | ![[IM Output]](../static/img/color_basics/separate_CMYK_3.gif)
黒
---|---|---|---|---|---
シアン・マゼンタ・イエローの量が減り、CMY 色空間のときよりも暗くなっていることに注目してください。それらの使用が適切な量の黒に置き換えられたためです。つまり、特定のピクセルで3つすべてのインクが存在する場合、代わりに黒が使われます。したがって、例えば純粋な黒を印刷するには、純粋な黒のインクだけを使い、他のインクは使いません。上記の「黒」は紙に塗布する黒のインクの量であることを思い出してください。グレースケールのチャンネル画像が明るいほど、より多くの黒のインクを使うべきだということです。そのため、これも他の3つの画像と同様に、ネガに見える画像になっています。もちろん、カラープリンターで純粋な黒を加えることで、黒い文字の印刷がずっと単純になります。純粋な黒の線・文字・図形を生成するために、3つの異なるインクを同じ場所に完璧に重ねて印刷する必要がなくなるからです。これはインクがはるかに少なくて済むことを意味し、紙が「濡れにくく」、にじんだりこすれたりしにくくなるため、特にプリンターにとって好都合です。RGB と CMYK の色がどう機能するかについての別の同様の議論については、XaraXone Workbook, Defining Color の導入ページを参照してください。
その他の色空間
他の色空間は、同じ色を表現する別の方法、あるいは厳密な RGB を超えて、私たちの不完全な目が識別できる色の一部を表現する別の方法にすぎません。しかし、そうした色空間は、モニターでの色の表示にも印刷にもほとんど関係ありません。それらは基本的に、特定の事柄を強調したり際立たせたりするために、画像の色を扱い、あるいは処理する別の方法を表しています。例えば次のようなものです。
- 暗い色のより優れた非線形な扱い (sRGB)
- 色の虹と色相 (HSB,HSL,HSI,OTHA 色空間 — 強度は保存されない)
- 標準化された色の定義 (XYZ)
- 正確または知覚的な色差 (LAB と LUV 色空間、およびそれらの循環的な色相に対応する LCHab と LCHuv)
- 拡張されたハイダイナミックレンジ (HDRI 画像で使用) (scRGB)
- 色値のより優れた圧縮 (YIQ や YUV など)
- テレビの伝送用 (YCbCr, YPbPr。Y = 白黒信号)
まだ言及していない最後の色空間が「グレースケール」ですが、これは単純なピクセル値の単一の配列にすぎません。これらの値をどう解釈するかは可変で、多くの異なるものを表しうるからです。通常、そうした画像は線形グレースケールであり、(非線形の sRGB とは対照的に)線形 RGB に似たものとみなされます。IM バージョン 6 には実はそのようなグレースケール色空間がなく、すべての RGB 設定を同じ値に設定した線形 RGB 色空間で、それを擬似的に再現しているにすぎません。3つの値が同じでなければ、その画像はもはやグレースケールではありません。IM バージョン 7 のグレースケールは単一チャンネルの画像です(メモリ使用量がはるかに少なくなります)。 | _画像の「色空間」に対する上記の変更は、メモリ内での画像の色の大まかな配置にすぎません。また、異なる色空間どうしの非常に基本的な(単純化された)色変換も提供します。
正確な色指定と色変換には、代わりに カラープロファイル を使うべきですが、これはカラープロファイルを扱える画像ファイル形式を使用する場合にのみ機能します。
_
---|---
ガンマ補正と sRGB 色空間
人間の色知覚
上記では、画像をさまざまな方法で表現できることを見ました。上記で見たすべての色空間は「線形」色空間として知られており、これは使われる実際の値が、画像内の色の実際の「強度」値を表すことを意味します。 しかし、実生活はそれほど単純ではありません。決して単純にはいきません! 例えば、単純な線形の灰色の値の連なりを持つ画像を生成して保存してみましょう。 |
magick -size 100x100 gradient:'gray(100%)-gray(0)' \
-set colorspace sRGB gradient.gif
- 「
gradient:'gray(100%)-gray(0)'」を使うことで、IM が線形 RGB データのグラデーション、すなわち線形 RGB 色空間のものを生成することが保証されます。 - 「-set colorspace sRGB」は、この「線形」グラデーションが実際には「sRGB」であると IM に伝え、これにより sRGB 色空間の値しか格納できない GIF 画像ファイル形式に保存するときに「補正」が不要になります。
さて、この画像で使われている実際の色値は、上部の白から下部の黒へ滑らかに変化し、中央には数学的に正確な完璧な 50% グレーがある線形グラデーションのはずです。しかし、画像を見ると、明るい(白に近い)色よりも暗い(黒に近い)色がずっと多く含まれているように見えます。なぜでしょうか? それは、人間の視覚が最大範囲(「白」)の半分の光の強度を与えられたとき、その色値が示す純粋な中間調の灰色ではなく、ずっと暗い色を見るからです。その結果、上記の線形グラデーションは白から黒への均一で線形な広がりには見えず、本来あるべきよりもはるかに多くの暗い色を含んでいます。実際の画像の値から知覚される値への関係は、おおよそ次の形の「べき関数」です。
**_perceived_grey_ = _value_ 2.2**
値「2.2」は、ほとんどの人間に典型的な、平均的なガンマ関数の値です。
ガンマ補正
ガンマ補正は、実際に保存される色値を調整して、最終的な画像の色の広がりがずっと均一に見えるようにする方法です。基本的に、人間の視覚はべき係数 2.2 を使って光を暗く見せるので、線形画像を「線形に」見せるには、1/2.2 の値を使ってそのべき関数を逆にする必要があります。つまり、画像を線形に見せるには、次の式を使って補正する必要があります。
**_gamma_corrected_value_ = _value_ 1/2.2**
IM は レベル演算子のガンマ引数、またはより具体的には ガンマ演算子 を通じてガンマ補正を提供します。ただし、Evaluate POW 関数 を使って画像の値を直接変更することもできます。
では適用して「ガンマ補正された画像」の結果を見てみましょう。 |
magick -size 100x100 gradient:'gray(100%)-gray(0)' -gamma 2.2 \
-set colorspace sRGB gradient_gamma.gif
![[IM Output]](../static/img/color_basics/gradient_gamma.gif)
画像が明るい色と暗い色をはるかに均等な量で含むようになったことに注目してください。しかし、画像内の実際の値はもはや「線形」ではなく、これは後でこの画像を処理するときに問題を引き起こす可能性があります。ガンマ補正は、画像を「正しく」見せるために色を調整する大まかで「手早い」方法にすぎません。人間の応答に合わせて画像を補正する通常の、あるいは最良の方法でさえありません。画像処理のためのガンマ補正のより具体的な例については、ガンマ補正付きのリサイズ を参照してください。ガンマ補正についての詳細は、次を参照してください。
- Gamma Correction (Wikipedia)
- Gamma error in picture scaling (IM の使用に関するセクションを含む)
- Gamma FAQ, Image Processing
線形 RGB 画像を生成しようとして、(線形空間で)明るい色と暗い色を均等な量にするようにガンマを調整しようとする「[-auto-gamma](https://imagemagick.org/command-line-options/#auto-gamma)」演算子も見てみるとよいでしょう。
モニターのガンマ
モニターから数メートル(ヤード)離れて、左の画像を見てください。あなたのモニター(およびウェブブラウザー)が sRGB 画像を正しく表示しているなら、中央の「ハッシュ」パターンの明るさが、周囲の sRGB グラデーションとほぼ等しくなる点が、ちょうど真ん中にあるはずです。ほとんどのコンピューターモニターはこのテストに失敗します! ただし HDMI のテレビは完璧に表示されるはずです。この画像は次のように作成しました。 |
magick -size 45x256 gradient: -size 10x256 pattern:gray50 \
-duplicate 1,0 +append -set colorspace sRGB -colorspace RGB \
monitor_sRGB.png
![[IM Output]](../static/img/color_basics/monitor_sRGB.png)
ここに、異なる「ガンマ」レベルの同様の画像をいくつか示します。これにより、あなたのモニターが、人間の知覚にとって正しい「2.2」ガンマ表示にどれだけ近いかを見ることができます。
for gamma in 1.6 1.8 2.0 2.2 2.4
do
magick -size 45x256 gradient: -size 10x256 pattern:gray50 \
-duplicate 1,0 +append -gamma $gamma monitor_g$gamma.png
done
![[IM Output]](../static/img/color_basics/monitor_g1.6.png)
ガンマ 1.6 | ![[IM Output]](../static/img/color_basics/monitor_g1.8.png)
ガンマ 1.8 | ![[IM Output]](../static/img/color_basics/monitor_g2.0.png)
ガンマ 2.0 | ![[IM Output]](../static/img/color_basics/monitor_g2.0.png)
ガンマ 2.2 | ![[IM Output]](../static/img/color_basics/monitor_g2.4.png)
ガンマ 2.4
---|---|---|---|---
(離れて見たとき)等しい明るさの点がおよそ 50% の位置にある画像が、あなたのモニターのおおよそのガンマレベルを教えてくれます。適切に調整されていれば、あなたのモニターのガンマレベルは 2.2 になっているはずで、これは sRGB 色空間のガンマと非常によく一致します。これを書いたとき、私の古い画面(職場から支給されたもの)は極めて質が悪いものでした。ガンマ設定はおよそ 1.8 で、しかもディスプレイの上部(より暗い)とディスプレイの下部(より明るい)で異なるガンマを持っていました。これは、画面上の異なる位置で画像を比較するときに私を悩ませました。同じ画像が、垂直方向に異なる位置に置かれると違って見えるのです! 一方、(当時の)私の個人用ラップトップは非常に均一なディスプレイで、上記によればまずまずの 2.0 のガンマ設定でした。
sRGB 色空間補正
sRGB 色空間を使って画像を保存するのは、画像をガンマ補正するのと非常に似ていますが、人間の目の実際の応答、特に非常に暗い色合いをよりよく再現するために、わずかに複雑になっています。 では、線形グラデーションを sRGB 補正された色空間で保存してみましょう。 |
magick -size 100x100 gradient:'gray(100%)-gray(0)' \
-set colorspace RGB -colorspace sRGB gradient_sRGB.gif
![[IM Output]](../static/img/color_basics/gradient_sRGB.gif)
| IM v6.7.7 以降、上記は次のように簡略化されます。 |
magick -size 100x100 gradient:white-black gradient_sRGB.gif
_これは、線形グラデーションが常に線形(RGB)色空間で生成される(演算子が動作する唯一の理にかなった方法)ためです。
しかし sRGB の色 'white-black' が要求されているので、線形データのグラデーションは自動的に sRGB 色空間に変換され、非線形のデータ値と、知覚的に線形なグラデーションが生成されます。
| _IM バージョン 6.7.5 より前では、IM は 'sRGB' と 'RGB' 色空間の意味を逆にしていたため、上記は失敗していたでしょう。そのため、古いバージョンの IM では2つの色空間名を入れ替える必要がありました。例えば...。 |
magick -size 100x100 gradient: -set colorspace sRGB \
-colorspace RGB gradient_sRGB.gif
_この色空間の扱いの奇妙さは、長らく IMv7 のバグとみなされていました。IMv7 でのみ修正される予定でしたが、IMv7 にバックポートされました。
上記(あるいは他のどんなグラデーション)も完璧ではないことに注意してください。完璧というのは単に不可能だからです。誰もがわずかな違いを伴って自分なりの見方で物事を見ています。簡単に言えば、_あなたに見えているものは、他の人に見えているものと決して正確には同じではありません(これは実に禅的です)。sRGB はあくまで、多数の調査、そして多くの印刷・塗料・色の専門家によれば、大多数の人々にとって非常によい近似であるにすぎません。正確な sRGB の式の詳細については、Wikipedia, sRGB Colorspace を参照してください。より完全で正確な「人間の輝度応答」が開発されており、論文 Human Vision, Just Noticeable Difference でオンライン上で見ることができます。これには、照明が大きく変化する状況での順応応答も含まれています。World Wide Web は、推奨される(そしてまだ十分に単純な)デフォルトの色空間として sRGB の使用を標準化しており、したがって色空間プロファイル情報を含まないすべての画像に使用すべきです。つまり、GIF・PNG・JPEG・TIFF などの画像です。これらすべての形式(GIF を除く)では、カラープロファイル を使って画像の色空間を確定的に指定できます。しかし、PbmPlus などの画像ファイル形式は、通常 sRGB 色空間にあるとはみなされません。そのため、そうしたファイル形式を扱うときは、色空間が想定どおりであることを保証するために「-set colorspace ...」を使うのが一般的によい考えです。そして、比較できるように3つの画像をすべて並べたものがこちらです。 ![[IM Output]](../static/img/color_basics/gradient.gif)
線形 | ![[IM Output]](../static/img/color_basics/gradient_gamma.gif)
ガンマ | ![[IM Output]](../static/img/color_basics/gradient_sRGB.gif)
sRGB
---|---|---
ご覧のとおり、ガンマ補正と sRGB 補正された画像はほぼ同一で、グラフ化したときの違いは実際には極めて小さいものです。そのため、sRGB を使うのがより正しい方法ではありますが、ガンマ補正 を使う方がおそらく適用が簡単です。sRGB 画像とガンマ画像の最大の違いは、極端に暗い画像にあります。8 ビットのグレー値 1 に対して、sRGB は等価なガンマよりも 60 倍明るくなります。値 8 では 5 倍明るくなります。これはほとんどの場合に目立った違いを生みませんが、非常に暗い画像を扱うときには違いが出ることがあります。
実画像の処理
ほとんどの画像処理演算子は、画像がどの色空間を使っているかを気にせず、その色空間にかかわらず単にチャンネルデータに操作を適用します。もっとも、一部の演算子は「黒(Black)」の余分なチャンネルデータや、後で見るように「アルファ(Alpha)」(または「アルファ」透明度)の扱いに特別な配慮を必要とします。しかし、画像の色空間は多くの操作の最終結果に大きく影響しうります。そのため、異なる色空間で画像処理を行うことで、改善された結果が得られることがあります。この例は、sRGB で処理するのがなぜよくないのかをより明確に示します。これは IM ユーザーフォーラムでの Color Blurs と「壊れた色」に関する議論からのものです。 異なる色チャンネルを使う2つの色を取り、チャンネル内で色がゼロ(低い色値)へとぼけていくように、それらをぼかして混ぜ合わせます。まず、デフォルトの sRGB 入力チャンネルを使ってこれを行いましょう。 |
magick -size 40x80 xc:red xc:lime +append \
-blur 0x20 blur_sRGB.png
![[IM Output]](../static/img/color_basics/blur_sRGB.png)
結果を見ると、色が赤から黒を経て緑へとぼけているように見えます。それは、sRGB 色空間では値が本来あるべきよりも私たちの目に暗く見えるからです。 ここでは同じ画像を、今度は線形 RGB 色空間を使ってもう一度ぼかします。 |
magick -size 40x80 xc:red xc:lime +append \
-colorspace RGB -blur 0x20 -colorspace sRGB blur_RGB.png
![[IM Output]](../static/img/color_basics/blur_RGB.png)
ご覧のとおり、今回は赤と緑の色がオレンジを経てぼける、はるかに理にかなった結果が得られます。LAB や LUV などの他の線形色空間を使っても同様の結果が得られます。これらについては後でより詳しく見ていきます。基本的に、色の混合を伴う画像を処理するとき、例えば 色の量子化(色の削減)のような操作だけでなく、画像のリサイズ や、より一般的には 画像の歪み でも、より正確な結果のためには線形色空間で画像を処理すべきですが、現実にはこれを行う人はほとんどいません。 | _(バレル歪みとレンズ補正で有名な)Helmut Dersch は、画像を処理する際、特にリサイズや画像の歪みに対して、線形の「LAB」色空間の使用を検討するよう推奨しています。
私は、画像の描画・合成・リサイズ・歪みを行うときにのみ、「入力」の sRGB 色空間から他の「線形」色空間へ移ることを推奨します。それが線形 RGB か LAB か LUV かは、それほど問題にならないはずです。
_
---|---
例えば、これが主要な3つの線形色空間における赤と青のぼかしです。これらの色を選んだのは、生成される中間色に最も大きな違いが現れるように見えるからです。
for colorspace in RGB LUV LAB
do
magick -size 80x40 xc:red xc:blue -append \
-colorspace $colorspace -blur 0x30 -colorspace sRGB \
colorspace_$colorspace.png
done
色空間を考慮した画像処理のより多くの例については、色空間補正付きのリサイズ を参照してください。また、線形色空間での色名と描画に関する警告については、ガンマと色空間補正を伴う描画 も参照してください。
色の指定
IM では色をさまざまな方法で指定できます。これに関する最良のガイドは、公式 IM ウェブサイトの Color Names にあります。
名前による色指定
多くの色には特定の名前が付けられており、使いやすくなっています。例えば「RoyalBlue」は非常に美しい明るい青みがかった色です。
右にあるのは、ImageMagick で利用できる、数字付きのものも含めたすべての名前付きの色を含む画像です。色はまずオフホワイト・中間調・暗い色の3つのグループに分類され、それぞれ異なる垂直方向のオフセットを持つ3つの別々の HSL カラーホイールにプロットされました。純粋な白と黒の色は、チャートの一番上と一番下に、垂直方向の範囲の両極端を形成する独立した点として現れます。これを生成したスクリプトは「[hsl_named_colors](../static/img/scripts/hsl_named_colors)」で、レイヤー画像のプログラム的な配置 で見た手法に従っています。 | _技術的には、HSL の色を「円柱」ではなく「二重円錐(bi-cone)」の3次元形状で描画しているので、各色の点の半径は、単なる「彩度(Saturation)」ではなく、色の「クロマ(Chroma)」(「彩度」/「明度」)に等しく設定されています。Wikipedia: HSL and HSV を参照してください。
さらに正確を期すなら、円錐の代わりに六角錐を使うべきですが、それは計算がはるかに難しく、得られるものはわずかです。
_
---|---
ご覧のとおり、赤から黄色にかけてはたくさんの色名があり、シアンから緑の色相にはより小さなグループがあります。オフホワイトのイエローとシアンにも同様のかたまりがあります。しかし、名前付きのオフグリーンの色はほとんどありません。本質的に、HSL 色空間には名前付きの色がほとんどない領域がいくつかあります。使うべき特定の名前付きの色を見つけるのは難しいことがあります。しかし、右の画像を IM の「[display](basics.html#display)」プログラムで読み込めば、マウスの中ボタンを使って、プロットされた特定の色の ImageMagick の色名を確認できます。
特別な色名
ImageMagick 内で特別な目的のために使われる特別な色がいくつかあります。「None」または「Transparent」は完全に透明な黒色で、一般に背景の透明度を指定するために使われます。例えば 単色キャンバス を作成するときや、画像レイヤー を使うときなどです。「Opaque」は単に「Black」の別名であり、そのためめったに使われません。これは通常、アルファチャンネル処理を行うときなど、何らかの不透明な色を意味したい場合にのみ使われます。
色名の衝突
色名は SVG・X11・XPM の3つの異なるソースから来ることがあり、ほとんどの名前は定義元のソースにかかわらず同じ色を生成します。しかし、使われている色指定によって異なる色を生成する色名がいくつかあります。最大の問題は SVG の色「Green」(半分の明るさの緑)で、これは X11/XPM の色「Green」(純粋な RGB の緑)とは異なります。純粋な緑が欲しい場合は、衝突のない SVG の色名「Lime」を使う方がよいでしょう。Wikipedia には、色名の衝突に関する優れた記事と、実際の色名の良い表が X11 color names にあります。また、いくつかの色の範囲をきれいに並べた表のセットを提供する Web Colors の記事も見てみるとよいでしょう。最も顕著な衝突は4つの特定の色にあります。これが既知の色名の衝突の表です。IM がデフォルトで使うのは SVG の色であることを覚えておいてください。 衝突する
色名 | SVG の結果
(IM のデフォルト) | X11 の結果
名前に対する | X11 で同等の
名前 | 代替の
色名
---|---|---|---|---
Green | | #008000 | | #00FF00 | | | Lime
Maroon | | #800000 | | #B03060 | | FireBrick |
Purple | | #FF00FF | | #A020F0 | | Magenta |
Gray | | #7E7E7E | | #BEBEBE | | | Grey
上記についての注意...
- X11 の「
Grey」は視覚的な中間調の灰色です。これは X11 の色「Gray74」や SVG の色「Silver」(「gray(192)」)にも非常に近い(ただし完全に同じではない)色です。 - デフォルト(SVG)の「
Gray」は、数学的に完璧な灰色に非常に近く、色名「Gray50」または「gray(128)」(8 ビット用)で指定する方がよいでしょう。 - すべての名前付きの色は 8 ビット(0-255)の値で指定されているため、どれも完璧な 16 ビットの純粋な灰色を生成しません!
- FFT DC 位相、エッジ検出、シェード画像、合成のライティング効果、相対変位マップ などの数学的処理に灰色が必要な場合は、色の式「
gray(50%)」を使う方がはるかによいでしょう。これはどの色のビット深度でも完璧な数学的中間調の灰色を生成します。
色と色空間
多くの色には名前がありますが、画像に見られるほとんどの色には名前がなく、特定の色を指定する一連の値(通常は3つ)にすぎません。しかし、3つの値だけでは色を完全に定義することはできず、それらの値が属する「色空間」または「色系」も指定する必要があります。上記のすべての「名前付き」の色は sRGB 色空間にあり、それが定義された色空間です。しかし、ときには異なる色空間で色を定義したいことがあります。例えば、HSL や CYMK、あるいは XYZ の色としてです。ImageMagick はこれを行うことができ、これらの指定の詳細は ImageMagick Color Names で見ることができます。将来: 他の色空間を使う例(まだ開発中) | _ImageMagick における RGB は線形 RGB 色空間を表しますが、「rgb(value,value,value)」という色名が実際には sRGB の色 を定義している、というのが受け入れられている慣行です。
sRGB の色ではなく線形 RGB の色を実際に定義するには、色の式「icc-color(RGB,value,value,value)」を使ってください(次を参照)。
---|---
IM v6.7.8-3 以降、関数「icc-color(colorspace,color...)」を使って色を定義したり、特定の色の色空間を再定義したりできます。_将来: 使用例
半透明の色
半透明の色を直接指定できる方法は2つだけです。半透明の色を設定する最も一般的な方法は、16 進値を使うことです。例えば、これがさまざまなレベルの色の透明度を示すいくつかの色指定です。パターンが画像の透明度を通して見えることがわかるように、生成した色画像を背景パターンの上に表示しています。
magick -size 50x50 xc:'#00FF00FF' color_hex_1.png
magick -size 50x50 xc:'#00FF00C0' color_hex_2.png
magick -size 50x50 xc:'#00FF0090' color_hex_3.png
magick -size 50x50 xc:'#00FF0060' color_hex_4.png
magick -size 50x50 xc:'#00FF0030' color_hex_5.png
magick -size 50x50 xc:'#00FF0000' color_hex_6.png
| IM v6.3.0 より前は、最後の 16 進数の組は「マット(matte)」または「不透明度(opacity)」値の形で色の透明度を含んでいました。つまり、最後の 16 進数「00」は「不透明」を表し、「FF」は透明でした。
しかし IM v6.3.0 以降、この値は反転され、「アルファ(alpha)」透明度の値を表すようになり、IM を SVG 標準や他のグラフィックスパッケージと一致させました。言い換えれば、「FF」は今や完全に不透明を表し、「00」は完全に透明です。
---|---
特別な「rgba()」色関数を使って色を指定することもできます。RGB の値は 0 から 255 まで、アルファチャンネルは 0.0(透明)から 1.0(不透明)までの小数の分数として指定されます。
magick -size 50x50 xc:'rgba(255,0,0, 1.0)' color_rgba_1.png
magick -size 50x50 xc:'rgba(255,0,0, 0.8)' color_rgba_2.png
magick -size 50x50 xc:'rgba(255,0,0, 0.6)' color_rgba_3.png
magick -size 50x50 xc:'rgba(255,0,0, 0.4)' color_rgba_4.png
magick -size 50x50 xc:'rgba(255,0,0, 0.2)' color_rgba_5.png
magick -size 50x50 xc:'rgba(255,0,0, 0.0)' color_rgba_6.png
| IM バージョン 6.2.7 より前は、「rgba()」もアルファチャンネルの値にマット値を使っていました。つまり、完全に不透明には値 0、完全に透明には値 255 でした。これは、IM が他の画像標準、特に WWW と SVG の用途に対してより準拠するようになる一環として、「W3C CSS3 Color Module の色指定に関する勧告」で定義されたとおりに変更されました。
---|---
現在のところ、追加のアルファ値設定を伴う名前で半透明の色を直接指定することはできません。しかし、その名前付きの色を生成してから、その画像の透明度を変更することでごまかすことはできます。さらに、実際に色の透明度を設定する前に アルファチャンネルを設定 しなければならないという、追加の複雑さもあります。
magick -size 50x50 xc:RoyalBlue color_name_1.png
magick -size 50x50 xc:RoyalBlue -alpha set \
-channel A -evaluate set 80% color_name_2.png
magick -size 50x50 xc:RoyalBlue -alpha set \
-channel A -evaluate set 60% color_name_3.png
magick -size 50x50 xc:RoyalBlue -alpha set \
-channel A -evaluate set 40% color_name_4.png
magick -size 50x50 xc:RoyalBlue -alpha set \
-channel A -evaluate set 20% color_name_5.png
magick -size 50x50 xc:RoyalBlue -alpha set \
-channel A -evaluate set 0 color_name_6.png
そう、これは面倒で、色名の指定の一部として透明度を設定できればよいのですが。これが実現してほしいと思うなら、IM Developers Forum で要望を出してください。MVG 描画設定 を使って名前付きの塗りつぶし色を描画することも可能ですが、これが正しく機能するには透明な開始キャンバスが必要です。例えば...。 |
magick -size 50x50 xc:none \
-draw "fill Tomato fill-opacity 0.5 rectangle 0,0 49,49" \
color_name_draw.png
| ![[IM Output]](../static/img/color_basics/color_name_draw.png)
| 完全に透明な色は完全に見えませんが、それでも色を持っていることに注意してください。しかし、ほとんどの IM 演算子は、完全に透明な色は他のどの完全に透明な色とも同じであると認識します。このことと、内部の数学が動作する仕組みのために、多くの演算子は完全に透明な色を、しばしば完全に透明な黒(特別な色「none」とも呼ばれる)に置き換えます。
---|---
色チャンネル
画像の実際の色データは、チャンネルとして知られる値の配列として格納されます。通常、画像は少なくとも3つのチャンネルを持ち、赤・緑・青の色値を表します。しかし、上で見たように、格納される値は他の色空間を表すこともあります。
色空間とチャンネルの命名
「[-colorspace](https://imagemagick.org/command-line-options/#colorspace)」演算子の主な目的は、IM がメモリ内で画像の色を格納する方法を変更することです。通常、各画像は3つ(または4つ)のチャンネルの画像データを持ちます。画像の現在の「色空間」が、各チャンネルのデータが何を表すかを決定します。さて、通常チャンネルは「赤(Red)」「緑(Green)」「青(Blue)」と名付けられます。それが通常それらのチャンネルに格納される画像データの種類だからです。しかし、常にそうとは限りません。「R」または「赤(Red)」のチャンネルを赤だと思わず、それを「チャンネル 1」だと考えてください。これは画像の色空間によって「赤」「色相」「シアン」その他のデータを含みうるものです。「赤(Red)」は、通常「赤」に、すなわち最初のチャンネルに使われるチャンネルのラベルにすぎません。2 番目によく使われる色空間は「CMYK」で、これは「白い」紙を暗くするために塗布すべき色の「インク」の量を定義します(減法色空間)。なお、K は「黒(blacK)」の略で、画像の強度値をネガ化したものです。これは非常に一般的なので、「RGB」チャンネルには「シアン(Cyan)」「マゼンタ(Magenta)」「イエロー(Yellow)」、あるいは単に「C」「M」「Y」という代替の命名もありますが、実際には「RGB」画像に使われるのと同じチャンネルの組を指します。「黒(Black)」または「K」の色チャンネルのために、特別な 4 番目の色チャンネルも追加されます。これは基本的に、「Green」の色チャンネルが、実際には「Magenta」に使われるのとまったく同じ色チャンネルを指すことを意味します。データそのものが「緑」か「マゼンタ」かは、チャンネルの名前ではなく、メモリ内の画像の「色空間」によって決まります。同じことが他の色空間でも起こります。例えば「LAB」色空間を使うと、「赤(Red)」チャンネルは「明度(Lightness)」値を、「緑(Green)」チャンネルは「A」(または赤-緑)値を、「青(Blue)」チャンネルは「B」(または青-黄)値を保持します。
同様に、チャンネル名「Alpha」(「A」)、「Opacity」(「O」)、「Matte」は、すべて画像の透明度情報を指す「[-channel](https://imagemagick.org/command-line-options/#channel)」設定の別名です。「アルファ」チャンネルが「マット」チャンネルの反転であることは問題ではなく、それは依然として同じチャンネルを指し、同じ結果、すなわち画像の 内部マットチャンネル を生成します。演算子が内部のアルファチャンネルのデータを「アルファ」値として扱うか否かは、演算子によります。「[-threshold](https://imagemagick.org/command-line-options/#threshold)」のような低レベルのチャンネル演算子は、メモリ内のチャンネルの生の「マット」データに作用します。しかし、「[-fx](https://imagemagick.org/command-line-options/#fx)」や「[-composite](https://imagemagick.org/command-line-options/#composite)」のような、より高レベルなほとんどの演算子は、操作の目的上、そのデータを「アルファ」データを表すものとして扱います。格納された画像データの色空間を制御するもう1つの方法があります。「[-set](https://imagemagick.org/command-line-options/#set) colorspace」(IM v6.4.3-7 で追加)は、メモリ内の「色空間」設定だけを変更します。つまり、画像が使っている実際のピクセルデータを変更したり修正したりすることなく、RGB 画像を HSL 画像に変換できます。この最も典型的な用途は、手動で チャンネルデータを結合する ときに、結合された画像の最終的な色空間を設定する場合です。
では、色チャンネルをどのように操作できるかを見ていきましょう。各チャンネルは単なる値の配列であることを思い出してください。すべてのチャンネルが結合されて、画像内の各ピクセルの実際の色を表すことになります。
チャンネル画像の分離
個々の色チャンネルを分離する最も簡単な方法は、「[-separate](https://imagemagick.org/command-line-options/#separate)」演算子を使って、各チャンネルの現在の内容をグレースケール画像として抽出することです。
magick rose: -channel R -separate separate_red.gif
magick rose: -channel G -separate separate_green.gif
magick rose: -channel B -separate separate_blue.gif
| 赤いバラが赤チャンネル画像で目立つ一方、青と緑のチャンネルではかなり暗くなっていることに注目してください。一方、緑の葉は緑チャンネルで目立ちますが、他のチャンネルでは目立ちません。画像の下の方にある白は、すべてのチャンネルで明るくなっています。 | IM v5 以前では「-channel」は後続の画像操作のための設定であっただけでなく、ときには指定したチャンネルをグレースケール画像に変換する「画像演算子」でもありました。非常に紛らわしい! IM v6 では、これら2つのまったく異なるタスクを「分離(separate)」するために「-separate」が作られました。「-channel」オプションは後続の画像操作で使われる設定にすぎず、「-separate」は指定したチャンネルを別々のグレースケールで完全に不透明な画像に抽出します。 |
|---|---|
IM v6.2.9-3 以降、「-separate」演算子は「-channel」設定に従って複数の色チャンネルを分離できます。「-channel」設定の項目数が、(RGBA の順で)作成される画像の数を決定します。例えば、デフォルトの「-channel」設定は「RGB」なので、デフォルトの動作は3つの画像を作成することです。それを下に出力します。 |
magick rose: -separate separate_RGB_%d.gif
そしてここでは、「-colorspace」演算子を使って、IM が画像の色データを格納する方法を CMYK の色表現 に変換します。それから、関与する4つの色チャンネルを抽出します。
magick rose: -colorspace CMYK -separate separate_CMYK_%d.gif
最後の画像(「Black」または「K」チャンネル)は、元の画像のネガ化されたグレースケール画像のように見えるので特に興味深いものです。実際には、これは CMYK プリンターが紙に塗布すべき「インク」の量を表しており、他の色チャンネルに必要な色の量を減らします。なお、デフォルトでは「-channel」設定は画像の特別な マット透明度チャンネル を含みません。存在するすべてのチャンネルを常に生成したい場合は、「-channel ALL」のチャンネル設定を使うか、「RGBA」または「CMYKA」の「-channel」設定を使えます。
色空間の表現からのグレースケールチャンネル
特別な目的のために、色空間から特定のチャンネル値を抽出できます。例えば、ここでは多くの異なる表現を使って、バラの画像からそのグレースケールの輝度または強度を抽出します。
magick rose: -colorspace Gray channel_gray.gif
magick rose: -grayscale Rec709Luma channel_luma709.gif
magick rose: -grayscale Rec601Luma channel_luma601.gif
magick rose: -colorspace HSI -channel B -separate channel_average.gif
magick rose: -colorspace HSL -channel B -separate channel_lightness.gif
magick rose: -colorspace HSB -channel B -separate channel_brilliance.gif
magick rose: -colorspace CMYK -channel K -negate -separate channel_black.gif
magick rose: -colorspace LAB -channel R -separate channel_lab_light.gif
![[IM Output]](../static/img/color_basics/channel_gray.gif)
Gray
Gray | ![[IM Output]](../static/img/color_basics/channel_luma709.gif)
Rec709Luma
| ![[IM Output]](../static/img/color_basics/channel_luma601.gif)
Rec601Luma (Y)
YUV/YIQ | ![[IM Output]](../static/img/color_basics/channel_average.gif)
Average (I)
HSI/OHTA | ![[IM Output]](../static/img/color_basics/channel_lightness.gif)
Lightness
HSL | ![[IM Output]](../static/img/color_basics/channel_brilliance.gif)
Brightness
HSB | ![[IM Output]](../static/img/color_basics/channel_black.gif)
Neg Black
CMYK | ![[IM Output]](../static/img/color_basics/channel_luma709.gif)
Luminance*
LAB / LUV
---|---|---|---|---|---|---|---
実際の式については、「[-colorspace](https://imagemagick.org/command-line-options/#colorspace)」オプションの公式リファレンスを参照してください。IM v6.7.7 以降、グレースケール画像はメモリ内でも保存時でも、ガンマや sRGB の修正なしで格納されることに注意してください。そのため、このバージョン以前よりも暗くなる傾向があります。なお、「Gray」(「強度(Intensity)」、より正確には「輝度(Luminance)」とも呼ばれる)と、YUV 色空間の「Luma」は等価です。同様に、HSB 色空間の「Brightness」と、CMYK 色空間のネガ化された「黒(blacK)」チャンネルは等価です(そして、グレースケール用途には通常明るすぎます)。LAB(および LUV)色空間の「Lightness」チャンネル(HSL の「Lightness」と混同しないこと)は、人間の視覚的知覚に最もよく一致すると考えられていますが、グレースケール画像の生成には一般的には使われません。なお、グレースケール画像が与えられた場合、すべての色空間のグレースケール画像は、LAB / LUV 色空間の「Lightness」(「R」)チャンネル画像を除いて、入力のグレースケール画像とまったく同じ画像を生成します。
その他のチャンネル分離手法
1つの方法は、分離演算子(Separate Operator) が生成するのとちょうど同じように、1つのチャンネルを他のすべてのチャンネルにコピーしてグレースケール画像を生成することです。単純ですが遅い方法は、FX DIY 演算子 を使うことです。
magick rose: -fx R channel_red.gif
magick rose: -fx G channel_green.gif
magick rose: -fx B channel_blue.gif
これはしばしば理解するのが最も「単純」な解決策とみなされ、他の IM チュートリアルでも使われてきました。他の方法には、不要なチャンネルを「ゼロにする」ためのさまざまな手法の使用が含まれます。これらは下記の 色チャンネルのゼロ化 に挙げられており、通常は「[-fx](https://imagemagick.org/command-line-options/#fx)」を使うよりもはるかに高速です。
RGB チャンネル画像の結合
すべての画像の色チャンネルを分離して処理したら、それらの画像を再び1つに結合し直せる必要もあるでしょう。これは特別なリスト演算子「[-combine](https://imagemagick.org/command-line-options/#combine)」を使って行えます。これは基本的に「-separate」のちょうど逆です。
magick separate_red.gif separate_green.gif separate_blue.gif \
-combine -set colorspace sRGB rose_combined.gif
これらは「[-combine](https://imagemagick.org/command-line-options/#combine)」されて、sRGB 色空間の画像として宣言される画像を作成します。あるユーザーが画像の赤と青のチャンネルを入れ替えられるようにしたいと考えました。これは簡単で、チャンネルを分離し、入れ替え、再結合するだけです。 |
magick rose: -separate -swap 0,2 -combine rose_rb_swap.gif
![[IM Output]](../static/img/color_basics/rose_rb_swap.gif)
デフォルトの「[-channel](https://imagemagick.org/command-line-options/#channel)」設定は「RGB」であり、どのチャンネル画像が結合されるかを定義することを思い出してください。結合されるすべてのチャンネルが定義されていない場合、他のチャンネルは現在の「-background」設定の色値を使って設定されます。ただし、「[-combine](https://imagemagick.org/command-line-options/#combine)」と「-separate」はどちらも、「[-channel](https://imagemagick.org/command-line-options/#channel)」でチャンネルが定義される順序を無視することに注意してください。チャンネルは、「[-channel](https://imagemagick.org/command-line-options/#channel)」設定で設定された各チャンネル組について、常に標準の「Red,Green,Blue,Matte」のチャンネル順で処理・生成されます。したがって、「-channel BR」設定や単に「blue,red」を使ったとしても、「-combine」演算子は依然として最初に赤、次に青の順で画像が並ぶことを期待します。緑とアルファの値(画像が透明度を持つ場合)は、現在の「-background」設定の値から設定されます。例えば...。
magick separate_red.gif separate_blue.gif -background black \
-channel blue,red -combine rose_red_blue.gif
非 RGB チャンネル画像の結合
IM v6.4.3-7 以降、他の色空間を表すチャンネル画像を「[-combine](https://imagemagick.org/command-line-options/#combine)」することもできますが、結果として生成される画像がどの色空間であるべきかを IM に伝える必要があります。これは特別な「[-set](https://imagemagick.org/command-line-options/#set) colorspace」演算子を使って行います。これは基本的に、画像のピクセルデータをマッピングすることなくメモリ内の画像の色空間を変更し、データはそのまま残します。画像が正しい色空間で結合されたら、通常の「[-colorspace](https://imagemagick.org/command-line-options/#colorspace)」演算子を使ってピクセルデータを通常の RGB データに戻すようにマッピングできます。 |
magick separate_HSB_?.gif -set colorspace HSB -combine \
-colorspace sRGB rose_HSB_combined.gif
![[IM Output]](../static/img/color_basics/rose_HSB_combined.gif)
この方法は CMYK 画像でも機能します。CMYK 画像は4番目の色チャンネルが必要なために扱いが難しいことがしばしばあります。 |
magick separate_CMYK_?.gif -set colorspace CMYK -combine \
-colorspace sRGB rose_CMYK_combined.gif
![[IM Output]](../static/img/color_basics/rose_CMYK_combined.gif)
(IM の以前のバージョン向けの)代替の回避策は、1つの画像(赤チャンネル)を読み込み、それを正しい色空間になるように変更することです。その後、個々のチャンネル画像を読み込んで、その事前に準備された画像に チャンネルコピー できます。 |
magick separate_HSB_0.gif -colorspace HSB \
separate_HSB_0.gif -compose CopyRed -composite \
separate_HSB_1.gif -compose CopyGreen -composite \
separate_HSB_2.gif -compose CopyBlue -composite \
-colorspace sRGB rose_HSB_combined_alt.gif
![[IM Output]](../static/img/color_basics/rose_HSB_combined_alt.gif)
もちろん「[-set](https://imagemagick.org/command-line-options/#set) colorspace」操作を使った場合、これは実際のピクセルデータを変更せずデータの解釈の仕方だけを変えるので、最初のチャンネルのデータはすでに所定の位置にあります。 | 最後の例は「CMYK」画像では機能しません。「Black」チャンネル画像は実際には黒チャンネルを含んでいないからです! そのため「-compose CopyBlack」はコピーすべき有効なデータを見つけられず失敗します。私はこれをバグとみなしましたが、現状では修正される見込みは薄いです。
---|---
他の色空間を使うのは便利なことがあります。例えば、ここでは組み込みのバラの画像を取り、「Lab」色空間で画像の輝度チャンネルをネガ化したいとします。終わったら、再結合して再び sRGB 画像を構築します。 |
magick rose: -colorspace Lab -separate \
\( -clone 0 -negate \) -swap 0 +delete \
-combine -set colorspace Lab \
-colorspace sRGB rose_light_neg.gif
![[IM Output]](../static/img/color_basics/rose_light_neg.gif)
| _以前、この例では「HSL」色空間を使っていましたが、それは線形色空間であり、私たちは「Lab」が提供するような「知覚的色空間」でネガ化したいのです。
_
---|---
画像が依然として同じ色を持っているものの、色の明るさ(明度)が反転され、奇妙な効果が生まれていることに注目してください。「-negate」を、画像の明るさのレベルを調整する自分なりの操作の組に置き換えることもできます。ただし、「-negate」自体がチャンネル制御された演算子なので、ネガ化するために輝度チャンネルを「-separate」で分離する必要はありませんでした。 |
magick rose: -colorspace Lab \
-channel R -negate +channel \
-colorspace sRGB rose_light_neg2.gif
![[IM Output]](../static/img/color_basics/rose_light_neg2.gif)
ご覧のとおり、これは物事を単純化しますが、達成したい効果によっては必ずしも実用的でないこともあります。
色チャンネルのゼロ化
ときには、画像(RGB やその他の色空間)があって、色チャンネルの1つか2つだけをクリアまたは「ゼロ化」し、他のすべてのチャンネルはそのまま残したいことがあります。例えば、RGB の グレースケール化手法 を使わずにグレースケール画像を作るには、HSL 色空間で彩度チャンネル(「G」)を「ゼロ化」してグレースケール画像を作れます。彩度がゼロのとき「色相(Hue)」値には意味がないので、グレースケール画像が残ります。最も直接的な手法は、しばしば Evaluate 演算子 を使って不要なチャンネルのすべての値をゼロにすることです。 |
magick rose: -colorspace HSL \
-channel G -evaluate set 0 +channel \
-colorspace sRGB rose_grey.gif
![[IM Output]](../static/img/color_basics/rose_grey.gif)
しかし、これを行う、それほど明白でない方法はたくさんあります。
# Evaluate (高速で直接的)
-channel G -evaluate set 0 +channel
# FX によるゼロ化 (直接的で単純だが遅い)
-channel G -fx 0 +channel
# 残したいチャンネルを分離してから、
# 背景色を使って他のチャンネルを設定して結合する
-channel RB -separate -background black -combine +channel
# ガンマ。これは演算子の誤用だが、非常にうまく機能する!
# ( 1 = そのまま; 0 = チャンネルをゼロ化; -1 = チャンネルを最大化 )
# これは短く単純で、チャンネル設定も不要だが、非常にわかりにくい!
-gamma 1,0,1
# チャンネルをゼロに閾値化する
-channel G -threshold 101% +channel
# 最大値に閾値化してからネガ化してゼロにする
-channel G -threshold -1 -negate +channel
# 適切な原色/二次色との乗算
# 色は保持するチャンネルを指定する! 'magenta' = 'red'+'blue'
\( +clone +level-colors magenta \) -compose multiply -composite
# 特定のチャンネルを黒にカラー化する
# (0 = そのまま; 100% は塗りつぶし(黒)から設定 )
-fill black -colorize 0,100%,0
上記に挙げていない、色チャンネルをゼロ化(または最大化)する別の方法を思いつきますか? -- メールください
色空間
ここまでは「sRGB」「RGB」「CMYK」の色空間に集中してきました。それは、これらが画像の表示・印刷・従来のファイルへの格納に通常使われる色空間だからです。しかし、これらの色空間は実用的ではあるものの、私たち人間が実際に世界をどう見ているかを表すものではありません。私たちの目は赤・緑・青の波長で見るかもしれませんが、私たちの脳はこれらを、色の色相(どんな色か)、灰色さ(どれだけ鮮やかか)、強度(どれだけ明るいか/暗いか)として解釈します。このため、しばしば完全に独立した要求から、多くの色空間や色系が開発されてきました。例えば画家たちは、(ラピスラズリのような色の素材に基づく)色・陰影・着色の系を開発しました。後に RGB を使うコンピューターシステムでは、計算負荷が高くなりすぎない方法で、ユーザーが色を選択・変更するためのよりよい方法が必要になりました。
色相ベースの色空間
おそらく最もよく知られた代替案の1つは、RGB の色のための色選択インターフェースとして開発された、循環的な色相に基づく系です。基本的に、RGB の色立方体を3次元で回転させて、立方体の黒-灰-白の対角軸が色空間の1つの軸になるようにしました。そしてこれが、色がどれだけ暗いか明るいかを指定します。この変更の鍵となる特徴は、RGB 値からの単純な変換で、原色をこの軸の周りに等間隔に配置し、赤から緑、青を経て赤へと循環する色相を形成することでした。色がこの軸から(放射方向に)どれだけ離れているかが、彩度(Saturation)またはクロマ(Chroma)として知られていました。
例えば、組み込みの「rose:」画像を「HSB」(Hue, Saturation, Brilliance。HSV とも呼ばれ、V は Value)色空間に変換した後、そのチャンネルを 分離 してみましょう。
magick rose: -colorspace HSB -separate separate_HSB_%d.gif
あるいは、よく似ているが少し異なる「HSL」(Hue, Saturation, Lightness)です。
magick rose: -colorspace HSL -separate separate_HSL_%d.gif
両方の色空間で「色相(Hue)」チャンネル画像が、ほぼ純粋な黒と白の色の同じまだら模様になっていることに注目してください。それは、色相が実際には循環的だからです。つまり、上記のチャンネル画像での黒と白はどちらも、実際には「赤」の色相を表しており、わずかな変動によって色相が赤の一方の側(白を生成)から他方の側(黒を生成)へ反転します。これが問題なら、Modulate 演算子 を使って色相設定を回転させ、赤が他の色相値で表されるようにできます。「HSL」と「HSB」の本当の違いは、原色の明るさがどう定義されるかです。しかし、これを見るには、カラーホイールを使って色空間のより実用的な表現を見る方がよいでしょう。上記の分離での最後の「明るさ/明度(brightness/lightness)」画像を見ると、「HSB」は強い(原色に近い)「赤」の色をほぼ白として扱う一方、「HSL」はそれをむしろ中間調の灰色の強度のように扱っていることがわかります。
HSL カラーホイールの生成
上記の画像からの生の色の分離は、まだ理解するのが難しいものです。色空間をよりよく理解するには、それを見てみる必要があります。色空間は通常、色空間の一部を示す円形の極座標グラデーションとしてより一般的に表現されます。別々のチャンネル値画像を生成し、それらを 結合 して、他の方法では生成が難しい特定の種類の画像を生成できます。例えば、ここでは完璧な「HSL」カラーホイールを生成します。
magick -size 100x300 gradient: -rotate 90 \
-distort Arc '360 -90.1 50' +repage \
-gravity center -crop 100x100+0+0 +repage angular.png
magick -size 100x100 xc:white solid.png
magick -size 100x100 radial-gradient: -negate radial.png
magick angular.png solid.png radial.png \
-combine -set colorspace HSL \
-colorspace sRGB colorwheel_HSL.png
![[IM Output]](../static/img/color_basics/angular.png)
Hue | ![[IM Output]](../static/img/color_basics/solid.png)
Saturation | ![[IM Output]](../static/img/color_basics/radial.png)
Luminance | | ![[IM Output]](../static/img/color_basics/colorwheel_HSL.png)
HSL カラーホイール
---|---|---|---|---
| _グレースケール画像は sRGB 値を使う線形グラデーションとして生成されています。そのため、グラデーションは本来あるべきよりも少し暗く見える傾向があります。しかし、ここで重要なのは入力画像内の値であって、表示する色空間ではありません。
一方、結果として生成される画像は線形 RGB 色空間で生成されますが、ブラウザーや他の画像表示プログラムが視覚的にうまく機能する形でグラデーションを表示することを保証するために、sRGB 色空間として保存されています。_
---|---
また、色相は「剰余(modulus)」値であり、赤(色相値 = 0)で折り返すことに注意してください。これは画像処理を行うときに厄介なことがあります。視覚的には同一だが、値の上では色相の距離が最大に離れている2つの赤色を持つことになるからです。これは色差に取り組むときに使うのによい色空間ではありません。実は HSB と HSL 色空間の明度/輝度チャンネルは、さまざまな色相が等しく扱われないため、あまり役に立ちません。基本的にこれは原色の強度を「均等化」してしまいます。例えば、「黄色」の色相を回転させて「青」の色相にすると、非常に明るい色が非常に暗くなり、その逆も起こります。詳細は HSL Disadvantages を参照してください。注意が推奨されます。
この同じ「六角錐(hex cone)」ベースの色相系を使う色空間がいくつかあります。HSB、HCL、HCLp(知覚的 HCL)です。これら4つの「六角錐」色空間すべてのカラーホイールがこちらです。
magick angular.png solid.png radial.png \
-combine -set colorspace HSL \
-colorspace sRGB colorwheel_HSL.png
magick angular.png solid.png radial.png \
-combine -set colorspace HSB \
-colorspace sRGB colorwheel_HSB.png
magick angular.png solid.png radial.png \
-combine -set colorspace HCL \
-colorspace sRGB colorwheel_HCL.png
magick angular.png solid.png radial.png \
-combine -set colorspace HCLp \
-colorspace sRGB colorwheel_HCLp.png
![[IM Output]](../static/img/color_basics/colorwheel_HSL.png)
HSL | ![[IM Output]](../static/img/color_basics/colorwheel_HSB.png)
HSB | ![[IM Output]](../static/img/color_basics/colorwheel_HCL.png)
HCL | ![[IM Output]](../static/img/color_basics/colorwheel_HCLp.png)
HCLp
---|---|---|---
上記で示したすべての色は最大の色彩度で生成されていることを思い出してください。ただし「HSB」色空間は原色を最大の明度で生成します(HSL はこれらを半分の強度で生成しました)。このため、白は彩度がゼロのときにのみ生成できます。その結果、縁の周りに白い領域ができる代わりに、完全に飽和した色が得られます。「HCL」色空間は同じ「六角錐」の色相計算を使いますが、直接の線形 RGB 値ではなく色の強度を使うように「明度(lightness)」チャンネルを調整します。その結果、「HCL」を使うと、原色は異なる強度レベルに位置し、青は中央の黒色に近づき、赤色ははるかに明るく外側に位置します。「HCL」色空間の 50% 強度の領域は、強い色を生成せず、代わりにより自然なパステル調の色を生成します。例えば、これは HSL と HCL 色空間における飽和した色相を 50% 強度で比較したものです。
magick -size 100x100 xc:black \
-fill white -draw 'circle 49.5,49.5 40,4' \
-fill black -draw 'circle 49.5,49.5 40,30' \
-alpha copy -channel A -morphology dilate diamond anulus.png
magick hue_angular.png -size 100x100 xc:white xc:gray50 \
-combine -set colorspace HSL -colorspace RGB \
anulus.png -alpha off -compose Multiply -composite \
anulus.png -alpha on -compose DstIn -composite \
-colorspace sRGB hues_HSL.png
magick hue_angular.png -size 100x100 xc:white xc:gray50 \
-combine -set colorspace HCL -colorspace RGB \
anulus.png -alpha off -compose Multiply -composite \
anulus.png -alpha on -compose DstIn -composite \
-colorspace sRGB hues_HCL.png
とはいえ、「HCL」に純粋な色が含まれていないというわけではありません。それらは「HSL」色空間でのように共通の平面に「強制」されていないだけです。特に、HCL のすべての色合いが(要求どおり)同じ 50% 強度を持っているのに対し、HSL 色空間の色相の結果はそうでないことに注目してください。緑はおそらくすべての主要な色の中で 50% 強度に最も近いので、50% の色相でよい応答を示します。画像内のすべての色の全体的な明るさを保つために、色相の回転にはこの色空間を使うことが推奨されます。HCL 色空間での Modulate の例を参照してください。HWB 色空間 ???
知覚的色空間
「Lab」と「Luv」の色空間は、「RGB」や「sRGB」色空間とは異なり、画像のグレースケールの強度を色成分から完全に分離するように設計されています。これにより、コツをつかめば、色空間が全般に処理・変更しやすくなります。より具体的には、「Luv」は「知覚的に線形」になるように設計されました。つまり、色空間のある部分での小さな色の変化が、色空間の別の部分での同様の変化とほぼ同じに見える、ということです。これにより Luv 色空間は画像の差分比較にずっと適したものになります。2つの色空間は非常によく似ており、画像を処理するとき一般に同様の結果を生成します。ここでは、2つの色空間が実際にどれほど似ているかを示すために、「Lab」と「Luv」の色空間のチャンネルを分離します。
magick rose: \( -clone 0 -colorspace LAB -separate +append \) \
\( -clone 0 -colorspace LUV -separate +append \) \
-delete 0 -append -set colorspace sRGB separate_lab_luv.png
Luv
---|---|---|---
「Lab」と「Luv」色空間のより優れた例は、その円柱状の「LCHab」「LCHvu」の変種を使って、下記の LCH カラーホイール で見ることができます。これらの色空間を使う実用的な例については、Lab 色空間でのリサイズ を参照してください。
Lab および Luv ベースの色空間
「HCL」色空間は「LCHuv」色空間に基づいており、これは「Luv」色空間の円柱状の表現ですが、最大の明度で純粋な白を生成するように、明度チャンネルにはより単純な式が使われています。完全を期して、「Lab」と「Luv」色空間の円柱状表現がこちらです。これらはそれぞれ「LCHab」と「LCHuv」として知られています。ただし、チャンネルの順序は、上で示した等価な「HCL」色空間とは逆であることに注意してください。
magick radial.png solid.png angular.png \
-combine -set colorspace LCHab \
-colorspace sRGB colorwheel_LCHab.png
magick radial.png solid.png angular.png \
-combine -set colorspace LCHuv \
-colorspace sRGB colorwheel_LCHuv.png
![[IM Output]](../static/img/color_basics/radial.png)
Lightness* | ![[IM Output]](../static/img/color_basics/solid.png)
Chroma | ![[IM Output]](../static/img/color_basics/angular.png)
Hue | | ![[IM Output]](../static/img/color_basics/colorwheel_LCHab.png)
LCHab | ![[IM Output]](../static/img/color_basics/colorwheel_LCHuv.png)
LCHuv
---|---|---|---|---|---
「LCH」色空間は「LCHab」の別名であることに注意してください。上記で、「LCHuv」には、カラーホイールの処理で非現実的な色が設定される不連続部分があることがわかります。画像の通常の変換ではこれらの色は生成されません。
scRGB ハイダイナミックレンジ色空間
Wikipedia: http://en.wikipedia.org/wiki/ScRGB
これは本質的に、ハイダイナミックレンジの色(負の値や、線形 RGB
の範囲の最大 10 倍まで)を、通常の 16 ビット sRGB 画像の半分の色
解像度で、16 ビット整数に格納する方法です。
16 ビット整数を使っているので、そうした画像を保存できる画像ファイル
形式(PNG、PPM、MIFF)に格納できますが、それらの画像が scRGB 色空間
のデータを保持していることを示すために、カラープロファイルや何らかの
他の方法を使うべきです。
この色空間では、負の数を扱えるようにするための「オフセット」があるため、
多くの画像処理演算子に対して非常に注意が必要です。
リサイズや歪みなど一部の演算子はこの色空間で直接使えますが、より一般的な
画像処理には、HDRI 版の ImageMagick を使い、線形 RGB(負の値あり)に
変換する方がおそらくよい考えです。
_この色空間を使う例ともっと多くの情報があるとよいでしょう_
画像内の色の置換
ImageMagick は当然ながら、特定の色や近いマッチの色を別の色で置き換えるためのオプションをいくつも提供しています。これは、ごく少数の色しか含まないアイコンや「ビットマップ」型の画像を扱うときには優れていますが、色の階調やアンチエイリアスのエッジピクセルを含む画像を扱うときには失敗しがちです。基本的に、色は単一の色合いで置き換えられることを覚えておく必要があります。ですから、色の組や近傍を置き換えると、それらの色すべてが、マッチする色の範囲ではなく、特定の単一の色1つで置き換えられます。だからといって階調のある色の置換が不可能というわけではなく、ただ現時点では多大な労力なしには簡単にできない、というだけです。それでも、GIF 画像は半透明の使用を許可しないので、このように色を置換するのは GIF の背景の透明度を制御するよい方法です(例については 背景パターン上の GIF を参照)。もう1つの側面は、事前定義のカラーマップ を使って、すべての「近い色」を所定のカラーマップにマッピングできる一方、大量の色の組を、まったく異なる別の色の組に直接1対1でマッピングする演算子はないことです。これは将来のバージョンの IM で変わるかもしれない欠点です。その注意点を踏まえつつ、IM が1つの特定の色を別の色で直接置換するために提供する方法を見ていきましょう。
特定の色を置換する
「[-opaque](https://imagemagick.org/command-line-options/#opaque)」と「[-transparent](https://imagemagick.org/command-line-options/#transparent)」演算子は、画像内の1つの色を別の色で置き換えるために設計されています。例えば「blue」の色を「white」で置き換えるには、次のようなコマンドを使います。 |
magick balloon.gif -fill white -opaque blue balloon_white.gif
![[IM Output]](../static/img/color_basics/balloon_white.gif)
基本的に「blue」だった色はすべて、現在の「[-fill](https://imagemagick.org/command-line-options/#fill)」色で置き換えられました。しかし IM v6.2.7 以降、この演算子は「[-channel](https://imagemagick.org/command-line-options/#channel)」設定によって制限されます。そのため、色(例えば青)を透明に変換するには、色を透明にするためにアルファチャンネルを含めるように「[-channel](https://imagemagick.org/command-line-options/#channel)」を指定する必要があります。また、透明度情報を保持するために、画像に「マット」または アルファチャンネル が有効になっていることを確認する必要があります。 |
magick balloon.gif -alpha set -channel RGBA \
-fill none -opaque blue balloon_none.gif
![[IM Output]](../static/img/color_basics/balloon_none.gif)
色を透明で置き換えるのは非常に一般的な操作なので、上記には専用の透明置換演算子「[-transparent](https://imagemagick.org/command-line-options/#transparent)」があります。 |
magick balloon.gif -transparent blue balloon_trans.gif
![[IM Output]](../static/img/color_basics/balloon_trans.gif)
IM バージョン 6.3.7-10 以降、これらの演算子の「プラス」版は色の選択を反転します。つまり、与えられた色にマッチ「しない」色が置き換えられます。例えば、ここでは純粋な黒「でない」色をすべて白で置き換え、画像の純粋な黒の縁だけを残します。 |
magick balloon.gif -fill white +opaque black balloon_borders.gif
![[IM Output]](../static/img/color_basics/balloon_borders.gif)
これは大したことではないように見えるかもしれませんが、ファズ係数(後述)と組み合わせると、これは非常に強力なツールになります。 | IM v6.3.7-10 より前は、反転操作には画像マスクを使ったちょっとした工夫が必要でした。基本的に、保持したい色を透明で置き換え、それから他のすべての色を所望の色に「[-colorize](https://imagemagick.org/command-line-options/#colorize)」してオーバーレイマスクを作成します。これを元の画像の上に重ねて、マッチしなかった色を「マスクアウト」するのです! | |
magick balloon.gif \
\( +clone -alpha set -transparent black \
-fill white -colorize 100% \) \
-composite balloon_mask_non-black.gif
![[IM Output]](../static/img/color_basics/balloon_mask_non-black.gif)
ご覧のとおり、演算子の「プラス」形式は「この色でない」という置換操作を大幅に単純化しました。
より高度な置換手法については、背景の除去 を見ることをお勧めします。 | _すべてのマッチする色(特に「ファジーにマッチした色」、後述)が単一の均一な色で置き換えられるため、色のついた領域のエッジにアンチエイリアスが一切かからないことに注意してください。そして、存在しうるあらゆる影やその他の陰影効果を失うことになります。これは、単純でない、漫画のようでない画像の見た目に深刻な悪影響を及ぼしうります。
この種の色置換は、実際の現実世界の画像を念頭に置いて設計されているのではなく、むしろ画像のマスキング効果のためのものです。注意が推奨されます。_
---|---
「[-opaque](https://imagemagick.org/command-line-options/#opaque)」の色置換は、色をタイル状のパターンで置き換えることはできません。色を別の特定の単一の色で置き換えることしかできません。しかし「[-draw](https://imagemagick.org/command-line-options/#draw)」と「[-floodfill](https://imagemagick.org/command-line-options/#floodfill)」の両方の色置換方法はそれができます(後述)。
画像内の色で置換する
描画による色置換(Draw Color Replacement) を使って、特定の色ではなく、画像自体に存在する色に基づいて画像の色を変えることもできます。 |
magick present.gif -fill red -draw 'color 0,0 replace' present_blue.gif
![[IM Output]](../static/img/color_basics/present_blue.gif)
置き換えるべき色を指定したのではなく、置き換えるべき色の位置だけを指定したことに注目してください。どの領域を塗りつぶすかを「マッチ」させるために使われるのは、その位置にある色であり、それがどんな色であるかにかかわらずです。上記の例で色置換の問題が見て取れます。特定の色は、意図したのとは別の場所にも現れることがあり、上記の「present」画像の中に赤いピクセルの線ができてしまっています。透明度も問題になりませんが、上記で赤くなったのと同じように、画像の一部の内部も透明になってしまいました。 |
magick present.gif -alpha set -fill none \
-draw 'color 0,0 replace' present_none.gif
![[IM Output]](../static/img/color_basics/present_none.gif)
ただし、「[-opaque](https://imagemagick.org/command-line-options/#opaque)」や「[-transparent](https://imagemagick.org/command-line-options/#transparent)」とは異なり、描画による色置換 では、置き換える「マッチする色」を反転させることはできないことに注意してください。Draw には特別な マット置換(Matte Replacement) もあり、塗りつぶし色の透明度だけが置き換えられます。つまり、ピクセルそのものの色を実際に変えることなく、すべてのマッチする色を透明または半透明にできます。もちろん、適切なファイル形式が必要です。 |
magick present.gif -alpha set -fill '#00000080' \
-draw 'matte 0,0 replace' present_semi.png
![[IM Output]](../static/img/color_basics/present_semi.png)
これは ファズ係数 も指定されているときに、はるかに有用になります。「[-draw](https://imagemagick.org/command-line-options/#draw)」を使う最大の利点は、色をタイルパターンで置き換えることもできることです。例えば...。 |
magick present.gif -tile pattern:right30 \
-draw 'color 0,0 replace' present_tile.gif
![[IM Output]](../static/img/color_basics/present_tile.gif)
より高度な置換手法については、背景の除去 を見ることをお勧めします。
塗りつぶし描画 (Floodfill Draw)
描画色(Draw Color) の方法は、「塗りつぶし(floodfilling)」によって色を置き換える簡単な方法も提供します。つまり、画像内のすべてのマッチする色を置き換えるのではなく、画像内の指定した点に「接続されている」または「付着している」色だけを選択できます。指定した点は、開始点(シードポイント)を指定するだけでなく、置き換えようとしている色も指定します。 |
magick present.gif -fill red -draw 'color 0,0 floodfill' present_fill.gif
![[IM Output]](../static/img/color_basics/present_fill.gif)
0,0 のピクセルに「付着して」いなかった赤い領域は置き換えられなかったことに注目してください。背景の置換ではこれが問題になることがありますが、解決策も同じくらい簡単です。画像を少し拡張して塗りつぶしがあらゆる方向から画像に「漏れ込める」ようにし、終わったらその余分なスペースを削除します。 |
magick present.gif -bordercolor white -border 1x1 \
-fill red -draw 'color 0,0 floodfill' \
-shave 1x1 present_bgnd.gif
![[IM Output]](../static/img/color_basics/present_bgnd.gif)
もちろん、下記の ファズ係数 の制御設定を使って、どの色が「マッチ」するかを調整できます。これは JPEG 画像に対して特に重要です。
塗りつぶし演算子 (Floodfill Operator)
「[-floodfill](https://imagemagick.org/command-line-options/#floodfill)」演算子は、特に置き換えたい色を正確に指定したい場合に、塗りつぶしをわずかに簡単にするために追加されました。これは ファズ係数 の色マッチングを使うときに特に重要になりえます。ただし、そのシードポイントが探している色の ファズ係数 のマッチ範囲内になければ、「[-floodfill](https://imagemagick.org/command-line-options/#floodfill)」は何もしないことに注意してください。これは演算子の機能であると同時に、その難点ともみなせます。
塗りつぶしには小さな ファズ係数 が推奨されます。
あるいは、シードポイントが探している色に正確にマッチすることを確認してください。
例えば、既知の色の縁を追加して、エッジから塗りつぶします。 |
magick present.gif -bordercolor white -border 1x1 \
-fill red -floodfill +0+0 white \
-shave 1x1 present_floodfill.gif
![[IM Output]](../static/img/color_basics/present_floodfill.gif)
これは、+0+0 から始まるシードピクセルを取り囲む領域の直接の一部であり、追加した縁のために「白」であることが保証されている「白」の色をすべて「赤」に置き換えます。タイルパターンで塗りつぶすこともできます。 |
magick present.gif -bordercolor white -border 1x1 \
-tile pattern:left30 -floodfill +0+0 white \
-shave 1x1 present_pattern.gif
![[IM Output]](../static/img/color_basics/present_pattern.gif)
「color」引数はときに厄介なことがあります。シードポイントの色とマッチしなければ、何の動作も起こらないからです。しかし、これは塗りつぶしが予期しないことではなく、あなたが望んだことを正確に行うことを保証するので、有用なこともあります。例えば、ここでは白い円盤をさまざまな色で塗りつぶそうとします。 |
magick disks.gif \
-fill Red -floodfill +30+50 white \
-fill Green -floodfill +60+60 white \
-fill Blue -floodfill +10+40 white \
floodfill_hit_miss.gif
![[IM Output]](../static/img/color_basics/floodfill_hit_miss.gif)
この場合、「Green」と「Blue」の塗りつぶし操作だけが「円盤に当たり」(そしてそれを塗りつぶし)、一方「Red」の塗りつぶしは円盤にマッチしなかったので、画像の背景を誤って塗りつぶすことなく、どの円盤も塗りつぶされませんでした。これはまた、すでに特定の領域を塗りつぶしている場合、後の塗りつぶしは、2 つの点がその領域に当たっても、同じ領域を「再塗りつぶし」しないことも意味します。これは多くの時間を節約できます。画像内の複数の「シード」点からのより低レベルの塗りつぶし操作を表す 条件付き膨張(Conditional Dilation) も見てみるとよいでしょう。
ファズ係数 — 類似/複数の色のマッチング
これまでの例で示したように、置き換える単一の色を選ぶだけの全体的な結果は、通常あまり良いものではありません。単色の領域の縁やエッジは、アンチエイリアス(詳細は アンチエイリアス を参照)のために、一般にエッジに色の混合があります。そのため、可能であれば直接の色置換は避けるべきです。例えば、ここでは単純な白黒の「牛」のように見えるものを取り、赤い牛にしようとします。
magick cow.gif -fill red -opaque black cow_replace_red.gif
ご覧のとおり、「黒」の領域の中心部分だけが実際に赤くなりました。それは、画像が白黒に見えても、実際にはほとんどすべての縁がさまざまな灰色の色合いになっているグレースケール画像だからです。つまり、それらは正確には純粋な黒色ではありません。ファズ係数(「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」)は、画像が使っているどの色空間であっても、色どうしの多次元の球面距離における「類似性」のマッチを表します。さて、これを平易な言葉で言ってみましょう。特定の色があります。別の色は、これらの色の差がファズ係数の設定値より小さければ、探している色と 同じ として扱われます。「ファズ係数」が大きいほど、より多くの「近い」色がマッチして置き換えられます。では、牛の画像でこれを試して、純粋な黒だけでなく、黒に近い色も赤に変換してみましょう。
magick cow.gif -fuzz 40% -fill red -opaque black cow_replace_fuzz.gif
ご覧のとおり、今度は画像の「暗い」ピクセルすべてを赤に置き換えました。しかし結果は依然として非常に悪く、縁に灰色がかった色合いと、強い エイリアシング効果 があります。直接の色置換は、大きな「ファズ係数」を使えば機能させられるとはいえ、この画像にはよい解決策ではありません。この画像の理想的な解決策については、色によるレベル調整 の例を参照してください。この問題は、背景色を透明で置き換えようとしている画像では、さらに悪化します。基本的に、その背景色上のオブジェクトの周りに「ハロー」ができてしまいます。これは解決が非常に難しく、このような問題は 背景の除去 で詳しく扱われています。どの操作がファズ係数を使うか 「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」演算子は、画像内の特定の色を比較するほぼすべての演算子に影響します。これには次が含まれます。「[-opaque](https://imagemagick.org/command-line-options/#opaque)」「[-transparent](https://imagemagick.org/command-line-options/#transparent)」「[-floodfill](https://imagemagick.org/command-line-options/#floodfill)」「[-trim](https://imagemagick.org/command-line-options/#trim)」「[-deconstruct](https://imagemagick.org/command-line-options/#deconstruct)」「[-draw](https://imagemagick.org/command-line-options/#draw) 'color'」「[-draw](https://imagemagick.org/command-line-options/#draw) 'matte'」、そしておそらく他にもあります。また、GIF の「[-layers](https://imagemagick.org/command-line-options/#layers) [OptimizeTransparency](anim_opt.html#opt_trans)」や「[-compose](https://imagemagick.org/command-line-options/#compose) [ChangeMask](compose.html#changemask)」の処理にも影響します。さらに、「magick compare」の結果、具体的には「[-metric](https://imagemagick.org/command-line-options/#metric) AE」すなわち絶対誤差ピクセル数(Absolute Error Pixel Count)にも影響します。
ファズ係数の距離
「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」設定は、実際には色の「距離」設定の一種です。探している色から与えられた距離以内にある色は、たとえ正確なマッチでなくても、その色とマッチします。値「200」は、使われている IM の現在の色深度における 200 色単位の距離を表します。IM Q16(16 ビット品質 の色格納)の場合これはかなり小さく、IM Q8 の場合これは非常に大きく、多くの色が互いにマッチする原因になります。 例えば、ここでは「blue」から(IM Q16 で)30,000 色単位以内のすべての色を白に変更します。私の Q16 の ImageMagick プログラムでは、これはおおよそ「blue」から「navy」(半分の暗い青)までの距離を表します。 |
magick colorwheel.png \
-fuzz 30000 -fill white -opaque blue \
opaque_blue.jpg
![[IM Output]](../static/img/color_basics/opaque_blue.jpg)
これを理解しやすくするために、ここではマッチした色を反転させ、マッチしなかった色を白にします。 |
magick colorwheel.png \
-fuzz 30000 -fill white +opaque blue \
opaque_blue_not.png
![[IM Output]](../static/img/color_basics/opaque_blue_not.png)
あなたの IM が、「[-opaque](https://imagemagick.org/command-line-options/#opaque)」演算子の「プラス」形式が追加されたバージョン 6.3.7-10 より古い場合、このマスキングの方法を使って色マッチの結果を反転できます。 |
magick colorwheel.png \
\( +clone -fuzz 30000 -transparent blue \
-channel RGB +level-colors white +channel \) \
-composite opaque_blue_inv.png
![[IM Output]](../static/img/color_basics/opaque_blue_inv.png)
あるいは、すべての変更を「アルファチャンネル」だけに限定し、元の色をすべてそのまま残すこの方法もあります。つまり、色の選択からネガ化されたマスクを作成して、選択されなかった色をすべて完全に透明にします。それらは依然として存在し、ただ透明なだけです! |
magick colorwheel.png -fuzz 30000 -transparent blue \
-channel A -negate +channel opaque_blue_inv_alpha.png
![[IM Output]](../static/img/color_basics/opaque_blue_inv_alpha.png)
これらの代替方法の利点は、それらを拡張して「複数の色でない」という手法を生成できることです。必要なのは、マスクをネガ化する前に、透明にする色のリストにさらに色を追加し、場合によってはネガ化された透明度を除去することだけです。 |
magick colorwheel.png \
-fuzz 25000 -transparent blue -transparent red -transparent lime \
-channel A -negate +channel \
-background white -alpha remove opaque_multi_inv.png
| _興味深いことに、Q8 のコンパイル設定の IM では、256 (28) の「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」係数で、色「black」と「blue」が等価になります。Q16 設定の IM では、この数は 65536 (216) です。
「blue」と「red」の色をマッチさせるには、この数を 2 の平方根、すなわち IM Q8 では 362、IM Q16 では 92682 を掛けなければなりません。
すべての色をマッチさせる(例えば色「black」と「white」)には、3 の平方根を掛ける必要があります。言い換えれば、ファズ係数の設定は IM Q8 で 444、IM Q16 で 113512 です。
---|---
| 「LAB」や「LUV」のような「知覚的」色空間を使えば、おそらくより優れた、より現実的な色の距離を定義できるでしょう。ファジーな色マッチングを行う前に、画像をその色空間に変換するだけです。これにより、純粋な青と黒のような色が、「sRGB」や「線形 RGB」色空間よりもずっと近くなり、黄色と白も近くなります。_
---|---
上記の式からわかるように、直接の色距離は、使うファズ係数を設定するのに決して良い方法ではありません。どのコンパイル時の 品質設定 が使われているかにも依存するからです。「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」係数をパーセンテージとして設定すると、その使用がずっと単純になります。この場合、「100%」はすべての色をカバーするのに十分な大きさのファズ係数を表します。つまり、RGB 色立方体の 3 次元の対角線を横切る「black」から「white」までの色距離を表します。 ここでは、白から黒までの距離の 90% 以内のすべての色を白で置き換えます。これにより、黒は RGB 色立方体の反対側にあるので、画像には「black」に近い最後の 10% の色だけが残るはずです。 |
magick colorwheel.png -fuzz 90% -fill white -opaque white opaque_w90.jpg
![[IM Output]](../static/img/color_basics/opaque_w90.jpg)
この 90% は、RGB 色立方体内の「白」の周りの色の球を表すことに注意してください。しかし、これは黒の 10% の球内にない色を置き換えるのとは同じではありません。 |
magick colorwheel.png -fuzz 10% -fill white +opaque black opaque_k10.jpg
ご覧のとおり、黒に近い色の 10% の球は、白の周りの色の 90% の球を選択するよりもはるかに均一です。立方体の白の角を中心とした大きな球がその立方体をどう満たすかを考えてみてください。それから、黒の角を中心とした小さな球を考えれば、2 つの画像の違いを理解できるでしょう。 ![[IM Output]](../static/img/color_basics/opaque_k10.jpg)
| _「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」係数 100% は、RGB 色立方体の「black」から「white」までの距離に相当します。これから、おおよそ 57.7% のパーセンテージが「black」と「blue」の間の距離であり、81.6% が「blue」から「red」、あるいはそれらいずれかの色から「white」までの距離であると計算できます。
要約すると、おおよそ 25%(「blue」から「navy blue」までの RGB 距離にわずかに満たない)より大きいものは、非常に大きな色の変化を表します。_
---|---
色の距離をさらに示すために、青色の周りで徐々に大きくしたファズ係数のパーセンテージを使ってみましょう。
magick colorwheel.png -fuzz 10% -fill white -opaque blue opaque_b10.jpg
magick colorwheel.png -fuzz 25% -fill white -opaque blue opaque_b25.jpg
magick colorwheel.png -fuzz 57% -fill white -opaque blue opaque_b57.jpg
magick colorwheel.png -fuzz 81% -fill white -opaque blue opaque_b81.jpg
magick colorwheel.png -fuzz 95% -fill white -opaque blue opaque_b95.jpg
これから、「blue」から最も遠い色は「black」でも「white」でもなく、実は RGB 色空間内で最も遠いのは「yellow」であることがはっきりとわかります。また、81% の色差では純粋な「red」の色のマッチをちょうど逃しますが、純粋な赤は他の赤とはマッチしないものの、(オレンジ-赤の色を除いた)赤はマッチすることにも注目してください。これも、色マッチの「球面的」な性質によるものです。教訓は、おそらく単一の大きな値よりも、複数の小さな「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」係数のマッチか、より小さな「反転マッチ」を使う方がよい、ということです。ここでは、画像内の色を別の色、すなわち「ほぼ完璧な灰色」の色と比較し、「ファズ係数」が増えるにつれて、類似の色をその同じ灰色の色に変更します。
magick colorwheel.png -fuzz 25% -fill gray50 -opaque gray50 opaque_g25.jpg
magick colorwheel.png -fuzz 30% -fill gray50 -opaque gray50 opaque_g30.jpg
magick colorwheel.png -fuzz 35% -fill gray50 -opaque gray50 opaque_g35.jpg
magick colorwheel.png -fuzz 45% -fill gray50 -opaque gray50 opaque_g45.jpg
magick colorwheel.png -fuzz 51% -fill gray50 -opaque gray50 opaque_g51.jpg
ご覧のとおり、カラーホイール画像の色は 30% のちょうど手前のファズ係数でようやくマッチし始め、45% で最も極端な色を除くすべてが消えるまで徐々に増えていきます。51% までに、画像内のすべての色がほぼ完璧な灰色にマッチしました。あなたが見ているのは、RGB の色が 3 次元空間で立方体に配置される仕方の結果です。しかし「カラーホイール」画像には「完全に飽和した色」、つまり RGB 色立方体の外側の面に位置するすべての極端な色しか含まれていません。一方、完璧な灰色は立方体の中心に位置し、すべての「飽和した色」からかなり離れています。そのため、立方体の面の中央の色がマッチし始めるのは、28% という大きなファズ係数に達してからです。ファズ係数が大きくなるにつれて、ますます多くの色がマッチし、色立方体の極端な角の色だけが残るようになります。およそ 50% で、角の色もマッチし始め、そして 51% ではすべての不透明な RGB 色がマッチしてしまいます。
ファズ係数と透明色
「[-fuzz](https://imagemagick.org/command-line-options/#fuzz)」係数を使うと、マッチングに透明色や半透明色が関わるとき、より複雑になります。例えば、ここでは画像を横切って黒と白の間のグラデーションを作成し、それから垂直方向に透明のグラデーションを追加します。それから、完璧な灰色の色(すなわち 50% グレー)のファジーな色マッチを行います。後続の画像では、完全に透明になるまでマッチさせる色をより透明にしていきますが、ファズ係数 は一定の 20% のままです。
magick -size 100x100 gradient: \( +clone -rotate 90 \) +swap \
-compose CopyOpacity -composite trans_gradient.png
magick trans_gradient.png -channel RGBA \
-fuzz 20% -fill Gray50 -opaque 'GrayA(50%,1.0)' fuzz_trans_100.png
magick trans_gradient.png -channel RGBA \
-fuzz 20% -fill Gray50 -opaque 'GrayA(50%,.75)' fuzz_trans_75.png
magick trans_gradient.png -channel RGBA \
-fuzz 20% -fill Gray50 -opaque 'GrayA(50%,.40)' fuzz_trans_40.png
magick trans_gradient.png -channel RGBA \
-fuzz 20% -fill Gray50 -opaque 'GrayA(50%,0.0)' fuzz_trans_00.png
上記での「-channel RGBA」の使用は色マッチングのためではなく、「塗りつぶす」べき色チャンネルを指定するためであることに注意してください。つまり、それがないと、上記は同じ色をマッチさせはしますが、灰色の「塗りつぶし」は半透明のままになり、不透明な灰色の色には設定されません。透明度にかかわらずすべての色をマッチさせたい場合は、画像の 透明チャンネルをオフにする 必要があります(少なくとも一時的に)。あとでまたオンに戻せますが、その場合は塗りつぶし色が再び元の色と同じ透明度を持つことになります。完全に不透明な灰色の色(alpha=「1.0」)でマッチさせた最初の画像では、不透明に近い灰色の色すべての、非常に球面的なマッチが得られます。しかし、マッチさせる色がより半透明になるにつれて、マッチする半透明の色の数はより大きくなるように見え、ついには完全に透明な灰色が、透明に近いどの色ともマッチするようになります。何が起きているかというと、透明度が増すにつれて、半透明の色どうしの距離が減少するのです。2 つの色が透明であるほど、その不透明な対応物に比べて、色どうしが近くなります。両方の色が完全に透明なとき、2 つの色は完璧な、すなわち「0」の距離のマッチとみなされます。もう 1 つ気づくことは、(IM v6.6.6-4 以降)完全に透明な色(灰色でもそれ以外でも)からの距離は、純粋に色の透明度(アルファ値)の関数だということです。上記の最後の画像は、実際の色にかかわらず、完全に透明であることから 20% 以内のすべてのピクセルをマッチさせました。 これはまた、完全に透明な色(「none」など)を伴う大きな ファズ係数 を使って、すべて、またはほぼすべての半透明の色をマッチさせられることも意味します。例えば...。 |
magick trans_gradient.png -channel RGBA \
-fuzz 95% -fill Gray50 -opaque None \
-alpha off fuzz_trans.jpg
![[IM Output]](../static/img/color_basics/fuzz_trans.jpg)
上記では、不透明に近い色の上位 5% だけがマッチせず、一方で他のすべての半透明の色は灰色に変わったことに注目してください。最後の「[-alpha](https://imagemagick.org/command-line-options/#alpha) off」は、画像から半透明性の最後の名残を取り除きます。このため、「[-channel](https://imagemagick.org/command-line-options/#channel) RGBA」設定は実際には必要ありませんが、完全を期して推奨されます。この例は本質的に、(透明な色を灰色にするために)灰色の下地を加える前の、アルファチャンネルの閾値化に相当します。 | IM v6.6.6-4 より前は、ファジーな色マッチングは完全に透明な色と不透明な色を等しくマッチさせませんでした。実際、黒の方が白よりずっと近いマッチでした。そのため、最後の例は失敗します。詳細は ファズ距離と透明色のバグ を参照してください。
---|---
| さらにひどいことに、IM v6.2.6-2 より前は、ファジーな色マッチングはすべての完全に透明な色を同じ色とはみなしませんでした。つまり、完全に透明な黒(「None」とも呼ばれる)は、両方とも完全に透明であるにもかかわらず、完全に透明な白(または色「#FFF0」)と同じではありませんでした。
---|---
工事中
色の演算(2 つ以上の色の平均を取る)....
例 2 つの色の平均... 例えば '#000000' と '#DDDDDD'
一般に色は画像に追加され、結果は単一のピクセルの 'txt:-' 画像として
出力され、そこから色を抽出できます。
* -resize を使って色をマージする
magick -size 2x1 xc:'#000000' -fill '#DDDDDD' \
-draw 'point 0,0' -resize 1x1 txt:-
* それらに -evaluate-sequence mean を使う!
magick -size 1x1 xc:'#000000' xc:'#DDDDDD' \
-evaluate-sequence mean txt:-
あるいは大量の色には 'Box' リサイズフィルターを使える
magick rose: -filter Box -resize 1x1\! txt:
# ImageMagick pixel enumeration: 1,1,255,RGB
0,0: (145, 89, 80) #915950
* -fx を使って、好きな式を何でも適用する
magick -size 1x1 xc:'#000000' xc:'#DDDDDD' \
-fx '(u+v)/2' txt:-
ImageMagick API を使えば、結果を画像からより直接的に取得できます。
![[IM Output]](../static/img/color_basics/colorspace_RGB.png)
![[IM Output]](../static/img/color_basics/colorspace_LUV.png)
![[IM Output]](../static/img/color_basics/colorspace_LAB.png)
![[IM Output]](../static/img/color_basics/color_hex_1.png)
![[IM Output]](../static/img/color_basics/color_hex_2.png)
![[IM Output]](../static/img/color_basics/color_hex_3.png)
![[IM Output]](../static/img/color_basics/color_hex_4.png)
![[IM Output]](../static/img/color_basics/color_hex_5.png)
![[IM Output]](../static/img/color_basics/color_hex_6.png)
![[IM Output]](../static/img/color_basics/color_rgba_1.png)
![[IM Output]](../static/img/color_basics/color_rgba_2.png)
![[IM Output]](../static/img/color_basics/color_rgba_3.png)
![[IM Output]](../static/img/color_basics/color_rgba_4.png)
![[IM Output]](../static/img/color_basics/color_rgba_5.png)
![[IM Output]](../static/img/color_basics/color_rgba_6.png)
![[IM Output]](../static/img/color_basics/color_name_1.png)
![[IM Output]](../static/img/color_basics/color_name_2.png)
![[IM Output]](../static/img/color_basics/color_name_3.png)
![[IM Output]](../static/img/color_basics/color_name_4.png)
![[IM Output]](../static/img/color_basics/color_name_5.png)
![[IM Output]](../static/img/color_basics/color_name_6.png)
![[IM Output]](../static/img/color_basics/separate_red.gif)
![[IM Output]](../static/img/color_basics/separate_green.gif)
![[IM Output]](../static/img/color_basics/separate_blue.gif)
![[IM Output]](../static/img/color_basics/channel_red.gif)
![[IM Output]](../static/img/color_basics/channel_green.gif)
![[IM Output]](../static/img/color_basics/channel_blue.gif)
![[IM Output]](../static/img/color_basics/rose_combined.gif)
![[IM Output]](../static/img/color_basics/rose_red_blue.gif)
![[IM Output]](../static/img/color_basics/separate_HSB_0.gif)
![[IM Output]](../static/img/color_basics/separate_HSB_1.gif)
![[IM Output]](../static/img/color_basics/separate_HSB_2.gif)
![[IM Output]](../static/img/color_basics/separate_HSL_0.gif)
![[IM Output]](../static/img/color_basics/separate_HSL_1.gif)
![[IM Output]](../static/img/color_basics/separate_HSL_2.gif)
![[IM Output]](../static/img/color_basics/hues_HSL.png)
![[IM Output]](../static/img/color_basics/hues_HCL.png)
![[IM Output]](../static/img/color_basics/separate_lab_luv.png)
![[IM Output]](../static/img/images/cow.gif)
![[IM Output]](../static/img/color_basics/cow_replace_red.gif)
![[IM Output]](../static/img/color_basics/cow_replace_fuzz.gif)
![[IM Output]](../static/img/color_basics/opaque_multi_inv.png)
![[IM Output]](../static/img/color_basics/opaque_b10.jpg)
![[IM Output]](../static/img/color_basics/opaque_b25.jpg)
![[IM Output]](../static/img/color_basics/opaque_b57.jpg)
![[IM Output]](../static/img/color_basics/opaque_b81.jpg)
![[IM Output]](../static/img/color_basics/opaque_b95.jpg)
![[IM Output]](../static/img/color_basics/opaque_g25.jpg)
![[IM Output]](../static/img/color_basics/opaque_g30.jpg)
![[IM Output]](../static/img/color_basics/opaque_g35.jpg)
![[IM Output]](../static/img/color_basics/opaque_g45.jpg)
![[IM Output]](../static/img/color_basics/opaque_g51.jpg)
![[IM Output]](../static/img/color_basics/trans_gradient.png)
![[IM Output]](../static/img/color_basics/fuzz_trans_100.png)
![[IM Output]](../static/img/color_basics/fuzz_trans_75.png)
![[IM Output]](../static/img/color_basics/fuzz_trans_40.png)
![[IM Output]](../static/img/color_basics/fuzz_trans_00.png)