aoirint's note

メモ帳(古い記事はkanomiya blogから移行)

Install TexLive on Ubuntu 18.04

普段TeXを書くときはAtom + latex + pdf-viewなのですが、うまくpdf-viewが動作してくれなくなった(空のタブが開いたりする)ので検証ついでに(関係ないとは思いつつ)TeXのバージョンを上げてみたくなった。aptからインストーラでのインストールに変更。

TeXはインストールに時間がかかっていけない..。dockerイメージ化したいが、毎回dockerコンテナ付けるとめっちゃオーバーヘッドできそう。up -dしてexecで動かせば速いのかな? 一般ユーザでdockerコマンド実行できるようにもしないといけないか。

sudo apt purge texlive-*

東京周辺ならJAIST山形大学などのミラーサーバに繋がるかと思います。

wget http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz
sha512sum install-tl-unx.tar.gz
6fbca1895f0f08645e2ff97b34b9b07d659af7d25de1edc6e123fc472f3dd05db42edc9e5450fd09fae548f5259f93d7f98f63d29dfe6ff7e069685ba202661b  install-tl-unx.tar.gz
tar xf install-tl-unx.tar.gz
cd install-tl-*
sudo ./install-tl
Actions:
 <I> start installation to hard disk
 <P> save installation profile to 'texlive.profile' and exit
 <H> help
 <Q> quit

Enter command: I
Installing to: /usr/local/texlive/2020
Installing [0001/3978, time/total: ??:??/??:??]: texlive.infra [420k]
Installing [0002/3978, time/total: 00:01/02:06:37]: texlive.infra.x86_64-linux [143k]

おうちの回線では1h-2hくらい。おやすみなさい..

Welcome to TeX Live!


See /usr/local/texlive/2020/index.html for links to documentation.
The TeX Live web site (https://tug.org/texlive/) contains any updates and
corrections. TeX Live is a joint project of the TeX user groups around the
world; please consider supporting it by joining the group best for you. The
list of groups is available on the web at https://tug.org/usergroups.html.


Add /usr/local/texlive/2020/texmf-dist/doc/man to MANPATH.
Add /usr/local/texlive/2020/texmf-dist/doc/info to INFOPATH.
Most importantly, add /usr/local/texlive/2020/bin/x86_64-linux
to your PATH for current and future sessions.
Logfile: /usr/local/texlive/2020/install-tl.log
export MANPATH=/usr/local/texlive/2020/texmf-dist/doc/man:$MANPATH
export INFOPATH=/usr/local/texlive/2020/texmf-dist/doc/info:$INFOPATH
export PATH=/usr/local/texlive/2020/bin/x86_64-linux:$PATH

...問題は直りませんでした。やっぱ関係ないか。本題についてはエンジンをplatexからuplatexに変更してみたら解決した気がする。ついでにAtomのバージョンが古くなっていたのでアップデート。レスポンス良くなった?

nginx basic auth, reverse proxy, static files

Basic auth

        auth_basic "Authentication Required";
        auth_basic_user_file DIRECTORY/.htpasswd;

Reverse proxy

        proxy_set_header HOST $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
                proxy_pass http://localhost:8000;
        }

Static files

        location /static/ {
                root PARENT_OF_STATIC_DIRECTORY;
        }

Let's Encrypt certbot Error Ubuntu(ImportError: cannot import name 'constants')

間違えてOSのパッケージリポジトリからcertbotを入れてしまった.

コマンド

sudo certbot --nginx

エラー1(初期状態)

ImportError: cannot import name 'constants'

エラー2(pip3 uninstall certbotの後)

AttributeError: module 'acme.challenges' has no attribute 'TLSSNI01Response'
sudo pip3 uninstall certbot acme
sudo apt purge certbot python-certbot-nginx

# HERE: register official ppa repository (see official guide)

sudo apt install certbot python-certbot-nginx

OpenGL 2.1/4.1(GLFW)でOpenCVの画像を表示する(Python, Mac)

pip3 install PyOpenGL glfw

モジュールバージョン

PyOpenGL==3.1.5
glfw==1.11.0

システムのOpenGLバージョン

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'4.1 INTEL-14.4.23'

OpenGL 2.1

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'2.1 INTEL-14.4.23'

glDrawPixels

import cv2
from OpenGL.GL import *
import glfw

if __name__ == '__main__':
    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB)

    glfw.init()

    # These parameters need to be changed according to your environment.
    # Mac: https://support.apple.com/ja-jp/HT202823
    # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    width = img.shape[1]
    height = img.shape[0]
    window = glfw.create_window(width, height, 'Lena', None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

Texture

import cv2
from OpenGL.GL import *
import glfw

if __name__ == '__main__':
    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    glfw.init()

    # These parameters need to be changed according to your environment.
    # Mac: https://support.apple.com/ja-jp/HT202823
    # glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    # glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    # glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    # glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    window = glfw.create_window(256, 256, 'Lena', None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

    height, width = img.shape[:2]
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        glEnable(GL_TEXTURE_2D)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        glBegin(GL_QUADS)
        glTexCoord2d(0.0, 1.0)
        glVertex3d(-1.0, -1.0, 0.0)
        glTexCoord2d(1.0, 1.0)
        glVertex3d(1.0, -1.0, 0.0)
        glTexCoord2d(1.0, 0.0)
        glVertex3d(1.0, 1.0, 0.0)
        glTexCoord2d(0.0, 0.0)
        glVertex3d(-1.0, 1.0, 0.0)
        glEnd()

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

OpenGL 4.1 / GLSL

Vendor : b'Intel Inc.'
GPU : b'Intel Iris OpenGL Engine'
OpenGL version : b'4.1 INTEL-14.4.23'
import sys
from OpenGL.GL import *
import glfw
import numpy as np
import cv2


vertex_shader_text = '''
#version 410 core

in vec3 vPosition;
out vec2 vTextureCoord;

void main(void) {
    vTextureCoord = vec2((vPosition.x + 1.0) / 2, (vPosition.y + 1.0) / 2);
    gl_Position = vec4(vPosition, 1.0);
}
'''

fragment_shader_text = '''
#version 410 core

uniform sampler2D vTexture;
in vec2 vTextureCoord;
out vec4 flagColor;

void main(void) {
    flagColor = texture(vTexture, vTextureCoord).rgba;
}
'''

def init_context():
    print('Initializing context..')
    glfw.init()

    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)

    global window
    window = glfw.create_window(512, 512, __file__, None, None)
    glfw.make_context_current(window)

    print('Vendor :', glGetString(GL_VENDOR))
    print('GPU :', glGetString(GL_RENDERER))
    print('OpenGL version :', glGetString(GL_VERSION))

def init_texture():
    print('Initializing texture..')

    img = cv2.imread('lena.png', 1)
    img_gl = cv2.cvtColor(cv2.flip(img, 0), cv2.COLOR_BGR2RGB)

    global width, height
    height, width = img.shape[:2]

    global texture
    texture = glGenTextures(1)

    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, texture)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_gl)

def init_shader():
    print('Initializing shader..')

    global vertex_shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader, vertex_shader_text)
    glCompileShader(vertex_shader)
    if not glGetShaderiv(vertex_shader, GL_COMPILE_STATUS):
        print('Vertex shader is not OK')
        print(glGetShaderInfoLog(vertex_shader))
        sys.exit(1)
    else:
        print('Vertex shader is OK')

    global fragment_shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader, fragment_shader_text)
    glCompileShader(fragment_shader)
    if not glGetShaderiv(fragment_shader, GL_COMPILE_STATUS):
        print('Fragment shader is not OK')
        print(glGetShaderInfoLog(fragment_shader))
        sys.exit(1)
    else:
        print('Fragment shader is OK')

    global program
    program = glCreateProgram()
    glAttachShader(program, vertex_shader)
    glDeleteShader(vertex_shader)
    glAttachShader(program, fragment_shader)
    glDeleteShader(fragment_shader)
    glLinkProgram(program)
    if not glGetProgramiv(program, GL_LINK_STATUS):
        print('Shader program is not OK')
        print(glGetProgramInfoLog(program))
        sys.exit(1)
    else:
        print('Shader program is OK')

def init_vao():
    print('Initializing vao..')

    # anti-clockwise
    vertices = np.array([
        -1.0, -1.0, 0.0, # left bottom
        1.0, -1.0, 0.0, # right bottom
        -1.0, 1.0, 0.0, # left top

        -1.0, 1.0, 0.0, # left top
        1.0, -1.0, 0.0, # right bottom
        1.0, 1.0, 0.0, # right top
    ], dtype=np.float32)

    global vertex_vbo
    vertex_vbo = glGenBuffers(1)

    global vertex_vao
    vertex_vao = glGenVertexArrays(1)
    glBindVertexArray(vertex_vao)

    glEnableVertexAttribArray(0)

    glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo)
    glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
    glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

    glBindVertexArray(0)

def render():
    glUseProgram(program)

    glUniform1i(glGetUniformLocation(program, 'vTexture'), 0)

    glBindVertexArray(vertex_vao)
    glDrawArrays(GL_TRIANGLES, 0, 6)
    glBindVertexArray(0)

if __name__ == '__main__':
    init_context()
    init_texture()
    init_shader()
    init_vao()

    print('Start rendering..')
    while not glfw.window_should_close(window):
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        render()

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

Fisheye distortion

カメラ座標 
P_c = \left(
\begin{array}{c}
X_c \\
Y_c \\
Z_c
\end{array}
\right)


x' = X_c / Z_c \\
y' = Y_c / Z_c \\
r^2 = x'^2 + y'^2 \\
\theta = {\rm atan}(r)

歪み補正 / Distortion correction


\theta_d = \theta ( 1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8 )\\
x'' = \frac{ \theta_d }{r} x' \\
y'' = \frac{ \theta_d }{r} y'

カメラ座標変換


\left(
\begin{array}{c}
u \\
v
\end{array}
\right)
=
\left(
\begin{array}{ccc}
f_x & 0 & c_x \\
0 & f_y & c_y \\
\end{array}
\right)

\left(
\begin{array}{c}
x'' \\
y'' \\
1
\end{array}
\right)

OpenCV

K = np.array([
    [ 1, 0, 320 ],
    [ 0, 1, 240 ],
    [ 0, 0, 1 ],
], dtype=np.float32)
D = np.array([ 1, 0, 0, 0 ], dtype=np.float32)

undistorted_points = np.array([[
    [ 0, 0 ],
    [ 0, 10 ],
    [ 10, 0 ],
    [ 10, 10 ],
]], dtype=np.float32)

distorted_points = cv2.fisheye.distortPoints(undistorted_points, K, D)

distorted_points
array([[[320.     , 240.     ],
        [320.     , 244.65497],
        [324.65497, 240.     ],
        [323.44827, 243.44826]]], dtype=float32)

歪みなしカメラ画像の座標変換

カメラ行列(内部パラメータ / intrinsic parameters)


A = \left(
\begin{array}{ccc}
f_x & 0 & c_x \\
0 & f_y & c_y \\
0 & 0 & 1
\end{array}
\right)

射影変換行列(Perspective transform matrix, 外部パラメータ/ extrinsic parameters)

参考:2次元の射影変換行列


[R|t] = \left(
\begin{array}{cccc}
r_{11} & r_{12} & r_{13} & t_x \\
r_{21} & r_{22} & r_{23} & t_y \\
\end{array}
\right)

3次元の射影変換行列


[R|t] = \left(
\begin{array}{cccc}
r_{11} & r_{12} & r_{13} & t_x \\
r_{21} & r_{22} & r_{23} & t_y \\
r_{31} & r_{32} & r_{33} & t_z \\
\end{array}
\right)

実世界の位置とカメラ画像座標の射影変換

「任意の原点・角度の位置(世界座標)」と「カメラの位置、角度からの相対座標(カメラ座標)」の変換


P_c =
\left(
\begin{array}{c}
x \\
y \\
z
\end{array}
\right)
= [R|t] \left(
\begin{array}{c}
X_w \\
Y_w \\
Z_w \\
1
\end{array}
\right)

「カメラの位置、角度からの相対座標(カメラ座標)」と「カメラ画像中の画素の座標」の変換


P_i =
\left(
\begin{array}{c}
u \\
v \\
1
\end{array}
\right)
= A\ P_c
= A\ [R|t] \left(
\begin{array}{c}
X_w \\
Y_w \\
Z_w \\
1
\end{array}
\right)