A little Cafe Times

日々のちょっとしたこと

つくろう!ナチュラルハーモニー

このブログはD@NPEN Advent Calendar 2020 - Adventarの16日目の記事です。

前日はid:kitos_ma09 君のCSSチュパカブラチャレンジ - Noteでした。

技術系の記事ですね!Pythonは一発芸的な使い方も気軽にできるのがよいですね。さりげないデビ太郎も好き。

というわけで9日振りです。よくわからないタイトルと共に戻ってきました。

ナチュラルハーモニーとは?

哲学的な話ではなく。

ナチュラルハーモニーといえば!

もちろん高森藍子緒方智絵里のユニットですね!発表から1年と1か月ちょっと経ちました!

ひとつ前の記事でもまとめていますが、今年は近年まれにみる大活躍。

この活躍をもっと盛り上げるべく、何かできることはないか……。そんなことを考えている中、ナチュラルハーモニーサーチをしていると別文脈で引っかかるものが。

ナチュラルハーモニー(配色)とは?

ナチュラルハーモニー」とはその名の通り、自然な調和を生む配色で、自然界に存在する配色も多く見慣れたものであることからそのような印象を与えます。具体的にどのような配色を指すかというと、配色の組み合わせのうち「黄色に近い色味を明るく」して、もう一方の「青紫色に近い色味を暗く」した配色になります。

引用 : ナチュラルハーモニー・コンプレックスハーモニー配色を比べてみる | オウンドメディア | 大阪市天王寺区SOHOホームページ制作 | デザインサプライ-DesignSupply.-

めっちゃナチュラルハーモニー(ユニット)って感じする!!!!

ここで思いつきました。気軽にナチュラルハーモニー(配色)に触れられるようになったらナチュラルハーモニー(ユニット)にも注目されるのでは???

思いついたらやってみましょう。

つくろう!ナチュラルハーモニー

引用にもある通り、黄色に近い色を明るく、青紫色に近い色を暗くするのがナチュラルハーモニーのようです。

画像の色をとっていい感じによしなにしてあげるとナチュラルハーモニーになりそうですね。

今回はこんな色相環(もどき)を考えてみます。

f:id:shilfol:20201215235152p:plain
色相環のようでそうでないカラーサークル

色を変換する

色を表すのによく使われるのは#C5DD7Fのような形で表現されるRGB形式でしょう。 ただ、RGBは明るさを扱うのが少し難しいので、別の表現方法を考えてみます。

ここでは、HSV(HSB)という、色相(色の種類)と彩度(色の鮮やかさ)、明度(色の明るさ)で表現される形式を使ってみます。なんと都合がよい形式でしょう。

ナチュラルハーモニーの定義から、黄色に近い色相であればあるほど明度を上げ、青紫色に近い色相であればあるほど明度を下げればよさそうです。

色相を表すHueは、通常0から360の値で表されます。めちゃくちゃ円を思い浮かべます。 そこで三角関数を用いて、色相に対応する明度を求めてみようとします。

黄色に近い値で最大値を取ってほしいので、黄色で最大値を取るようにCosを考えると、こんな感じになります。 なお、明度Vは後述するプログラムで0から1の範囲を取るので、補正もかけておきます。

V = Cos(θ - 60°) / 2 + 1/2 

これでナチュラルハーモニーっぽくなりそうです!

実装する

実装にはGoを使いました。理由は好きだからです。 好きを大切に。

Goの標準ライブラリはかなり充実していますが、色情報を扱うには少し不自由なので、go-colorfulというライブラリを利用します。

github.com

go-colorfulを用いることで、画像をRGB形式で読み込んだとしても容易にHSV形式に変換することが可能です。

今までの話をまとめて実装してみると、こんな感じです。 ソース片なので参考までに。

import (
    "image"
    "image/color"
    "math"

    "github.com/lucasb-eyer/go-colorful"
)

type NaturalHarmonyParam struct {
    P float64
}

func ConvertNaturalHarmony(img image.Image, nhp *NaturalHarmonyParam) image.Image {
    b := img.Bounds()
    ci := image.NewRGBA(b)
    for y := b.Min.Y; y < b.Max.Y; y++ {
        for x := b.Min.X; x < b.Max.X; x++ {
            p := innerProcessNaturalHarmony(img.At(x, y), nhp)
            ci.Set(x, y, p)
        }
    }
    return ci
}

func innerColorProcessNaturalHarmony(c colorful.Color, nhp *NaturalHarmonyParam) colorful.Color {
    h, s, v := c.Hsv()
    mh, ms, mv := mappingNaturalHarmonyHSV(h, s, v, nhp)
    mc := colorful.Hsv(mh, ms, mv)
    return mc
}

func mappingNaturalHarmonyHSV(h, s, v float64, nhp *NaturalHarmonyParam) (hh, ss, vv float64) {
    // hue(色相)はそのまま
    hh = h
    // saturation(彩度)もいったんそのまま
    ss = s
    // 0~360を0~2pi(rad)に変換するので, pi/180をかける
    radian := h * math.Pi / 180.0
    // 黄色のhは60(0~360)の値であるので, pi/3となる
    cv := (math.Cos(radian-math.Pi/3.0))/2.0 + 0.5

    // もともとのvとdiffを取ってみる
    // dv := math.Abs(cv - v)
    // diffをいくらか小さくした値(p)をcvに近づける方向へ加算
    // vv = ((cv-v)/dv)*dv*p + v を整理したもの
    p := nhp.P
    if !isNearlyZero(h) || !isNearlyZero(s) {
        vv = p*(cv-v) + v
    } else {
        // 白 or 黒はそのまま出す
        vv = v
    }
    return
}

要約すると、

  • ConvertNaturalHarmonyに画像情報を投げるとナチュラルハーモニーに変換するよ
  • NaturalHarmonyParamナチュラルハーモニー度を調整できるよ

という感じです。

動かしてみる

よしなに実装を終えたら、動かしてみます。その結果がこちら。

f:id:shilfol:20201216003449p:plain
おわかりいただけただろうか

処理前と並べてみます。

f:id:shilfol:20201216005412p:plain
ナチュラルハーモニー!

それっぽい!!!!!!!!ナチュラルハーモニー!!!!!!

Q.これがナチュラルハーモニー…?

A. 自分がナチュラルハーモニーだと思うものがナチュラルハーモニーだと思います。

それはそれとして。色々問題はあるのですが、

  • 色の変換を考えるときに最大値しか考えておらず青紫が最小ではない(記事を書いてる途中で気がついた)
  • 気軽に使えない
  • そもそもナチュラルハーモニー(配色)と言えるのか

一番下は色彩検定を持っているオタクに検証をお願いしたいところ。

気軽に使えないのは割と大きな問題ですね。 これをどうするか?解決策はもちろんありますが、それは明後日までのお楽しみです。

今日はここまで。アイマス要素があるかは謎ですがナチュラルハーモニー要素は盛りだくさんでお届けしました。

明日は腹いーたー君の詩花のお話です。詩花って書けない。

P.S. 小日向美穂さんお誕生日おめでとうございます!