アルファサード株式会社 代表取締役 野田 純生のブログ


ColorTesterはどうやって画像の色を拾っているのか。


公開日 : 2014-09-04 14:57:50


昨日公開したColorTester、もうお試しいただけましたでしょうか? JIS X-8341-3適合の試験なんかをやっている方は是非お試しください。

ColorTesterスクリーンショット のサムネイル

同様のチェックを行えるツールとして、Colour Contrast Analyser (CCA) というソフトウェアがあります(有名ですね)。

もちろん、既にチェックソフトがあるのに作ったのにはわけがあるのですが、それはそれとして、せっかくなのでメモがてらに色の判別方法について記載しておきます。

W3Cのコントラスト計算アルゴリズム

達成評価についてはW3C(WCAG 2.0)の計算式そのままです。もう、コピペの世界ですね。

検証

チェックポイント

  1. 以下の公式を用いて、各文字(すべて同一ではない限り)の相対輝度を測る:

    • 色の相対輝度 L = 0.2126 * R + 0.7152 * G + 0.0722 * B と定義されている。この場合のR, G 及び B は:

      • RsRGB <= 0.03928 の場合:R = RsRGB/12.92、それ以外の場合: R = ((RsRGB+0.055)/1.055) ^ 2.4

      • GsRGB <= 0.03928 の場合:G = GsRGB/12.92、それ以外の場合:G = ((GsRGB+0.055)/1.055) ^ 2.4

      • BsRGB <= 0.03928 の場合:B = BsRGB/12.92、それ以外の場合:B = ((BsRGB+0.055)/1.055) ^ 2.4

      また、RsRGB, GsRGB, 及び BsRGBは以下のように定義される:

      • RsRGB = R8bit/255

      • GsRGB = G8bit/255

      • BsRGB = B8bit/255

      "^"記号は指数演算子である。

    注意:エイリアス文字では文字の端から2ピクセルの部分の相対輝度の値を使用する。

  2. 同じ公式を用いて、文字のすぐ隣の背景のピクセルの相対輝度を測る。

  3. 次の公式を用いて、コントラスト比を算出する。

    • (L1 + 0.05) / (L2 + 0.05)

      • L1は前景または背景色の明るい方の相対輝度である。及び、

      • L2は前景または背景色の暗い方の相対輝度である。

  4. コントラスト比が4.5:1と同じ、又はそれ以上である。【訳注:この計算式を用いているチェックツールで、コントラスト比が4.5:1以上であることを確認すればよい。】

Colour Contrast Analyserについて特に不満がある訳ではないのですが、以下ことは思っていました。

  • OS X版ではOS標準のカラーピッカーを使うため、カラーピッカーを起動してからディスプレイの色選択まで、1アクション多い(Windows版では直接色を拾えるようになっています)
  • 画像から直接色を拾えないものか。その方が絶対楽だし、大量の画像を一点ずつ色選択してチェックって、数万ページの案件のチェックとかだと現実的に膨大な作業量になる

ColorTesterも標準設定ではOS標準のカラーピッカーを使うようになっていますが、設定→「OS標準のカラーピッカーを使う」チェックボックスをOffにすることで、直接画面から色を拾えるようになります。今のところマルチディスプレイには非対応であることと、Windows版では画面の解像度設定によってうまく色が拾えないことがあります。その場合Colour Contrast Analyserでもずれるんですよね。うまく拾えない場合、Colour Contrast Analyserでもカーソル位置からずれてしまう場合は、画面解像度の設定を変更して試してみてください。

お試しいただけるとわかるかと思うのですが、ブラウザからのドロップやファイルドロップでの色取得、それなりにうまく取得できているように思いませんか? でも、ドキュメントにも書いていますし最初の自動判別時にダイアログが出ることからもお分かりの通り、自動取得した色は正確ではない可能性があります。

色選択の際に最初に表示されるダイアログ

そもそも、2色しか拾えない訳ですから、前景色や背景色が明らかに複数の色で構成されている画像などでは取得に失敗します。明らかに拾い間違っているように見えるときは、あきらめてカラーピッカーから直接色を拾ってください。

ColorTesterはどうやって画像の背景色と前景色を判別しているのか

さて、本題です。
実際、トライ & エラーを繰り返しながら調整していったということなのですが、結果的に現在のバージョンでは以下のような考え方、アルゴリズムで判別を行っています。

  1. 一定以上の大きさの画像は画像サイズを小さくする(処理速度の問題)
  2. 近似色を丸める(グラデーションなどが用いられていると、不必要に色の数が多くなり判別が難しくなる)
  3. 画像のピクセルのカラーを調べて、どの色が何ピクセルを占めているかを調べる(keyに色(16進)、valueにピクセル数という形でマッピングしていきます)
  4. 一番面積の大きい画像が、背景色(これは、ほぼ問題ないかと思います)
  5. 問題は前景色です。まずは、二番目に面積が大きい色を前景色と仮定します。
  6. 背景色と、仮定した前景色のコントラスト差を求めます。これは、W3Cの計算式をそのまま使っています。
  7. コントラストの差が大きい場合(3以上としました)、仮定した前景色で決定です。
  8. コントラストが3以下の場合、面積の大きい順から色を調べて行き、一定のコントラスト差がある色を探します。但し、一定のピクセル以下の面積のもの(1ピクセルがその色だったとして、それが前景色ってことはないでしょう)は除きます。

というわけで上記の処理の結果、背景色と前景色を推測しているというわけです。色を丸めている点で、これはあくまでも近似色である、という見方もできるかと思いますが、どのみちディスプレイの色ってのはデリケートな要素が絡むものです。MacとWindowsでも違う値になるものがあります。Webセーフカラー! 何という懐かしい言葉の響き。ColorTesterでは16進の入力フィールドの背景色に取得した色セットしますから、試験の際に、もし自分の感覚とずれていたら念のためピクセルから取得した色で再チェックをお願いします。

その他のアイデア

正確さもさることながら、いかに効率よく背景色と前景色を判別するか、実装を考える上でいくつかのアイデアを試しました。

中央の1ピクセルを横になめていってはどうか?

上下中央のピクセルをなめる

横書きなら、これは有効なんですけどね。縦書きの画像だと、拾い損ねる可能性がありました。こんな画像だったらいいんですけどね。

斜めではどうか?

斜めにピクセルをなめる

縦書きでも横書きでも、これならクリアできそうですね。ただ、背景色についてはグラデーションかかってたりすると正確に取得できないのですね。また、上下左右の余白が広い場合にうまく行きません。もちろん、こんなべた塗り前景色一色の画像なら判別できるのですが。

他にも、隣接しているかどうかを判断基準に加えたり、ノイズを除去したりといったことも考えられますが、少なくとも「画像化された文字」の判別に特化するなら、あまり気にしなくても良いようです。 まぁ、単純にこういうのって面白いです。良いアイデアや良いアルゴリズムがあれば教えてください。



このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の創業者であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ