scikit imageでHue(色相), Saturation(彩度)の変更をする

scikit-image: Image processing in Python — scikit-image

Hue(色相)とSaturation(彩度)の変更方法は、RGBをHSV変換して、HとSのchannelを変更すれば良い。 どの程度変更すれば良いかがわかりにくいので、GIMPと同じになるように値を調整したものを作成した。

  • Hueの調整値: -180から180で指定
  • Saturationの調整値: -100から100で指定
import skimage.color
import numpy as np


def to_valid_image(image):
    return np.clip(image, 0, 255).astype('uint8')


def adjust_hue_saturation_lightness(
        image, hue_range=0, hue_offset=0, saturation=0, lightness=0):
    # hue is mapped to [0, 1] from [0, 360]
    if hue_offset not in range(-180, 180):
        raise ValueError('Hue should be within (-180, 180)')
    if saturation not in range(-100, 100):
        raise ValueError('Saturation should be within (-100, 100)')
    if lightness not in range(-100, 100):
        raise ValueError('Lightness should be within (-100, 100)')
    image = skimage.color.rgb2hsv(image)
    offset = ((180 + hue_offset) % 180) / 360.0
    image[:, :, 0] = image[:, :, 0] + offset
    image[:, :, 1] = image[:, :, 1] + saturation / 200.0
    image[:, :, 2] = image[:, :, 2] + lightness / 200.0
    image = skimage.color.hsv2rgb(image) * 255.0
    image = to_valid_image(image)
    return image

使い方は以下のようになる。

import skimage.io

img = sikimage.io.imread(path_to_image)
# Hue + 50
img = adjust_hue_saturation_lightness(img, 0, 50, 0, 0)
skimage.io.imshow(img)

元画像

20171204010033

Hue + 50

20171204010032

Saturation + 50

20171204010034

Value + 50

20171204010035

GitHub ioでjekyllをdisableにする

GitHub ioで静的web siteを公開する際にはdefaultではjekyllがONになっており、GitHubにpushした後jekyllによってcodeが処理される。 この時、jekyllのmeta directory _で始まるfolderなどが存在すると、除外されるなど、既にrepository内に静的HTMLを追加している場合は、jekyllの機能は邪魔になる。 jekyllを無効にする場合は、.nojekyllというfileをrepositoryに於けば良いが、置く場所はGitHub ioの設定によって変わる。

  • master branch
    • repositoryのroot
  • /docs folder
    • /docs/.nojekyll として置く
  • gh-pages branch
    • repositoryのroot

sphinx + breatheでAttributeError: 'NoneType' object has no attribute 'replace'

以下のようなエラーがSphinx + Breatheで出る。

# Sphinx version: 1.6.3
# Python version: 3.6.2rc1 (CPython)
# Docutils version: 0.13.1 release
# Jinja2 version: 2.9.6
# Last messages:
#   building [mo]: targets for 0 po files that are out of date
#
#   building [html]: targets for 1 source files that are out of date
#
#   updating environment:
#
#   1 added, 0 changed, 0 removed
#
#   reading sources... [100%] index
#
# Loaded extensions:
#   alabaster (0.7.10) from /usr/local/lib/python3.6/site-packages/alabaster/__init__.py
#   breathe (4.6.0) from /usr/local/lib/python3.6/site-packages/breathe/__init__.py
#   sphinx.ext.todo (1.6.3) from /usr/local/lib/python3.6/site-packages/sphinx/ext/todo.py
#   sphinx.ext.mathjax (1.6.3) from /usr/local/lib/python3.6/site-packages/sphinx/ext/mathjax.py
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/sphinx/cmdline.py", line 306, in main
    app.build(opts.force_all, filenames)
  File "/usr/local/lib/python3.6/site-packages/sphinx/application.py", line 339, in build
    self.builder.build_update()
  File "/usr/local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 331, in build_update
    'out of date' % len(to_build))
  File "/usr/local/lib/python3.6/site-packages/sphinx/builders/__init__.py", line 344, in build
    updated_docnames = set(self.env.update(self.config, self.srcdir, self.doctreedir))
  File "/usr/local/lib/python3.6/site-packages/sphinx/environment/__init__.py", line 583, in update
    self._read_serial(docnames, self.app)
  File "/usr/local/lib/python3.6/site-packages/sphinx/environment/__init__.py", line 602, in _read_serial
    self.read_doc(docname, app)
  File "/usr/local/lib/python3.6/site-packages/sphinx/environment/__init__.py", line 723, in read_doc
    pub.publish()
  File "/usr/local/lib/python3.6/site-packages/docutils/core.py", line 218, in publish
    self.apply_transforms()
  File "/usr/local/lib/python3.6/site-packages/docutils/core.py", line 199, in apply_transforms
    self.document.transformer.apply_transforms()
  File "/usr/local/lib/python3.6/site-packages/docutils/transforms/__init__.py", line 171, in apply_transforms
    transform.apply(**kwargs)
  File "/usr/local/lib/python3.6/site-packages/docutils/transforms/universal.py", line 294, in apply
    txtnode.parent.replace(txtnode, nodes.Text(newtext))
AttributeError: 'NoneType' object has no attribute 'replace'

breatheのbug

issueに解決方法が記載してある。 以下の該当行を次のコードで置き換えれば良い。

https://github.com/michaeljones/breathe/blob/d3eae7fac4d2ead062070fd149ec8bf839f74ed5/breathe/renderer/sphinxrenderer.py#L1103

        if nodelist:
            # nodelist[0].children = [term, separator] + nodelist[0].children
            nodelist[0].insert(0, term)
            nodelist[0].insert(1, separator)
        else:
            nodelist = [term]

numpyの演算

numpyの演算は、二次元の配列と一次元の配列を明確に区別している。 一次元の配列はvectorとして、二次元の配列はmatrixとして、数学的に許された演算のみ可能。 例えば、[0 1 2 3 4 5][[0 1 2 3 4 5]]の演算はできない。

def printVar(var, symboltable):
    for k, v in symboltable.items():
        if id(v) == id(var):
            print("{0}:".format(k))
            print(v)
            print("")

a = np.arange(6)
row_mat = np.arange(6).reshape(1, -1)
row_mat_trans = row_mat.T
col_mat = np.arange(6).reshape(-1, 1)
col_mat_trans = col_mat.T
add_mat = row_mat + col_mat_trans
mult_mat = row_mat.dot(col_mat)

printVar(a, locals())
printVar(row_mat, locals())
printVar(row_mat_trans, locals())
printVar(col_mat, locals())
printVar(col_mat_trans, locals())
printVar(add_mat, locals())
printVar(mult_mat, locals())

# operations causing errors
# mult_mat = a.dot(row_mat)

出力は

a:
[0 1 2 3 4 5]

row_mat:
[[0 1 2 3 4 5]]

row_mat_trans:
[[0]
 [1]
 [2]
 [3]
 [4]
 [5]]

col_mat:
[[0]
 [1]
 [2]
 [3]
 [4]
 [5]]

col_mat_trans:
[[0 1 2 3 4 5]]

add_mat:
[[ 0  2  4  6  8 10]]

mult_mat:
[[55]]

有限体の勉強するのに良い本

finite fields - Books on advanced galois theory - MathOverflow より引用。

Sierraのkarabiner elementsで日本語キーボードをUSキーボードっぽく使う

KarabinerはSierraにまだ対応していない。 Karabiner elementsでキーボードの配列を変更できるので、キーボードの配列を一文字ずついじってUSっぽく使うことはできる。

~/.config/karabiner/karabiner.jsonにキーの設定ファイルがあるので、以下を追記する。

Karabiner-Elements/README.md at master · tekezo/Karabiner-Elements

            "simple_modifications": {
              "0": "9",
              "1": "grave_accent_and_tilde",
              "2": "1",
              "3": "2",
              "4": "3",
              "5": "4",
              "6": "5",
              "7": "6",
              "8": "7",
              "9": "8",
              "caps_lock": "fn",
              "delete_forward": "equal_sign",
              "equal_sign": "hyphen",
              "hyphen": "0",
              "international1": "backslash",
              "international3": "equal_sign"
            },

次にKarabiner-Elementsを開きVirtual KeyboardのタブのKeyboard typeをANSIにしておく。

参考

std::stringでtolower/toupper

#include <algorithm>
#include <string> 

std::string data = "Abc"; 
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
std::transform(data.begin(), data.end(), data.begin(), ::toupper);

Reference