vscodeでリモート開発をするための環境
vscodeのリモート開発環境構築
- 研究室の後輩とか向け
- vscodeのremote development using sshを使用
- 踏み台サーバを通る必要がある場合の.ssh/configの書き方
- jupyterとかを使いたいときのポートフォワーディング設定
- オススメのvscode拡張
とかを書いておく.
vscode remote developmentの導入
これを使うと,研究室のファイルなどがローカルにあるノリで作業できる.
ここの最初らへんが参考になる.
vscodeのサイドバーの四角が4つ組み合わさったアイコンから検索
.ssh/configの設定
毎回,目的のipなどをフルで入力しても良いけれど,面倒くさいので設定すると楽
デフォルトのフォーマットは以下のような感じ.
Host alias HostName hostname User user
- 接続ポートがデフォルトの22番以外の場合.
port <番号>
- 踏み台を経由して接続
(Windowsの場合) ProxyCommand C:\Windows\System32\OpenSSH\ssh.exe -W %h:%p <踏み台のalias> (Ubuntuの場合) ProxyCommand ssh <踏み台のalias> -W %h:%p
- ポートフォワーディングする場合
LocalForward 127.0.0.1:8888 127.0.0.1:8888
Cisco AnyConnectが使いづらいので,代替としてOpenConnectを使う
大学のVPN
大学のVPNで色々と問題があったけれど,なんとか解決できたっぽい.
officialな方法だと使わされるAnyConnectが悪いのかはわからない.
少なくともルーティングの設定などが(そもそも出来るのかしらんけど)分かりにくいのは確か.
問題点
今回の方法で解決できるのは以下の2つの問題.
原因
- なんでQiitaとかのサイトに繋がらないかはわからん
- 大学側行きの通信だけ,大学側のゲートウェイに流したいけど,AnyConnectだと設定が弄れなさそう(よくわからん)
解決法(セキュリティ的に問題があったらゴメン)
- AnyConnectの代わりにOpenConnect使う
- OpenConnectの設定ファイルをいじってルーティングを設定する
以下で手順を解説していく.
手順
OpenConnectのインストール
OpenConnectは
OpenConnect is an SSL VPN client initially created to support Cisco's AnyConnect SSL VPN.
らしい.
- 公式サイト?はココ (https://www.infradead.org/openconnect/index.html)
- 最終の更新が2018年で嫌だけど,自分はGUIのほうを使いました (https://github.com/openconnect/openconnect-gui/releases)
こんな感じの画面が開きます.
自分の場合は設定済みなのでServerにTMU-VPNって出てるけど気にしないでください.
OpenConnectの接続設定
File -> Profiles -> New profile
から大学のGatewayを入力.
入力したら,Save&Connect押して,そもそも接続できるか試しとくと良いかも.
ルーティング設定
OpenConnectのルーティングの設定はvpnc-script.js
を弄れば良いらしい.
vpnc-script.js
はexeファイルと同じ階層にあった.
25行目のコメントを読むと-1を設定すれば上書きされなさそうなので,
// How to add the default internal route // -1 - Do not touch default route (but do other necessary route setups) // 0 - As interface gateway when setting properties // 1 - As a 0.0.0.0/0 route with a lower metric than the default route // 2 - As 0.0.0.0/1 + 128.0.0.0/1 routes (override the default route cleanly)
このコメントのすぐ下のコードの0の部分を-1に書き換える.
# 編集前 if (env("REDIRECT_GATEWAY_METHOD")) { var REDIRECT_GATEWAY_METHOD = env("REDIRECT_GATEWAY_METHOD"); } else { var REDIRECT_GATEWAY_METHOD = 0; } # 編集後 if (env("REDIRECT_GATEWAY_METHOD")) { var REDIRECT_GATEWAY_METHOD = env("REDIRECT_GATEWAY_METHOD"); } else { var REDIRECT_GATEWAY_METHOD = -1; }
ぱっとみ環境変数を使った方がお行儀が良いかも.
次に-1の場合のルーティングを書き加える.
163行目以降の// Add internal network routes
から始まるブロックを参考にしつつ,その下に-1のパターンを追記.
IPアドレスとマスクの部分は各自置き換えてください.
// Add internal network routes echo("Configuring Legacy IP networks:"); if (env("CISCO_SPLIT_INC")) { // Waiting for the interface to be configured before to add routes if (!waitForInterface()) { echo("Interface does not seem to be up."); } for (var i = 0 ; i < parseInt(env("CISCO_SPLIT_INC")); i++) { var network = env("CISCO_SPLIT_INC_" + i + "_ADDR"); var netmask = env("CISCO_SPLIT_INC_" + i + "_MASK"); var netmasklen = env("CISCO_SPLIT_INC_" + i + "_MASKLEN"); exec("route add " + network + " mask " + netmask + " " + internal_gw); } } else if (REDIRECT_GATEWAY_METHOD > 0) { // Waiting for the interface to be configured before to add routes if (!waitForInterface()) { echo("Interface does not seem to be up."); } if (REDIRECT_GATEWAY_METHOD == 1) { exec("route add 0.0.0.0 mask 0.0.0.0 " + internal_gw + " metric 1"); } else { exec("route add 0.0.0.0 mask 128.0.0.0 " + internal_gw); exec("route add 128.0.0.0 mask 128.0.0.0 " + internal_gw); } } echo("Route configuration done."); // --------------------------------------追記した部分-------------------------------------- if (REDIRECT_GATEWAY_METHOD == -1) { // Waiting for the interface to be configured before to add routes if (!waitForInterface()) { echo("Interface does not seem to be up."); } exec("route add 大学のIPアドレス mask 大学のマスク " + internal_gw + " metric 1"); } // --------------------------------------追記終わり-------------------------------------- if (env("INTERNAL_IP6_ADDRESS")) { echo("Configuring " + env("TUNIDX") + " interface for IPv6..."); exec("netsh interface ipv6 set address " + env("TUNIDX") + " " + env("INTERNAL_IP6_ADDRESS") + " store=active"); echo("done.");
これで,大学行きの通信だけそっちのゲートウェイを使ってくれそう.
設定前と設定後のVPN接続時の,tracert www.youtube.com
の結果とか見て,ちゃんとルーティング出来てるか確認してみてください.
(Linuxだったらtraceroute
,Windowsだったらtracert
)
dockerの場所を移動した話
dockerの場所を移動した
dockerはデフォルトで /var/lib/docker
にインストールされる.
しかし,様々な理由で(システム用の容量が少ないなど),ここのデータ容量が足りなかったので,別ストレージに移した.
色々な方法がネットに散らばっているが,下のサイトで紹介されているやり方が一番簡単で分かりやすかった.
How to move docker data directory to another location on Ubuntu - guguweb.com
手順
① dockerデーモンを止める
sudo service docker stop
② /etc/docker
にある daemon.json
に以下の内容を追記
{ "graph": "/path/to/your/docker" }
自分の場合は,もとからruntimeの設定があったので,
{ "graph": "/srv/docker", "runtimes": { "nvidia": { "path": "nvidia-container-runtime", "runtimeArgs": [] } } }
③ データを移動
sudo rsync -aP /var/lib/docker/ /path/to/your/docker
④ 古いディレクトリを一旦リネーム
sudo mv /var/lib/docker /var/lib/docker.old
⑤ dockerデーモンを起動
sudo service docker start
⑥ 確認
docker run hello-world
とか色々回してみて問題無さそうだったら,古いdockerファイルを削除
sudo rm -rd /var/lib/docker.old/
AtCoder Beginner Contest 131感想戦
コンテストやったきりで復習しないマンなので,
blogに書くことによって強制的に復習するライフハック()を実践していく.
AtCoder Beginner Contest 131
A - Security
https://atcoder.jp/contests/abc131/tasks/abc131_a
解けた.
S = input() ahead = S[0] flag = False for s in S[1:]: if s == ahead: flag = True break ahead = s if flag: print("Bad") else: print("Good")
B - Bite Eating
https://atcoder.jp/contests/abc131/tasks/abc131_b
解けた.
0に近い数値を引かなきゃいけないのに,単純にminで取ってしまってちょっと手間取った.
import numpy as np N, L = map(int, input().split()) taste = [L+i for i in range(N)] taste = np.array(taste) print(sum(taste) - taste[np.argmin(np.abs(taste))])
C - Anti-Division
https://atcoder.jp/contests/abc131/tasks/abc131_c
解けた.
最初わかんねぇ!と思ったけど,紙に書いたらn個おきに割り切れるやつが来るので,
その数を引いて,重なってる部分を補正してやれば良いと気づけた.
でも正直もっと良い実装がありそう.
from fractions import gcd def lcm(x, y): return (x * y) // gcd(x, y) A, B, C, D = map(int, input().split()) if A%C == 0: wid = A else: wid = (A//C + 1) * C if wid > B: c_num = 0 else: c_num = (B-wid) // C + 1 if A%D == 0: wid = A else: wid = (A//D + 1) * D if wid > B: d_num = 0 else: d_num = (B-wid) // D + 1 E = lcm(C, D) if A%E == 0: wid = A else: wid = (A//E + 1) * E if wid > B: e_num = 0 else: e_num = (B-wid) // E + 1 print(B - A - (c_num + d_num - e_num) + 1)
D - Megalomania
https://atcoder.jp/contests/abc131/tasks/abc131_d
やったぜ,解けた.
感覚的にCの方が難しかった気がする.
締め切り時刻と,締め切り時刻までのコストの和を比較すれば良いと気づけた.
N = int(input()) A = [] B = [] for i in range(N): a, b = map(int, input().split()) A.append(a) B.append(b) tmp = zip(B, A) B, A = zip(*sorted(tmp)) total = 0 flag = False for b, a in zip(B, A): total += a if total > b: flag = True break if flag: print("No") else: print("Yes")
E, F
わかんなかったorz
D問終わった時点で.40分位残ってたけど20分位椅子を温めて諦めた.
こういうの解けるようになりたいなぁ...
PythonでOpenCVを使ってHDR画像を生成する
複数のLDR画像からHDR画像を生成する
Python3でOpenCVを使って,複数のLDR画像からHDR画像を生成する.
B4ゼミでやったことのメモ書き的なの.
以下の書いたことの上位互換がOpenCVのtutorial.
一応,Debevecさんの論文読んだ時のメモ.
環境
処理
自分がやった時は,先輩にもらった3枚のLDR画像を合成した.
モジュールの読み込み
import cv2 import numpy as np import matplotlib.pyplot as plt %matplotlib inline plt.rcParams["font.size"] = 18
画像の読み込み
最初に,露出を変えて撮影された3枚の画像を読み込む.
後で,逆露光時間(inverce exposure time)が必要になるのでexifで確認しておく.
windowsであれば,エクスプローラーの表示タブの詳細ウィンドウから露出時間を確認する.(プロパティの詳細からでも見れます)
ldr1_img = cv2.imread(input_dir + "1_window_evaluative_m1EV.JPG") ldr2_img = cv2.imread(input_dir + "2_window_evaluative_0EV.JPG") ldr3_img = cv2.imread(input_dir + "3_window_evaluative_p1EV.JPG") images = [ldr1_img, ldr2_img, ldr3_img] IETs = np.asarray([1/80, 1/40, 1/20], dtype=np.float32)
CRFの予測・HDRIの生成
HDRI生成アルゴリズムはカメラ応答関数(CRF: camera response function)を使用する.
今回はDebevecのアルゴリズムを使ってCRFを予測する.
calibrate = cv2.createCalibrateDebevec() response = calibrate.process(images, IETs) plt.plot(response[:, 0, 0], color="blue", label="blue") plt.plot(response[:, 0, 1], color="green", label="green") plt.plot(response[:, 0, 2], color="red", label="red") plt.legend();
merge_debevec = cv2.createMergeDebevec() hdr_img = merge_debevec.process(images, IETs, response)
Tonemapping
HDR画像をそのまま見ても綺麗に見れない.
なので,LDRの環境でHDRの広いレンジを自然に見れるようにトーンマッピングする.
トーンマッピングも色々な方法が考えられていて,OpenCVにも複数パターン実装されている.
- 一番単純なやつ
tonemap = cv2.createTonemap(2.2) ldr_img = tonemap.process(hdr_img) ldr_img = np.clip(ldr_img*255, 0, 255).astype('uint8')
tonemap = cv2.createTonemapReinhard(2.0, 1.0, 0, 0) ldr_reinhard_img = tonemap.process(hdr_img) ldr_reinhard_img = np.clip(ldr_reinhard_img*255, 0, 255).astype('uint8')
一応,保存
cv2.imwrite(output_dir + 'ldr.png', ldr_img) cv2.imwrite(output_dir + "ldr_reinhard.png", ldr_reinhard_img)
結果
ちょっとトーンマップのパラメータを調整した結果.
AtCoder Beginner Contest 125感想戦
コンテストやったきりで復習しないマンなので,
blogに書くことによって強制的に復習するライフハック()を実践していく.
AtCoder Beginner Contest 125
A - Biscuit Generator
https://atcoder.jp/contests/abc125/tasks/abc125_a
解けた.
A, B, T = map(int, input().split()) print(int((T+0.5)//A*B))
まあ,書かれていた通りに実装.
特に何もなかった.
B - Resale
https://atcoder.jp/contests/abc125/tasks/abc125_b
解けた.
import numpy as np N = int(input()) V = np.array(list(map(int, input().split()))) C = np.array(list(map(int, input().split()))) ans = 0 for i in V-C: if(i > 0): ans += i print(ans)
最初読んだ時に,何にもわからん.....DPとか要るんか????
ってなって絶望しかけた.
B問題で要るはずがないと思って考えたら,
価値-コストが正のものだけ選べばということに気づいてAC.
行列同士の引き算とかする時は,本当にNumPyが便利.
C - GCD on Blackboard
https://atcoder.jp/contests/abc125/tasks/abc125_c
解けなかった....
頭ワルワルTLE実装
from functools import reduce def gcd(a,b): while b!=0: a,b=b,a%b return a def gcd_list(numbers): return reduce(gcd, numbers) N = int(input()) A = list(map(int, input().split())) max_ans = 0 for i in range(len(A)): tmp = A[:i] + A[1+i:] ans = gcd_list(tmp) if max_ans < ans: max_ans = ans print(max_ans)
一個を除いた場合の最大公約数なのはわかるけど,
時間を短くする方法を思いつかなかったorz
あと,AtCoderのPythonのバージョンが3.4なので,
最大公約数を求めるgcd
はmath
モジュールじゃなくて,
fractions
モジュールにあるのを初めて知った.
Twitterで観測した解法は,
- 累積最大公約数
- 数列のテキトーな2要素(1個目と2個目とか)の約数の和集合を取って全探索
の2種類があった気がする.
2つ目の解き方もあー,言われてみればと思ったけど,
今回は1つ目の解き方でお直しした.
def gcd(a,b): while b!=0: a,b=b,a%b return a N = int(input()) A = list(map(int, input().split())) # 累積最大公約数的な head = [] tail = [] head.append(A[0]) tail.append(A[-1]) for i, j in zip(A[1:], A[N-2::-1]): head.append(gcd(head[-1], i)) tail.append(gcd(tail[-1], j)) ans = 0 for i in range(len(head)-2): tmp = gcd(head[i], tail[len(tail)-1-2-i]) if ans < tmp: ans = tmp print(max(head[-1], head[-2], tail[-2], ans))
D - Flipping Signs
https://atcoder.jp/contests/abc125/tasks/abc125_d
解けた.
import numpy as np N = int(input()) A = np.array(list(map(int, input().split()))) ans = np.zeros(1, dtype=np.uint64) even_odd = 0 mini = 1000000000 for i in A: if(i < 0): even_odd = (even_odd + 1) % 2 ans += abs(i) if(mini > abs(i)): mini = abs(i) if(even_odd == 0): print(ans[0]) else: print((ans - (mini * 2))[0])
D問題だし,やっぱ難しいな~と思って紙に書いてたら,
あれ,これ結局マイナスを自由に移動できるから,
最終的に負の数が0か1にしかならないじゃんって気づけた.