Ubuntu 18.04 で WiFi ホットスポットを作成する

インターネット上に乗っている情報が今一古かったりしたので、18.04 用に集めた情報をまとめておきます。

パッケージのインストール

必要なパッケージをインストールする。Destop だと自動で入るようだが、server だと入らないようなので、手動で入れる。

sudo apt-get install wireless-tools wpasupplicant

WiFi ホットスポット情報の作成

ifconfig などで WiFi デバイス名を取得する。仮に wlan0 とする。

nmcli コマンドで WiFi ホットスポットを作成する。

sudo nmcli device wifi hotspot ifname wlan0 con-name 'hostspot' ssid 'MyHotspot' band 'bg' password 'password1234'

/etc/NetworkManager/system-connections/hotspot を編集する。以下の行を [ipv4] 以下に追加する。

address1=192.168.0.1/24,192.168.0.1

意味としてはホストアドレス、プレフィクス、デフォルトゲートウェイとなる。

DHCP サーバのインストール

isc-dhcp-server をインストールする。

sudo apt-get install isc-dhcp-server

/etc/dhcp/dhcpd.conf を編集する。接続性のみ確認したいので、とりあえず domain-name, domain-name-server をコメントアウトし、subnet を定義する。

subnet 192.168.0.0 netmask 255.255.255.0 {
        range 192.168.0.100 192.168.0.131;
}


host myhostname {
        hardware ethernet xx:xx:xx:xx:xx:xx;
        fixed-address 192.168.0.1;
}

ここでは 192.168.0.x/24 に割り当てることとした。

/etc/default/isc-dhcp-server を編集する。INTERFACES に wlan0 を追加し、DHCPDv4_CONF, DHCPDv4_PID のコメントを外す。

wlan0 を念のために落とす。

sudo nmcli con down wlan0

DHCP サーバを再起動する。

sudo systemctl stop isc-dhcp-server
sudo systemctl start isc-dhcp-server

systemctl status isc-dhcp-server を実行して起動していることを確認する。よくあるエラーは PID や config ファイルの指定がコメントされたままになっていること。

WiFi の再起動

nmcli コマンドで WiFi を再起動する。

sudo nmcli con up hotspot

これで WiFi をホストモードで起動できたはず。

sudo nmcli device wifi

とすると現在使用しているプロファイルが表示される。

/etc/rc.local への追加

次回起動時に WiFi ホットスポットが自動で起動するように /etc/rc.local に以下の行を追加する。

nmcli con up hotspot
systemctl restart isc-dhcp-server

なお、デフォルトでは rc.local は存在しないが、作成して chmod +x /etc/rc.local することで利用可能になる。

darknet(本家)を OpenCV 4.2.0 でコンパイル

既に darknet は OpenCV 4.x 用に fork されていますが、そうとは知らず OpenCV 4.2.0 でコンパイルして躓いたところのメモです。OS は x86_64 Ubuntu 18.02.3 です。なお、CUDA 10.0, cuDNN 7.5 がインストール済みになっています。

OpenCV をインストールする前に ffmpeg 関連のファイルをインストールしておきます。apt-get によるインストールで問題ありません。

OpenCV は WITH_V4L, OPENCV_GENERATE_PKGCONFIG を ON にしておきます。Cmake を使って Makefile を生成し、make -j 4 などでコンパイルは普通に行います。出来たら make install で /usr/local 以下などにインストールします。

次に darknet をコンパイルする訳ですが、実行してみればわかりますが、image_to_ipl, ipl_to_image で使用されなくなった OpenCV API を使おうとしてコンパイルが停止します。直接 cv::Mat API を使用することにして image_opencv.cpp に以下のような修正をかけました。

Mat image_to_mat(image im) {
         Mat m = Mat(im.h, im.w, CV_8UC(im.c));
         if (im.c == 1) {
                 for (int row = 0; row < im.h; ++row) {
                         uchar *dst = m.ptr(row);
                         float *src = &im.data[row * im.w];
                         for (int col = 0; col < im.w; ++col) {
                                 dst[col] = (uchar)(src[col] * 255);
                         }
                 }
         } else {
                 for (int row = 0; row < im.h; ++row) {
                         Vec3b *dst = m.ptr(row);
                         float *src = &im.data[row * im.w];
                         for (int c = 0; c < im.c; ++c) {
                                 for (int col = 0; col < im.w; ++col) {
                                         dst[col][2 - c] = (uchar)(src[c * im.h * im.w + col] * 255);
                                 }
                         }
                 }
         }
         return m;
}

 image mat_to_image(Mat mat) {
         image im = make_image(mat.cols, mat.rows, mat.channels());
         float *data = im.data;
         if (mat.channels() == 1) {
                 for (int row = 0; row < im.h; ++row) {
                         uchar *src = mat.ptr(row);
                         for (int col = 0; col < im.w; ++col) {
                                 data[row * im.w + col] = (float)(src[col] / 255.0);
                         }
                 }
         } else {
                 for (int row = 0; row < im.h; ++row) {
                         Vec3b *src = mat.ptr(row);
                         for (int c = 0; c < im.c; ++c) {
                                 for (int col = 0; col < im.w; ++col) {
                                         data[c * im.w * im.h + row * im.w + col] = (float)(src[col][2 - c] / 255.0);
                                 }
                         }
                 }
         }
         return im;
} 

更に、CV_CAP_PROP_ などと CV_ が付いているパラメータについて、CV_ を削除します。これでコンパイルが通るはず。

おまけ: Anaconda は外しておいた方がよいようです。カメラを使う場合はユーザを video グループに参加させるのを忘れずに。

numpy vs cupy 速度比較

Anaconda の numpy がいつの間にかデフォルト mkl になっていたので、改めて numpy 対 cupy 対決をしてみました。

  • numpy: 1.16.2
  • cupy: 6.0.0b
  • CPU: intel 6960X(3.0GHz)
  • GPU: TITAN-V

結果を示すと以下の様になりました。

np(1000000):0:00:16.926656 sec
sum:250000055.953125
cp(1000000):0:00:01.184336 sec
sum:250006660.0
np(100000):0:00:01.684878 sec
sum:24998295.525390625
cp(100000):0:00:00.144552 sec
sum:24996460.0
np(10000):0:00:00.175715 sec
sum:2499707.635986328
cp(10000):0:00:00.143209 sec
sum:2499635.8

1万回ループでは殆ど差異はなく、10万回以上で10倍程度の差になっています。

CPUが今となっては非力な点があり、コア数が多く、周波数が高くAVX512 が使える 9XXX 番台だともっと高い数値が期待できると思います。

ちなみに計算時間の殆どは乱数計算が占めています。複雑な並列計算はGPU圧勝という感じでした。

最後に今回のスクリプトを掲載します。

# -*- coding: utf-8 -*-
# numpy(INTEL mkl edition) vs CuPy
import numpy as np
import cupy as cp
import datetime

# initiation...
cp.cuda.set_allocator(cp.cuda.MemoryPool().malloc)

xp = None
size=100000
loop = 1000

def func(r1, r2):
    return xp.dot(r1, r2)
    
def prepare(func, size, rem, el):
    st = datetime.datetime.now()
    r1 = xp.random.rand(size).astype(np.float32)
    r2 = xp.random.rand(size).astype(np.float32)
    rem += func(r1, r2)
    el += datetime.datetime.now() - st
    return (rem, el)

def measure(amble, size, func, count):
    rem = 0.0
    el = datetime.timedelta()
    for r in range(count):
        (rem, el) = prepare(func, size, rem, el)
    print (amble + ":" + str(el) + " sec")
    print ("sum:" + str(rem))

sizes = (1000000, 100000, 10000)
engines = (('np', np), ('cp', cp))

for s in sizes:
    for e in engines:
        xp = e[1]
        amble = e[0] + "(" + str(s) + ")"
        measure(amble, s, func, loop)

SHT31の暗電流が多い気がする

現在 SHT11 と SHT31 両方で室温と湿度を測っていますが、SHT11 の方は単4電池で1年近く持ったのに、SHT31 は単3電池でも 200 日くらいで電圧低下警告が出て止まってしまいました。

SHT31 が I2C であるのに対し、SHT11 が特殊なプロトコルだからかなとも思いましたが、自信はなし。CPU はどちらも TWEDIP を使っているので条件は同じだと思うのですが。

ちなみに SHT31 の高精度モードを使うと著しく電池のヘリが大きいです。

今更 Vocaloid を買ってみた

今まで使っていた PC が6年目を迎え、流石にWindows8.1だと辛くなってきたので、この際 MacBook Pro に乗り換えることにした。

で、なんとなくノリで Logic Pro X を買ってしまい、当然 Vocaloid5 も入れてしまった。

Vocaloid4 まではパラメータ調製が大変というイメージがあったが、5ではメニューから選んでかけ具合を調整するという形式に変更されたため、細かい調製は出来なくなっている。

喋り方はほぼ自動で制御してくれるので楽チンなのだが、音程が大きく下がって伸ばす音だと勝手にしゃくりを入れてしまうなど、若干使いにくいところもある。

付属の音声には英語と日本語があるが、英語がチンプンカンプンの私としては英語で歌詞を書くのはキツイですな。声質はどれも特徴的で一長一短という感じで曲想に合わせて使い分けていくことになるようです。

オーディオパラメータが大量に追加されているが、Logic Pro X を使う場合はそちらのエフェクターを使うと思うので、過剰な機能かなと思います。ただワンタッチでエフェクターを外して WAV ファイルを作成できるのは素晴らしい。

Logic Pro X は機能が多くてまだ覚えられません…
「Logic Pro X+ VOCALOID3 Editor 初心者からのステップアップ for Mac」という本をアマゾンで見つけて読み始めたが、MIXING で挫折しそうになっています。

勉強会に参加してみた

都内某所で開催された機械学習勉強会に参加してみた。
このような勉強会に参加するのは初めてなので、どんな感じなのかわからなかったが、この日は講義形式だった。

確率論の基本が分かっていれば理解できる内容だったが、項数が多くて途中の式変形を理解するのに苦労した。講義自体はテンポも良く、よく理解できた。

勉強会でもなければ本を読まなくなっている気がするので、たまには参加するのも良いと思いました。

Ultra96 の mini Display Port

Ultra96 は mini DisplayPort 端子なので、テレビに映したいと思い、パッシブ系の変換ケーブルを買ってきた。

違うメーカーのケーブル 2本買ってみたが、どちらもダメだった。どうやら Ultra96 のビデオ出力はデュアルモードがサポートされていない模様。

もちろん、Display Port への変換ケーブルは機能するので、DP 付きのモニタを使えばよいのだが、10インチ位のディスプレイは HDMI しかサポートしていなかったりする。

仕方がないので、HDMI モニタはラズパイ用にします。