>

2018年12月26日水曜日

コード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Globalization;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Phistory
{
    class IndexCanvas:Canvas
    {
        private static readonly DateTimeFormatInfo dtfi = new DateTimeFormatInfo();

        /// 
        /// 現在画面に表示されている目盛りを検索するためのDictionary
        /// 
        private Dictionary Up2NowIndexLabelDictionary { get; set; }
        private Dictionary Up2NowIndexRectangleDictionary { get; set; }
        
        private BitmapImage line = new BitmapImage(new Uri("images/line.bmp", UriKind.Relative));

        public IndexCanvas()
        {
            Up2NowIndexLabelDictionary = new Dictionary();
            CultureResources.ResourceProvider.DataChanged += OnResourceProviderDataChanged;
        }
        
        public void Render(long time, long scale)
        {
            // 表示開始タイマー刻み数(100ナノ秒単位)
            long begin = time;
            // 表示終了タイマー刻み数(100ナノ秒単位)
            long end = time + (long)(ActualWidth * scale);

            //目盛りの更新処理
            Dictionary nextIndexLabelDictionary = new Dictionary();
            Dictionary nextIndexRectangleDictionary = new Dictionary();
            List indicesToBeAdded = new List();
            foreach (Index index in GetIndices(begin, end, scale))
            {
                if (!Up2NowIndexLabelDictionary.ContainsKey(index))//今回表示すべき目盛りでこれまでも表示されていなかった目盛りに対する処理
                {
                    indicesToBeAdded.Add(index);
                }
                else//前回から表示されている目盛りに対する処理
                {
                    double x = (index.Time - time) / scale;
                    SetLeft(Up2NowIndexRectangleDictionary[index], x);
                    SetLeft(Up2NowIndexLabelDictionary[index], x);
                    nextIndexRectangleDictionary.Add(index, Up2NowIndexRectangleDictionary[index]);
                    nextIndexLabelDictionary.Add(index, Up2NowIndexLabelDictionary[index]);
                }
            }
            foreach (Index index in indicesToBeAdded)
            {
                double x = (index.Time - time) / scale;

                Rectangle lineRect = new Rectangle();
                lineRect.Width = 1;
                lineRect.Height = 24;
                SolidColorBrush brush = new SolidColorBrush(Util.GetForegroundColor());
                lineRect.Fill = brush;
                SetLeft(lineRect, x);
                SetBottom(lineRect, 0);
                Children.Add(lineRect);
                nextIndexRectangleDictionary.Add(index, lineRect);

                Label label = new Label();
                label.Content = index.Text;
                label.FontSize = 20;
                label.Foreground = new SolidColorBrush(Util.GetForegroundColor());
                SetLeft(label, x);
                Children.Add(label);
                nextIndexLabelDictionary.Add(index, label);
            }

            List indicesToBeRemoved = new List();
            foreach (Index index in Up2NowIndexLabelDictionary.Keys)
            {
                if (!nextIndexLabelDictionary.ContainsKey(index))//これまで表示されてきた目盛りで今回表示しない目盛りに対する処理
                {
                    indicesToBeRemoved.Add(index);
                }
            }
            foreach (Index index in indicesToBeRemoved)
            {
                Children.Remove(Up2NowIndexLabelDictionary[index]);
                Children.Remove(Up2NowIndexRectangleDictionary[index]);
            }

            Up2NowIndexRectangleDictionary = nextIndexRectangleDictionary;
            Up2NowIndexLabelDictionary = nextIndexLabelDictionary;
        }

        private void OnResourceProviderDataChanged(object sender, EventArgs args)
        {
            foreach (Index index in Up2NowIndexRectangleDictionary.Keys)
            {
                Rectangle lineRect = Up2NowIndexRectangleDictionary[index];
                if (Children.Contains(lineRect))
                {
                    Children.Remove(lineRect);
                }
            }
            foreach (Index index in Up2NowIndexLabelDictionary.Keys)
            {
                Label label = Up2NowIndexLabelDictionary[index];
                if (Children.Contains(label))
                {
                    Children.Remove(label);
                }
            }
            Up2NowIndexRectangleDictionary.Clear();
            Up2NowIndexLabelDictionary.Clear();
        }

        /// 
        /// 現在の表示範囲属性で画面に表示する目盛り情報を取得します。
        /// 
        /// 
        private List GetIndices(long begin, long end, long scale)
        {
            List retIndices = new List();

            string format;
            long interval = 0;//目盛りの間隔

            if (scale < 25920000000)
            {
                if (scale < 2000000)// 40s/200px
                {
                    format = "HH:mm:ss";

                    if (scale < 500000)// 10s/200px
                    {
                        interval = 50000000; // 5s
                    }
                    else if (scale < 2000000)
                    { // 40s/200px
                        interval = 200000000; // 20s
                    }
                }
                else if (scale < 360000000)
                { // 2h/200px
                    format = "HH:mm";

                    if (scale < 6000000)
                    { // 2m/200px
                        interval = 600000000;  // 60s
                    }
                    else if (scale < 30000000)
                    { // 10m/200px
                        interval = 3000000000; // 5m
                    }
                    else if (scale < 120000000)
                    { // 
                        interval = 12000000000;
                    }
                    else if (scale < 360000000)
                    {
                        interval = 36000000000;
                    }

                }
                else if (scale < 2160000000)
                {
                    format = "dd HH:mm";
                    interval = 216000000000;
                }
                else
                {
                    format = Util.GetMonthDateString();
                    if (scale < 8640000000)
                    {
                        interval = 864000000000;
                    }
                    else
                    {
                        interval = 2592000000000;
                    }
                }


                for (int i = 0; i < (int)((end - begin) / interval) + 2; i++)
                {
                    DateTime date = new DateTime(begin - begin % interval + i * interval);
                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    retIndices.Add(indexElement);
                }
            }
            else if (scale < 60480000000)//1week/100px
            {
                format = Util.GetMonthDateString();
                interval = 864000000000;

                for (int i = 0; i < (int)((end - begin) / interval) + 2; i++)
                {
                    DateTime date = new DateTime(begin - begin % interval + i * interval);

                    if (date.DayOfWeek == DayOfWeek.Sunday)
                    {
                        Index indexElement = new Index(date.Ticks, date.ToString(format));

                        retIndices.Add(indexElement);
                    }

                }
            }
            else if (scale < 725760000000)
            {
                format = Util.GetYearMonthString();

                DateTime date = new DateTime(begin);
                date = date.AddDays(-date.Day + 1);
                date = date.AddHours(-date.Hour);
                date = date.AddMinutes(-date.Minute);
                date = date.AddSeconds(-date.Second);
                date = date.AddMilliseconds(-date.Millisecond);
                while (date.Ticks < end)
                {

                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    if (scale < 241920000000)
                    {
                        retIndices.Add(indexElement);
                    }
                    else
                    {
                        if ((date.Month - 1) % 3 == 0)
                        {
                            retIndices.Add(indexElement);
                        }
                    }

                    date = date.AddMonths(1);
                }
            }
            else
            {
                format = "yyyy";
                DateTime date = new DateTime(begin);
                date = date.AddMonths(-date.Month + 1);
                date = date.AddDays(-date.Day + 1);
                date = date.AddHours(-date.Hour);
                date = date.AddMinutes(-date.Minute);
                date = date.AddSeconds(-date.Second);
                date = date.AddMilliseconds(-date.Millisecond);
                while (date.Ticks < end)
                {
                    Index indexElement = new Index(date.Ticks, date.ToString(format));

                    if (scale < 3153600000000)
                    {
                        retIndices.Add(indexElement);
                    }
                    else
                    {
                        if (date.Year % 5 == 0)
                        {
                            retIndices.Add(indexElement);
                        }
                    }

                    date = date.AddYears(1);
                }
            }

            return retIndices;
        }
    }
}

2018年7月17日火曜日

ひらがなかけ算九九

ひらがなを少しずつ読み始めた娘。
読めることが楽しいようで外を歩いていても看板にひらがながあると読み始める。

この意欲を有効活用するために掛け算九九をひらがなだけで作成した。

するとあら不思議、とりあえずひらがなを読みまくっていただけなのにいつの間にかいくつかは音として覚えてしまい、そのうち掛け算の概念も理解できてしまうのです。

下記URLがGoogleドライブに保存した掛け算九九一覧表です。印刷して壁に貼ってご利用ください。

https://docs.google.com/document/d/10rOZgZ2aIMBquW2hxH7Xmh8vGcC89N6-CvOPzlfFF7Y/edit?usp=sharing



2018年4月24日火曜日

Google Cloud Storage(GCS)に大量のファイルをアップロードする方法

機械学習に使うデータセットとか大量のデータをGCSにアップロードする場合はちゃんとした方法でアップロードしないと遅すぎて1月経っても終わらなかったりする。

GCSのドキュメント( https://cloud.google.com/storage/docs/object-basics?hl=ja )には
アップロード方法としてコンソール, GSUTIL, コードサンプル, REST APIの4通りの方法が記載されているがこのうちコンソール, GSUTIL, コードサンプル(python)について試して速度を見てみた。
その結果
コードサンプル(python) >> GSUTIL > コンソール
でした。
アップロードするならコードサンプル(python)がおススメです。

なお、pythonの場合コードサンプルは
def upload_blob(bucket_name, source_file_name, destination_blob_name):
    """Uploads a file to the bucket."""
    storage_client = storage.Client()
    bucket = storage_client.get_bucket(bucket_name)
    blob = bucket.blob(destination_blob_name)
    blob.upload_from_filename(source_file_name)
    print('File {} uploaded to {}.'.format(
        source_file_name,
        destination_blob_name))

となっているが注意する点は

  • from google.cloud import storage をすること。
  • コードサンプル中のbucket_nameには"gs://mybucket"の場合は"mybucket"を設定すること。
  • コードサンプル中のdestination_blob_nameには"gs://mybucket/floder1/myfile.jpg"の場合は"floder1/myfile.jpg"を設定すること。


2018年4月4日水曜日

CentOS 7 64bit にOpenCVをインストールする。

基本 https://qiita.com/estaro/items/c2f8f790dc62a9f5965f に従ってOpenCVをインストールしたが
自分の環境だとlibopencv_core.so.3.4.1のlinkの時にDSO missingとかundefined reference to symbolとか言われて困った。

結局cmakeコマンドに引数でコンパイラを指定していたのだがそこにg++を指定すべきだったのがgccをしていたのが原因だった。LinuxでC言語系開発した経験がなかったのが遠因。
(もう一つの原因は自分でgccの7.3をソースからビルドして/usr/localの下にinstallしてしまったのが事。これがデフォルトになってしまうと現状では結構文句言われてしまいかなり後悔している。)

誤:
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/gcc ..

正:
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ ..

ソース
https://github.com/opencv/opencv/issues/5435

2017年12月7日木曜日

"Large Pose 3D Face Reconstruction from a Single Image via Direct Volumetric CNN Regression"の著者のオープンソースを動かすまでに行ったことのメモ

"Large Pose 3D Face Reconstruction from a Single Image via Direct Volumetric CNN Regression"の著者 Aaron Jacksonのコードが https://github.com/AaronJackson/vrn   で公開されていたので動かしてみた。その時のメモ。

まずはOSの選定とセットアップについて。
著者によるとOSはFedora 24 and CentOS 7で確認しているとのこと。
VMWareからGPUパススルーで仮想クライアントのLinuxを入れようとしたが難しそうなのでパーティションを切ってデュアルブートでLinuxをインストールすることにする。
まずFedoraは2017/11/22現在最新の27でもcuda9.0に対応していなかったりして今後不便かもしれないので却下。またcuda8.0はfedora25のみに対応しているなどで一つのバージョンのfedoraで複数のcudaに対応していないようである。なのでCentOS7をインストールすることにした。

CentOS7はnvidiaのドライバーのインストールに苦労したが結局
https://gist.github.com/wangruohui/df039f0dc434d6486f5d4d098aa52d07
上記サイトをくまなく読めばうまくいった。但しnouveauが無効になったかどうかの確認は
http://www.demandosigno.study/entry/2016/04/30/230000
にある方法を使った。
sudo dracut --force
はタイミングを誤ったのか二回やらないとできなった。
セキュアブートの無効化は
https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn898540(v=vs.85).aspx
を参考にしたが結局自分のBIOSではwindowsのsecurity的な項目でoffにしたらうまくいった。

macからCentOSへのRDP接続はまずVNCで繋げられるようにする。
このあたりのページの通りにやればよい。
https://gtrt7.com/blog/linux/rdp-centos
https://qiita.com/takao_mofumofu/items/449b8b7bf8e58c7d4d35
しかし、NVDIAのドライバを使っている場合はデスクトップにGNOME系は使えないとのことなのでKDEを導入。
https://qiita.com/arc279/items/69518ea6dd1f45ae571f
https://www.server-world.info/query?os=CentOS_7&p=x&f=2

~/.vnc/xstartup
も編集してdesktopにstartkdeというコマンドを追加。

VNCがつなげたらxrdpも設定する。(VNCだけでもいい気がするが一応。)
http://cobitech.blogspot.jp/2015/12/centos-71-xrdp.html
の記事中色深度を32から24に変更するとのことだが自分の環境では変えなくても問題なかったが逆に/etc/xrdp/xrdp.iniにてport番号を5901にしないと5910につなごうとしてエラーになるようであった。59XXの下2桁がディスプレイ番号と対応しているらしいので今回は5901にした。

日本語入力は右下のタスクトレイから ibusらしきものを見つけて切り替えショートカットキーをctrl+qに設定した。 xstartupに
export QT_IM_MODULE=ibus
という環境変数を追加したのも効いた可能性あり。

smart card managerなるアプリが毎回起動時にポップアップして鬱陶しい件はyum remove escで解決した。


Anacondaをインストールしてデフォルトをpy3.6にした。 source activate py27でpython2.7を使用できるよう仮想環境をインストールした。

以上がOS周りのセットアップ。

以下は元々のお題である著者のコードを動かすための作業を書く。基本的には https://github.com/AaronJackson/vrn#installation-example に従うがそのとき発生したトラブルと対応を書く。

著者の上記サイトからgit cloneしてもface-alignmentのフォルダが空になっている。
これはgitのsubmoduleの仕組みを理解していないからだが下記サイトに書いてある方法で対応できる。
http://dqn.sakusakutto.jp/2013/06/git_submodule_empty_directory.html


まずtorchをインストール。途中でコンパイルエラーが出たが下記に従って環境変数を追加してからやったら CUDA9.0でもできた。(なお、最初CUDA9.0でセットアップしていたが結局後にcudnnのバージョンが合わないとか言われたのでCUDA8.0+CuDNN5.1に変更した。)
https://github.com/pytorch/pytorch/issues/2972

fb.python のインストールでも PYTHON_LIBRARIESなどがないと言われた。これは anaconda envを使っているせいで自動検索できないのではないかと予想している。
cd fblualib/fblualib/python/build
してから
ccmake ..
でcmakeのUIを起動して、tキーを押してadvanced modeにしてPYTHON関係のパスを手動で入力することで対応できた。なお設定したパスは下記の通り。
PYTHON_LIBRARIES=/home/edo/anaconda3/envs/py27/lib/libpython2.7.so
PYTHON_INCLUDE_DIRS=/home/edo/anaconda3/envs/py27/include/python2.7
このとき肝心の python  自体のパスも anaconda3/envs/py27 のものであることを確認。自分が1回目やったときはこれが/usr/bin/pythonになっていたらしくひどい目にあった。

 libiomp5.so が無いと言われるのはこのファイルをfindして見つけたフォルダを LD_LIBRARY_PATH に追加。

matio が無いと言われるのは多分luarocks intall matioで解決。(sudo yum install matioもやったが多分これは関係なかった。)

npy4th が無いと言われるのはこちらのサイトに従ってインストール
https://github.com/htwaijry/npy4th

Lapack library not found in compile timeと言われるのは
https://github.com/torch/torch7/issues/174
に従って OpenBLASをインストールしてからもういちどtorch distroをインストールすると解決。上のほうのtorchインストールの項目でも書いたがtorchのビルドでは環境変数
export TORCH_NVCC_FLAGS="-D__CUDA_NO_HALF_OPERATORS__"
の設定を忘れずに。

以上で動くことを確認したがxrdpからだとOpenGLが呼べないらしく落ちるので普通にデスクトップから動かす必要がある。

なお、このプログラムはanacondaで作ったpython2.7環境で実行する。そのため
source activate py27
を実行してpython2.7になってから行うこと。py27は自分がanacondaで作ったpython2.7用環境の名前。


2016年4月26日火曜日

"iTunes Matchはこのデバイスのミュージックライブラリに置き換わります" というダイアログはOKしてよい。

iPhoneでiTunes MatchをONにしようとすると出て来る
"iTunes Matchはこのデバイスのミュージックライブラリに置き換わります"
というメッセージ。なんとなく今まで貯めてきたCloud上の自分のライブラリがiPhoneの少量の曲で上書きされてしまうと解釈してしまいそうだが、そうではない。正しくは"iTunes Match「が」このデバイスのミュージックライブラリに置き換わります"という意味で今使っているiPhoneのライブラリがiTunes Matchのたくさんの曲で上書きされるという意味らしい。

※このメッセージの意図はiTunes MatchをONにするとiPhoneだけに保存されている曲は消えてしまうのでそのような曲がある場合はあらかじめバックアップをとっておく必要があるという注意喚起のようである。


2016年1月17日日曜日

Amazon EC2を安全に使うために最低限やっておくこと。

※2015/12/25現在の情報です。
自分の家のPCにGeForceがないのでAmazon EC2でやってみることに。
Amazon EC2でGPUが使えるインスタンスを起動すると大体1時間に1ドルくらいかかるのでインスタンスの停止し忘れとかは非常に怖い。そういうことがないように最低限やっておくべき設定のメモ。


実際のインスタンスでCUDAが使えるようにする設定方法はすでに様々な記事があって例えば
http://sla.hatenablog.com/entry/chainer_on_ec2
この辺を参考に構築できます。

Amazon AWSの請求金額の総額が一定金額を超えた時にアラートメールが来るように設定する。


https://aws.amazon.com/jp/
上記URLからAmazon AWSのコンソールにサインイン。
サインインすると表示されるコンソール画面の一番上のメニューバーから自分のアカウント名をクリックするとドロップダウンメニューが表示される。その中から、「請求とコスト管理」をクリック。

請求情報とコスト管理ダッシュボード
にて
アラートおよび通知
というセクションがありこの文章中に「初回請求アラームの設定」というリンクがあるのでクリック。(下図)

「アラームの作成」をクリック(下図)

あとは表示されるダイアログに従って通知の閾値にする金額とe-mailアドレスを設定してアラームを作成する。必ずまずは$1とかの低額に設定してEC2を利用してあえてその閾値を超えさせてみて通知メールが実際に届くことを確認する。そして忘れずに閾値の金額を適切な値に再設定する。