けさらんぱの自由帳

とあるFF14プレイヤーがFF14のこととか関係ないことを書いていく予定のブログです。記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。

画像の乗算、スクリーン、オーバーレイ

SSを撮ったときに、なんか暗いなあと思うと画像をコピーしてスクリーン処理をする、ということがよくあります。ですが、スクリーンとかオーバーレイって何をする処理だっけ?とたまになるので、そのあたりの覚え書きです。

乗算

かけ算です。ただし、画像ファイルのデータの255を1.0とみなします。1.0より小さい値同士のかけ算なので、必ず元の値以下になります。

上の画像の値をo、下の画像の値をb、結果の画像の値をrとすると、
{\displaystyle
r = ob
}
となります。

もしo=b、つまり自分自身に乗算処理をした場合、グラフは以下のようになります。青の実線がオレンジの破線(y=x)より下にあり、暗くなることがわかります。
f:id:KesaranPa:20180214183759j:plain

スクリーン

乗算とは逆の処理です。
{\displaystyle
r = 1 - (1 - o)(1 - b)
}
この処理は、2つの画像を反転して乗算処理をして、その結果をさらに反転する、という処理と等価になります。乗算とは逆に必ず元の値以上になります。

もしo=b、つまり自分自身にスクリーン処理をした場合、グラフは以下のようになります。青の実線がオレンジの破線より上にあり、明るくなることがわかります。
f:id:KesaranPa:20180214183818j:plain

オーバーレイ

乗算とスクリーンを合体させた処理です。下の画像が暗いと乗算、明るいとスクリーンになります。
{\displaystyle
r = \cases{
2ob \cr
1 - 2(1 - o)(1 - b) \cr
}\qquad\array{
b \lt 0.5 \cr
b \ge 0.5 \cr
}
}

もしo=b、つまり自分自身にオーバーレイ処理をした場合、グラフは以下のようになります。暗いところはより暗く、明るいところはより明るくなります。
f:id:KesaranPa:20180214183836j:plain

FF14のSSで試してみる

元の画像。
f:id:KesaranPa:20180214184303j:plain

自身に乗算処理。
f:id:KesaranPa:20180214184318j:plain

自身にスクリーン処理。
f:id:KesaranPa:20180214184335j:plain

自身にオーバーレイ処理。
f:id:KesaranPa:20180214184347j:plain

シグモイド関数でコントラスト強調

たくさんの画像のコントラストを上げようとしたのですが、どんなアプリを使えばいいのかわからず、そもそもコントラストを上げると言っても、単純に値の上下数%を飽和させる方法とか、イコライザを使う方法とかいくつもあるようなので、自分の勉強も兼ねて適当に実装してみることにしました。今回はとりあえず目的に合っていそうだった、シグモイド関数を使ったコントラスト強調を試してみます。

ガンマ補正

いきなり本題とは少しずれた話題ですが、ほとんどのカラーの画像(sRGBの画像)ファイルにはガンマ補正がかかった値が格納されています(sRGBではない、例えばHDRの画像やグレースケールの画像はガンマ補正がないっぽいです)。PhotoshopGIMPだとそのあたり自動で処理してくれているはずなのですが、自分で実装する場合は考慮した方がいいと思います。コントラストの強調だけなら無視してもよさそうですが…

ガンマ補正というのは、昔のCRTディスプレイが入力に対して出力の特性が直線ではなく、
{\displaystyle
y = x^\frac{1}{\gamma}, \gamma=2.2
}
f:id:KesaranPa:20180208125354p:plain
に近い特性になっていて、これを補正するための処理のことです。具体的には
{\displaystyle
y = x^\gamma
}
となるような処理が画像ファイルのデータにはかけられています。

今回処理しようとした画像はsRGBで、上記の補正がかかっているので、画像処理をかける前にガンマ補正を除去する処理を行います。

シグモイド関数

シグモイド関数というのは下記の関数で、S字に似た形をしています。結構いろんなところで活躍しているひとらしいです。
{\displaystyle
\varsigma_a(x) = \frac{1}{1+\mathrm{e}^{-ax}}
}
f:id:KesaranPa:20180208125401p:plain

この形を利用して、明るいところはより明るく、暗いところはより暗くしようというのが今回の目的です。

コントラスト強調

素のままのシグモイド関数は、変曲点がx=0になっています。コントラスト強調に使用するため、x軸をbだけずらして
{\displaystyle
s(x) = \varsigma_a(x-b) = \frac{1}{1+\mathrm{e}^{a(b-x)}}
}
とします。bは、コントラストを強調したい場所になります。例えば、値が20%の周囲でコントラストを強調したいなら、b=0.2とします。aは、どのくらいコントラストを強調するかですが、決定には試行錯誤が必要になると思います。

また、このままだとyの範囲が0から1になっていないので、スケーリングを行います。最終的に、今回のコントラスト強調は下記のようになります。
{ \displaystyle
y = \frac{s(x)-s(0)}{s(1)-s(0)}
}
f:id:KesaranPa:20180208125410p:plain
上記のグラフはa=5.0, b=0.5の場合ですが、値が0.5より低いところではより暗く、0.5より高いところではより明るく、またx=0のときはy=0x=1のときはy=1になっているのがわかります。

Pythonで実装してみる

import math
import numpy as np
from PIL import Image
import sys
import os

def sigmoid(x):
    a = 5.0
    b = 0.5
    return 1.0 / (1.0 + math.exp(a * (b - x)))

lut = np.empty(256)
sigmoid0 = sigmoid(0.0)
sigmoid1 = sigmoid(1.0)
for i in range(256):
    x = i / 255.0
    x = x ** 2.2                                         # ガンマ補正を外す
    x = (sigmoid(x) - sigmoid0) / (sigmoid1 - sigmoid0)  # コントラスト補正をかける
    x = x ** (1.0/2.2)                                   # 再びガンマ補正をかける
    lut[i] = 255.0 * x

for fn in sys.argv[1:]:
    img = np.asarray(Image.open(fn))
    img = lut[img]
    ofn = os.path.splitext(fn)[0] + "-out.png"
    Image.fromarray(np.uint8(img)).save(ofn, quality=95)
    print("%s done." % fn)

numpy便利!

FF14のSSで試してみる

元の画像。 f:id:KesaranPa:20180208133320j:plain

a=5.0, b=0.5とした場合。 f:id:KesaranPa:20180208133335j:plain

b=0のときは、全体が明るくなります。 a=5.0, b=0.0とした場合。 f:id:KesaranPa:20180208133348j:plain

【FF14】【ID愛でる会Aegis】ラバナスタ観光

愛でる会で不定期にやっている24人レイドの観光、今回はラバナスタに行ってきました。最近では毎週行っているところですが、ゆっくり観光していくと普段とは違うところも見ていくことができます。

パーティ編成

今回はパーティ募集がアライアンスに対応したので、ぶっちゃけてしまうと集合する必要はなかったのですが、今回も今までと同じように集合場所を決めてそこでパーティ編成をしました。今回は、クガネランディングの近くの船の上に集合。出発まで思い思いのことをやっている参加メンバーたち。 f:id:KesaranPa:20180121145112j:plain

みんなログインしたらプライベート募集でパーティを編成して、突入!と思ったら、コンテンツファインダーサーバーのエラーが云々というメッセージ…! どうもアライアンスのリーダーしか申請できないようなのですが、あのエラーメッセージではそのことに気付かずしばらく混乱していました。みんなでよしだああ!!って叫んだあと無事に突入。

ラバナスタ地上部

1ボスは普通に撃破。自分が参加したCアラではメガネがドロップ。今回は不参加だったけど、愛でる会にはメガネ好きで有名なたけおさんがいらっしゃって、ラバナスタ実装初期にはメガネ入手のために随分苦労されていたのですが… f:id:KesaranPa:20180121145138j:plain f:id:KesaranPa:20180121145144j:plain

2ボスはかなり苦戦。砂球が爆発して2回全滅しました。初見の方もいるから仕方ない。撃破したあとの雑魚戦があるエリアには、周囲に赤チョコボの卵っぽいものがあります。オムレツ食べたい… f:id:KesaranPa:20180121145900j:plain

帝国の魔導兵器の残骸。最近戦闘があったとNPCが言っていますが、まだ燃えています。青い炎なのは青燐機関の燃料が燃えてるから、かな。 f:id:KesaranPa:20180121150340j:plain

水路

今回はここで一旦7分くらいの自由時間。

空中浮遊ララフェル。実際には水に浮いているだけなのですが、タレットを水面に置くと水上と水中が両方見えるのでこんなことに。紅玉海では青くなっちゃうのですが、ここの水は透明です。 f:id:KesaranPa:20180121150459j:plain

NPCも話していますが、潜水する場所はかなり水深が深いです。 f:id:KesaranPa:20180121150716j:plain

このエリア、天井を見上げても綺麗です。 f:id:KesaranPa:20180121150737j:plainf:id:KesaranPa:20180121150750j:plain

地下

3ボス、4ボスは特に問題なく撃破。3ボスさん、やっぱりグラフィックの作り込みがすごい。今回は3ボス撃破後に2回目の自由行動。 f:id:KesaranPa:20180121150857j:plain

4ボスの戦闘前、あの仮面がボスの近くに浮いてます。 f:id:KesaranPa:20180121150925j:plain

4ボスの途中で出てくるあの人、スカラタンク装備かな? f:id:KesaranPa:20180121150945j:plain

ダークアルテマ後は仮面が増えます。 f:id:KesaranPa:20180121151004j:plain

啓示の時はしっかり仮面を装着している4ボスさん。 f:id:KesaranPa:20180121151032j:plain

そうこうして無事にクリアしてみんなで集合写真を撮影して終了です。主催してくれたすぱさん、はなおん、本当にありがとうです! f:id:KesaranPa:20180121151119j:plain

記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。