Loading...
墨滴

张春成

2021/06/26  阅读:72  主题:默认主题

图解审美(二)

图解审美(二)

本文接上文《图解审美(一)》。 本文试图说明,可以通过在HSV颜色空间中的变换,对图像进行风格化变换。


颜色空间的线性变换

我们可以通过线性变换,达到图像风格化的目的

  • 原始动画图像;
  • 风格化后的图像对比。

p1--1 p1--2 p1--3

原始图像

为了说明颜色的分布问题, 我们从三张原始图像开始。

  • 第一张为动画风格图像;
  • 第二张为风景图像;
  • 第三张为油画图像。

p1-raw p2-raw p3-raw

变换后的图像

通过线性变换,可以实现HSV空间上的颜色分布匹配。 可以从下图看到,经过线性变换后,颜色的分布在颜色空间中产生了对齐效果。 当然,我们不能指望线性变换有特别好的效果。

  • 第一张为向风景图像进行变换 p1-2

  • 第二张为向风景图像进行变换 p1-3

分析及呈现代码

计算过程使用python代码,可以参考我的GITHUB仓库[1]。 代码如下

引用的包

import cv2
import urllib.request
from PIL import Image
from io import BytesIO

import numpy as np
import pandas as pd
from scipy.linalg import sqrtm

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

自定义工具

def mk_matrix(img):
    ''' Convert PIL [img] into RGB and HSV Matrix,
    and put them into the [img] Object.
    '''

    img.matrix = dict()

    rgb = np.array(img.convert('RGB'))

    hsv = cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV)

    img.matrix['RGB'] = rgb
    img.matrix['HSV'] = hsv

    return img

def ravel(d, full=False):
    ''' Ravel the 1st and the 2nd Dimensions,
    only keep 500 Pixels to save Computation Time.
    '''

    s = d.shape
    n = s[0] * s[1]
    d = d.reshape((n, s[2]))
    if n > 500 and not full:
        return d[range(0, n, int(n/500))]
    else:
        return d

def convert(rgb):
    ''' Convert RGB [rgb] values into #FFFFFF like Color String'''

    def n2s(n):
        s = hex(n).replace('x''')
        return s[-2:]

    return '#' + ''.join([n2s(n) for n in rgb])

def color_space(im):
    ''' Draw Color Space of Image [im] '''
    mk_matrix(im)

    v_rgb = ravel(im.matrix['RGB'])
    df = pd.DataFrame(ravel(im.matrix['RGB']), columns=['R''G''B'])
    df[['H''S''V']] = ravel(im.matrix['HSV'])
    df['color'] = [convert(e) for e in v_rgb]

    subplot_titles = ('RG''HS''GB''SV''RB''HV')
    subplot_pos = ((11), (12), (21), (22), (31), (32))
    fig = make_subplots(rows=3, cols=2, subplot_titles=subplot_titles)

    for pos, title in zip(subplot_pos, subplot_titles):
        x, y = title
        row, col = pos

        _fig = px.scatter(df, x=x, y=y, title=title)
        _fig.data[0]['marker']['color'] = df['color']

        kwargs = dict(
            row=row,
            col=col
        )

        fig.add_trace(
            _fig.data[0],
            **kwargs
        )

        fig.update_xaxes(title_text=x, **kwargs)
        fig.update_yaxes(title_text=y, **kwargs)

    fig.update_layout(dict(
        height=1000,
        width=900,
        title=url
    ))
    fig.show()

    fig1 = px.imshow(im)
    fig1.show()

比较和变换

# Target Image
url = 'http://localhost:8000/DP164837.jpg'
req = urllib.request.urlopen(url)
im2 = Image.open(BytesIO(req.read()))
color_space(im2)

# Compute Cov of Target Img
hsv = im2.matrix['HSV'].copy()
hsv_ravel = ravel(hsv, full=True)

mean2 = np.mean(hsv_ravel, axis=0)
std2 = np.std(hsv_ravel, axis=0)

print(mean2.shape, hsv.shape, hsv_ravel.shape)

cov = np.cov((hsv_ravel-mean2).transpose())
for j in range(3):
    for k in range(3):
        cov[j, k] /= np.sqrt(std2[j] * std2[k])

scov2 = sqrtm(cov)

# Converted Image
url = 'http://localhost:8000/132457451652521207_new.jpg'
req = urllib.request.urlopen(url)
im1 = Image.open(BytesIO(req.read()))
color_space(im1)

# Compute Cov of Converted Img
hsv = im1.matrix['HSV'].copy()
shape = hsv.shape
hsv_ravel = ravel(hsv, full=True)

mean = np.mean(hsv_ravel, axis=0)
std = np.std(hsv_ravel, axis=0)

print(mean.shape, hsv.shape, hsv_ravel.shape)

cov = np.cov((hsv_ravel-mean).transpose())
for j in range(3):
    for k in range(3):
        cov[j, k] /= np.sqrt(std[j] * std[k])

scov = sqrtm(cov)
iscov = np.linalg.inv(scov)
iscov

# Convert Img
hsv_ravel_new = np.matmul(np.matmul(hsv_ravel - mean, iscov), scov2) + mean2
hsv_new = hsv_ravel_new.astype(np.uint8)

for j in [12]:
    hsv_new[:, j][hsv_new[:, j] > 200] = 0

hsv_new

# Plot Converted Img
rgb = cv2.cvtColor(hsv_new.reshape(shape), cv2.COLOR_HSV2RGB)
im = Image.fromarray(rgb)
color_space(im)
px.imshow(im2).show()

参考资料

[1]

GITHUB仓库: https://github.com/listenzcc/JupyterScripts.git

张春成

2021/06/26  阅读:72  主题:默认主题

作者介绍

张春成