見出し画像

[Swift(iOSアプリ開発)]CIFilterの使い分け――CIKmeans編

画像処理初心者によるCIFilterについて調べた結果のまとめです。
第三回はCIPalettizeの説明で名前が出てきたCIKMeansについて動作を確認しました。

CIKMeansフィルターの概要

CIKMeans(CICategoryReductionカテゴリ)

画像の中で最もよく見かける色のパレットを作成します。

パラメータ
 - inputExtent: 効果の範囲を定義する矩形。
 - inputCount: 使用するk平均カラークラスタの数を指定します。
 - inputMeans: k-meansクラスタリングに使用する色の種を指定します。
 - inputPasses: k-meansパスを何回実行するかを指定します。
 - inputPerceptual: k-meansカラーパレットを知覚色空間で計算するかどうかを指定します。

inputMeansは幅inputCount高さ1のCIImage、またはCIColorの配列です。
色数が少ないならCIColorの方が調整が簡単で便利です。
inputPerceptualは1.0=true、0.0=falseです。
outputImageも幅inputCount高さ1の画像になります。

CIKMeansフィルターの使用例

CIKMeansフィルターのアルゴリズム

概要とパラメータだけ見て適当に動かしてもよくわかりませんが、ググると色々一般的な説明が出てきます。
私はこのサイトを参考にしました。

パラメータに合わせて説明するとこうなります。

(1) inputMeansで与えられた色を初期代表色とする
(2) 画像のinputExtentに含まれる各ピクセルについて、代表色からの距離によってinputCount個のクラスタに分ける
(3) 各クラスタの平均色を計算し、新たな代表色とする
(4) (2)〜(3)をinputPasses回繰り返す。

inputPerceptualは知覚色空間についてなので、単純に減色したい場合は0のままで大丈夫です。

ここまでが基本的な考え方です。
が、
実際には代表色に補正がかかります。

例えば、サンプル画像としてR255G255B255×80ピクセルとR0G0B0×20ピクセルで構成された画像(アルファは255)を用意します。

名称未設定 2

inputCount=2と適当なinputMeansを与えて代表色を予想すると、普通に考えれば(255, 255, 255)と(0, 0 0)になりますが、結果は(204, 204, 204, 204)と(0, 0, 0, 51)になります。
204は255×80%、51は255×20%です。

つまり、代表色のアルファはピクセルの平均ではなく、クラスタに所属するピクセルの割合になります。平均値は考慮されません。
そして、RGBの各値についてピクセルの割合を超えるものはピクセルの割合でカットされます。

また、クラスタのアルファ値平均が255(=1.0)でない時、RGBの各値にはアルファ値分の補正がかかります
例として平均色が(255, 63, 0, 127)なら、代表色のRGBには127/255の補正がかかって(127, 32, 0)になります。

まとめると

各成分の最大値を1.0(=255)として
代表色のR成分:min(クラスタの平均R×平均A, ピクセル率)
代表色のG成分:min(クラスタの平均R×平均A, ピクセル率)
代表色のB成分:min(クラスタの平均R×平均A, ピクセル率)
代表色のA成分:ピクセル率

です。

したがって、outputImageは基本的に暗くて透明になりがちです。
また、ピクセル数の少ない色は適切に代表色を設定しても特徴が潰れてしまうことになります。

CIKMeansを使えば画像から任意数の特徴色を抽出できると期待していたのですが、かなり工夫しないと難しそうです。 ■

参考:


この記事が気に入ったらサポートをしてみませんか?