エイバースの中の人

アプリとWEBサービスを作っているABARSのBLOGです。

CoreMLでfloat配列から推論する

Caffeと同様に、CoreMLでもMLFeatureProviderという形式でデータを与え、predictionFromFeaturesを呼び出すことで、float配列から推論を行うことができます。

任意のfloat配列からMLFeatureProviderを取得するには、MLMultiArrayにfloat配列を書き込み、MLMultiArrayを持つNSMutableDictionaryを作成し、NSMutableDictionaryからMLDictionaryFeatureProviderを生成することになります。このとき、ディクショナリのキーはmlmodelの入力層の名前になります。

NSArray *shape = @[@1, [NSNumber numberWithInt:src_w], [NSNumber numberWithInt:src_z], [NSNumber numberWithInt:src_y], [NSNumber numberWithInt:src_x]];
MLMultiArray* data = [[MLMultiArray alloc] initWithShape:shape dataType:MLMultiArrayDataTypeFloat32 error:&error];
int shape_size=1*src_w*src_z*src_y*src_x*sizeof(float);
memcpy( data.dataPointer, src, shape_size );
NSMutableDictionary *inputDict = [[NSMutableDictionary alloc] init];
inputDict[key] = data;
MLDictionaryFeatureProvider *inFeatures = [[MLDictionaryFeatureProvider alloc] initWithDictionary:inputDict error:&error];

mlmodelに対してpredictionFromFeaturesを呼び出すことで推論します。

id outFeatures = [model predictionFromFeatures:static_cast(inFeatures) error:&error];

処理結果はMLFeatureProviderで出力されます。ディクショナリのキーは出力層の名前になります。

NSSet *keys = [outFeatures featureNames];
MLFeatureValue *value = [outFeatures featureValueForName:key];
MLMultiArray* res=value.multiArrayValue;
double* fsrc = (double*)res.dataPointer;
float* fdst = (float*)dest;
for( int i=0; i<res.count; i++ ){
	fdst[i] = (float)fsrc[i];
}


predictionFromFeaturesとMLFeatureProviderの使い方はcoremltools/coremlpython/のソースコードを参照してください。

CoreMLの出力はdoubleですが、内部的にはMetalPerformanceShaderでhalf floatで実行されるそうです。How can I use half floats with CoreML neural nets?

CaffeModelをmlmodelに変換する

CaffeModelからCoreMLで使えるmlmodelに変換するにはcoremltoolsを使います。

pip install coremltools


PIPが古い場合はpipをupgradeします。

pip install --upgrade pip


以下のスクリプトをpython3で実行することでcaffemodelをmlmodelに変換します。

import coremltools
coremlmodel = coremltools.converters.caffe.convert(
        ("lenet.caffemodel", "lenet.prototxt"))
coremlmodel.save("lenet.mlmodel")


python3 coreml.py 

================= Starting Conversion from Caffe to CoreML ======================
Layer 0: Type: 'Input', Name: 'data'. Output(s): 'data'.
Ignoring batch size and retaining only the trailing 3 dimensions for conversion. 
Layer 1: Type: 'Convolution', Name: 'conv1'. Input(s): 'data'. Output(s): 'conv1'.
Layer 2: Type: 'Pooling', Name: 'pool1'. Input(s): 'conv1'. Output(s): 'pool1'.
Layer 3: Type: 'Convolution', Name: 'conv2'. Input(s): 'pool1'. Output(s): 'conv2'.
Layer 4: Type: 'Pooling', Name: 'pool2'. Input(s): 'conv2'. Output(s): 'pool2'.
Layer 5: Type: 'InnerProduct', Name: 'ip1'. Input(s): 'pool2'. Output(s): 'ip1'.
Layer 6: Type: 'ReLU', Name: 'relu1'. Input(s): 'ip1'. Output(s): 'ip1'.
Layer 7: Type: 'InnerProduct', Name: 'ip2'. Input(s): 'ip1'. Output(s): 'ip2'.
Layer 8: Type: 'Softmax', Name: 'prob'. Input(s): 'ip2'. Output(s): 'prob'.

================= Summary of the conversion: ===================================
Detected input(s) and shape(s) (ignoring batch size):
'data' : 1, 28, 28

Network Input name(s): 'data'.
Network Output name(s): 'prob'.

Xcodeに取り込むと以下のように見えます。

xcode_lenet


アプリに組み込む場合、Xcodeでは拡張子がmlmodelと表示されますが、アプリからはmlmodelcとしてアクセスする必要があります。mlmodelcにはXcodeが自動的に変換します。mlmodelcには手動で変換することもできます。

/Applications/Xcode.app/Contents/Developer/usr/bin/coremlc compile in.mlmodel out.mlmodelc

Compile .mlmodel to .mlmodelc for Xamarin.iOS?

Mac環境でlibtiffをビルドする

libtiffのダウンロードページからtiff-4.0.9.tar.gzをダウンロードします。
https://download.osgeo.org/libtiff/

./configureしたあとでmakeします。

libtiffフォルダに.libsフォルダが生成され、libtiff.5.dylibが生成されます。

デフォルトではlibtiff.5.dylibを/usr/local/libにインストールしようとするため、install_name_toolでrpath経由のパスに変更します。

install_name_tool -id @rpath/libtiff.dylib libtiff.5.dylib 
otool -L libtiff.dylib
libtiff.dylib:
@rpath/libtiff.dylib (compatibility version 9.0.0, current version 9.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.60.2)

VAEによる正常品のみからの不良品検出

製造工程の不良品を検出する場合、製造工程の不良率は低いため、不良画像をなかなか集めることができません。そのため、正常品のみから不良個所を判定する手法が求められており、AutoEncoderを使用する方法が提案されています。

AutoEncoderでは、入力画像の特徴を表すベクトルを学習します。Encoderでは入力画像を低次元の潜在変数zに写像します。Decoderでは潜在変数zから元解像度まで復元します。学習では、X->Encoder->z->Decoder->xと計算し、Xとxの誤差を最小化します。

AutoEncoderは正常品から学習しているため、不良品の特徴は捉えることができません。そのため、AutoEncoderの出力と、不良品の画像の差分を取ることで、不良個所を判別することができます。

AutoEncoderのzを直接学習せず、正規分布のパラメータを学習するようにしたのがVAEです。VAEを使用してMNISTで不良品検出をするには、以下の記事が参考になります。

Variational Autoencoderを使った画像の異常検知 前編

Colaboratoryに上記サイトのコードをコピペして実行してみます。実行結果が以下の画像です。画像上(old)がVAE、画像下(new)がVAEの損失関数をMVAEのみにしたバージョンです。1の画像を正常画像、9の画像を異常画像として、濃い青の部分が異常個所になります。このように、正常画像のみから異常画像を検出できることがわかります。

2dim


潜在変数zを2次元から4次元に変更して実行してみます。こちらの方が精度が高いように思われます。

4dim


8次元版。次数を上げすぎるとすべての特徴を表現できてしまい、異常検知が困難になります。

8dim


学習自体は正常画像のみで実行できますが、潜在変数をどれくらいの次元数に設定するかの判断のために、いくつかは不良画像が必要かと思われます。

SurfaceBook2でdGPUが認識しなくなる

SurfaceBook2はしばらく使っているとdGPUが認識しなくなります。具体的に、再起動やスリープからの復帰をすると認識しなくなり、ディスプレイを取り外して再びセットすると使えるようになります。この状態になると、毎回、ディスプレイを取り外す必要があり、とても不便です。

この問題は、PCの起動状態から、電源ボタン長押しで強制シャットダウンしたあと、20秒程度長押しでPCの電源ONすることで解消します。ただし、一度解消しても、一ヶ月程度でまた同じ問題が起きるため、再び、同じ操作をする必要があります。

Surface book2でnvidia gpuを認識しない。

MacのUnity Pluginからサードパーティのdylibを読み込む

MacのUnity Pluginはbundle形式になっています。bundleをビルドする際、bundleからサードパーティのdylibを読み込みたい場合があります。

通常の手順でdylibをリンクし、bundleをビルドした場合、otool -Lでbundleの依存関係を表示すると以下のようになります。

otool -L mybundle
mybundle:
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1454.90.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
@rpath/libthirdparty.dylib (compatibility version 0.0.0, current version 0.0.0)

このとき、@rpathからlibthirdparty.dylibが読み込まれるように設定されていますが、@rpathは$PATHなため、Unityから読み込めません。

そこで、install_name_toolで@rpathを@loader_pathに書き換えます。

install_name_tool -change @rpath/libthirdparty.dylib @loader_path/../Frameworks/libthirdparty.dylib mybundle

その上で、以下のようにContents/Frameworlsにdylibを配置すれば、dylibへのパスが通ります。

mybundle.bundle/Contents/MacOS/mybundle
mybundle.bundle/Contents/Frameworks/libthirdparty.dylib 

Unity+WindowsMRでメニューキーの入力を取得する

UnityでWindowsMRの開発を行う場合、通常はUWPでの開発が必要ですが、SteamVRをインストールしていると通常のStandaloneモードで開発することができます。その際、ProjectSettingsのXR SettingのVirtualRealitySupportのチェックボックスを入れるだけで、Main Cameraが自動的にステレオカメラになり、位置と方向が反映されます。

virtual_reality


コントローラの入力を取得する場合、スティックはInputManager、ボタンはInput.GetKeyを使用します。スティックの入力を取得するには、InputManagerで名前を登録した後、Input.GetAxis ("Horizontal2")のようにします。トリガーの入力を取得するには、Input.GetKey(KeyCode.JoystickButton14) のようにします。

input_manager


ここまで、開発は順調に進んでいたかのように見えたのですが、WindowsMRでメニューキーの入力を取得しようとしてトラブルが起きました。以下のサイトのキーコードに従って、Input.GetKey(KeyCode.JoystickButton6)としても、反応しないのです。

Input for Windows Mixed Reality

調査を進めたところ、WindowsMRでもStreamVRを使用している場合は、OpenVRのキーコードに従う必要があることがわかりました。具体的に、Input.GetKey(KeyCode.JoystickButton0)とするとキー入力が取得できました。

Input for OpenVR controllers

ヘッドマウントディスプレイは、Acer、Samsung Odyssey、Dell Visorの三種類を試しましたが、眼鏡に一番やさしいのはDell Visorでした。Oculus Goよりも余裕があり、セルフレームでも締め付けられません。



Dell Visorの箱はとても大きいので、以下のケースがおすすめです。

第29回IGポート株主総会レポート(2018/08/28)

IGポートの株主総会に行ってきました。今年の参加人数は70人程度。座席の密度が高く、過去、最大レベルの人数です。

IMG_0316

招集通知の一株純資産の訂正についてのお詫び。石川社長から、先立ってもらったメール質問への回答がありました。

”業績予想を下回ることへのお詫び。12話のシリーズの海外への納品は終わったが、監査法人の指摘により、イベント上映を行う来期に計上することになった。CGコストの増加によって、引当金を積んだ。それによって第4四半期の利益が大きく下回る。来期の赤字は、コンテンツ投資の償却負担。アニメビーンズ、マンガドアの費用など、プラットフォームへの投資。プラットフォームには資金、コンテンツ、協力者が必要。制作事業はパッケージ販売の低迷によりプリプロ予算が供与できない。アニメーターの固定費増加、受注額と実制作費の乖離。制作、営業、管理で改善に取り組む。ぷららとの提携。配信を主とする会社。オリジナルコンテンツを創出して配信することで赤字を減らす。投資案件の明確化を図る。魔法使いの嫁、曇天に笑うに続く、シナジーを産むコンテンツを模索していく。五カ年計画を策定している。同業他社よりも資本効率が悪いとの声。真摯に受け止め、経営に邁進する。事前に質問をいただき、ありがとうございました。”

以下、質疑応答です。

魔法使いの嫁の海外売上の国別の比率と中国に売れた理由。


中国と欧米の割合は非開示だが、中国の方が多い。和田社長のアイディアでPVを作り持って行った。PVを見てご購入頂いた。通常は企画書のみ。契約の内容次第で、入金が長期期間にわたることが多いがまとめて前期に支払われる内容だった。海外の書籍販売については、韓国、フランスが多くの割合を占めている。

7/3にトーマツからの監査意見。そこからの訂正について、経理、IRの人材が不足しているのではないか。


マンパワーの不足もあるが、増強している。管理部にも2名を入れた。

経営管理の問題。取締役は制作に強く関わっていて、管理が手薄になっていないか。


ウィットスタジオを立ち上げたが、全ての業務を一人でやっていた。今期から、郡司取締役に入ってもらい、外部との折衝を担当してもらうなど、分担を進める。

アニメ会社4社かかえているが、4社かかえる必要性がどれくらいあるのか。統合することで合理化できないか。


クリエイターの多様化の状況。クリエイターには、金銭的というよりは優秀なクリエイターについていきたいという面がある。多様性か必要。

IGから和田、森下が会社を作った経緯。IGだけだと中間から下が伸び悩む。よりフレッシュな作品を緊張感を持って作れるようにした。

減価償却はどのようにやっているのか。中期経営計画において2022年から急に利益があがっているのはプラットフォームの貢献によるものなのか。


映像マスターは1年で償却。コンテンツ資産は1次利用によって期間が異なる。計画は積み上げ方式。投資額から、版権収入を見込む。納品後、減価償却が抜けたタイミングで利益があがる。

劇場作品のFateを作るのも大きな要因。勝負作もぶつけたい。制作事業は作品のヒットに収益が依存する。スマホビジネスについては安定的に利益を生むプラットフォームを作るのが大事。

実写映画に出資している理由。


社員からも質問されている。サイコパスを作った時に実写の本広監督に出会ったというのが大きい。面白いものを作るという観点では同じ。本広監督が亜人を制作した。四月の長い夢は映画祭で賞をとった。

ブラッドの実写版のクオリティが低い。版権のコントロールが必要ではないか。


著作権は海外の会社からの許諾。亜人は制作をIGが受けている。IGの中に実写部隊を置いている。CGについては実写ともシナジーがある。本広監督にはヒットの法則を社員に伝えてもらう意味もあり社員になってもらった。

ROE以外の目標数値はあるのか。


利益率7%。資本効率については高めていきたいが、減価償却に出てしまうので、将来キャッシュフローを増やしていく。

アニメーションを作る環境として、世間は好景気で仕事は多いが、単価が厳しい。ただ、この状況はピンチとチャンスであり、大きなチャンスと考えている。それは、金銭的な蓄えがあるかないかというのが大きい。お金の力とクオリティに挑戦できる力というのは大きい。

絶版Z。海賊版対策として活用してはどうか。


書籍部門を閉じてコミックに集中していた。今期から書籍部門を再開する。頂いた案も検討する。

違法アップロードの対策は。


法務課長が官民連携で検討している。

版権事業の原価には何が乗るのか。


映像マスターは出資した額。コンテンツ資産はIGグループの制作費。


その後、議案採決。総会の時間は1時間15分でした。銀英伝の上映会は時間の関係で欠席しました。今年はお土産はありませんでした。

GoogleCloudStorageの公開アクセス設定

GoogleCloudStorageにアップロードしたファイルに誰でもURLでアクセスできるようにするためには、GoogleCloudStorageのBucketを公開アクセスに設定する必要があります。

公開アクセスの設定をするには、Bucketの権限設定でallUsersに読み取り権限を設定します。

公開アクセス


公開アクセスの設定を有効にすると、以下のようなURLでBucket内のファイルにアクセスすることができます。

https://storage.googleapis.com/[Bucket]/[File]

個人識別のための顔認識の学習済みモデル

個人識別のために顔認識を行う場合、FineTuningを行う方法と、FeatureExtractorを使う方法があります。

前者は、予め決まっている人物を識別したい場合に使用し、VGG16等をベースにFineTuningを行っておき、学習後の学習済みモデルを使用して人物を特定します。後者は再学習は不要な方法であり、事前に膨大な顔画像で学習させておいた学習済みモデルを使用して、その中間層のデータを取得することで、顔の特徴を示す特徴ベクトルを取得し、認識したい人物のベクトルと、カメラから取得した人物のベクトルとの距離を計算することで個人を識別します。

CNNをFeatureExtractorとして使う場合の学習済みモデルとしては、VGG Faceがあります。これは、2015年に公開されており、ネットワーク構造はVGG16です。しかし、VGG Faceは商用利用不可となっています。

そこでTensorFlowで動く商用利用可のモデルとして2017年に公開されたのが、FaceNetです。ネットワーク構造はInception ResNetとなっています。

2018年にはVGG Face2が公開されました。VGG Faceから精度が向上し、商用利用可のライセンスとなっています。ネットワーク構造はResNetとSENetの2バージョンがあります。

VGG Face2のデータセットはクリーニングされており精度が高いため、FaceNetの方でもVGG Face2のデータセットで再学習が行われ、精度が改善しています。

KerasでVGG FaceおよびVGG Face2を使うには、keras-vggfaceを使用することができます。VGG16、ResNet、SENetに対応しています。

test.pyをコメントアウトして実行すると、以下のようにデータセットの中から最も近い人を表示します。

('\n', 'RESNET50')
('\n', array([[1.2077236e-07, 6.9855632e-06, 9.1819614e-01, ..., 1.4105116e-07,
        9.3622623e-07, 9.7075758e-07]], dtype=float32))
('\n', 'Predicted:', [[[' A._J._Buckley', 0.91819614], [' Billy_Butler', 0.007661988], [' Chris_Hardwick', 0.007469104], [' A._J._Pierzynski', 0.0045922087], [' Michael_Voltaggio', 0.0044681374]]])
.('\n', 'VGG16')
('\n', array([[9.7901160e-01, 4.9870639e-08, 7.0865167e-07, ..., 5.4379225e-08,
        7.6642658e-07, 3.7070203e-07]], dtype=float32))
('\n', 'Predicted:', [[['A.J._Buckley', 0.9790116], ['David_Denman', 0.0014457349], ['Carmine_Giovinazzo', 0.0008676527], ['Robert_Buckley', 0.0007245681], ['Eddie_Cahill', 0.00041833066]]])

特徴ベクトルを取得するには、include_top=FalseにしてFC層を除外した上で推論します。VGG Face(VGG16)の場合は4096次元、VGG Face2(ResNet)の場合は2048次元になります。

model = VGGFace(include_top=False, input_shape=(224, 224, 3), pooling='avg',model='vgg16')
print model.predict(x)[0]

東証のXBRLのパーサをオープンソース化しました

東証のXBRLのzipをパースしてBSとPLを抽出するパーサをオープンソース化しました。
abars/xbrl2bspl

アーキテクチャは以下を参照下さい。
XBRLからネットネット株を探す

TDnetViewをオープンソース化しました

iOSとAndroidでリリースしている東証の適時開示情報ビューワをオープンソース化しました。プルリクエストも受け付けていますので、機能追加したい場合はプルリクエスト頂ければと思います。また、フォークして別バージョンを作成頂いてもよいかと思います。

TDnetView for iOS
TDnetView for Android

Dellのサポートでエクスプレスサービスコードがわからない場合の対処

UP2414Qを修理に出そうとしたのですが、昔のモニタにはエクスプレスサービスコードがありません。以下のサポート窓口に問い合わせたのですが、エクスプレスサービスコードが求められます。

モニタ、プリンタ、プロジェクタ、その他周辺機器
月-日 9:00-21:00
0120-981-690 | 044-556-3468

https://www.dell.com/support/incidents-online/jp/ja/jpdhs1/contactus/dynamic

この問題への対処方法は、エクスプレスサービスコードを入力せずに1分間待つというものです。これで、修理窓口に繋がります。

Unityのシェーダで右ビットシフトを行うとAndroidで不定となる

Unityのピクセルシェーダで右ビットシフト演算を行うと、floatでエミュレートされて実行されるため、Android(OpenGL ES3)における結果が不定になります。

vec = (vec >> 3);


この問題を回避するには、以下のように記述します。

vec = int(floor(vec/8.0));


また、右ビットシフト以外のビット演算は正常に動作します。

vec = (vec & 0x7);


Windows、Mac、iOSでは右ビットシフト演算も問題なく正確な値が取得可能です。

GeminiPDAの画面自動回転対応等

キーボード付きのAndroid端末であるGeminiPDAを購入したので、設定すべき項目をまとめました。

IMG_0215


画面の自動回転


GeminiPDAはデフォルトでは画面の自動回転が無効になっています。画面の自動回転を有効にするには、Appbar Settingの設定からForce LandscapeをOFFにする必要があります。

日本語キーボードで@が打てない


Gemini KeyboardをGoogle Play Storeで検索してアップデート、再起動後、Androidの入力設定から、日本語(English)を選択します。

半角/全角が機能しない


Google日本語入力ではCTRL+SHIFTで半角/全角切り替えを行うようです。

USBメモリにMacPro2013をバックアップする

AppleのTimeCapsuleが販売終了ということで、GoogleWifiに乗り換えたいと思ったのですが、問題はTimeMachineバックアップです。現状はTimeCapsuleの2TBのHDDにバックアップしているため、バックアップ先を移行する必要があります。

そこで、USBメモリにMacPro2013をバックアップしてみました。MacPro2013のSSDとUSBメモリは共に256GBモデルです。バックアップ後の結果は以下です。同容量のUSBメモリでも意外と余裕がある結果となりました。

backup


USBメモリはサンディスクのあまり目立たないものにしてみました。



特に問題はなく、GoogleWifiに移行できそうです。

IMG_0205

IMDB-WIKIによる高精度な年齢・性別推定

現在、公開されている学習済みモデルの中で、最も高精度な年齢・性別推定器であると言われているのが、IMDB-WIKI – 500k+ face images with age and gender labelsです。

imdb


Adience Benchmarkにおける認識精度は性別で91%、年齢で64%です。(Understanding and Comparing Deep Neural Networks for Age and Gender Classification

VGGベースで実装されており、モデルサイズは500MBと大きいのですが、NVIDIA ChaLearn LAP 2015 Best Paper Awardを獲得しており、miniXceptionやage/gender.netに比べ、とても安定した出力を得ることができます。

年齢に関しては0歳〜100歳までの推定確率が出力されるため、年齢ベクトルと内積することで推定年齢を出力します。性別に関してはfemaleとmaleの2カテゴリです。

学習は50万枚の顔画像を使用しており、データセットとラベルもダウンロード可能です。

AppEngineでは32MB以上のファイルをアップロードできない

AppEngineではhttpリクエストのgetとpostが32MBまでに制限されます。32MBよりも大きなファイルをアップロードする場合は、Blobstoreを使用する必要があります。

Blobstore Python API Overview

DataStore版のBlobstoreは提供が終了しましたが、GoogleCloudStorage版のBlobstore APIはdeprecatedになっておらず、使用可能です。

Feature Deprecations

AppEngineで32MB以上のファイルをアップロードする方法がBlobstore以外存在しないため、今後も使えるのではないかと考えています。

GoogleAppEngine/GoでCloudStorageのファイルを配信する方法とハマりどころ

Blobstore APIを使用するとCloudStorageのバケットが自動で作成されるため、特にCloudStorageを意識せずに使用可能です。

jslibで引数のポインタに値を書き込む

UnityでNativePluginと同様のインタフェースを持つjslibを作成することを考えます。

C#側で以下のCreate APIがあった時、JS側からhogeに値を書き込みたいとします。

 [DllImport("__Internal")]
 public static extern int Create(ref IntPtr hoge);

JS側はEmscriptenのsetValue APIで値を書き込むことができます。

Create : function(hoge)
{
  var some_value=1;
  setValue(hoge,some_value,"i32*");
}

同様に構造体へも書き込むことが可能です。

C#側の定義は以下です。

[DllImport("__Internal")]
public static extern int getInfo([In,Out] InfoStructinfo);

[StructLayout(LayoutKind.Sequential)]
public class InfoStruct
{
	public UInt32 width;
	public UInt32 height;
}

JS側の実装は以下です。

getInfo: function(info)
{
	setValue(info+0,i.width,"i32");
	setValue(info+4,i.height,"i32");
	return 0;
}

参考:Emscripten : preamble.js

Unity Collaborateでファイルが更新されない

PC1でCollaborateにアップロードした後、PC2でダウンロードした際、PC1ではアップロードに成功しているものの、PC2ではダウンロードできない場合があります。

その場合は、PC1で、Library/Collab/CollabSnapshot_*を削除した後、アップロードし直すことで、問題を解消することができます。

File is Missing bug
Recent Comments
Search
Profile

abars

アプリとWEBサービスを開発しています。最近はUnityとGAE/pyが主戦場。

ブラウザ向けMMOのメトセライズデストラクタ、イラストSNSのイラストブック、東証の適時開示情報を検索できるTDnetSearchを開発しています。

かつてエンターブレインのTECH Win誌でATULADOを連載しました。

サイト:ABARS
Twitter:abars
Github:abars

Twitter
TopHatenar
HotEntry
Counter

アクセス解析付きカウンター。あなたのBLOGにもどうですか?登録はこちらから。

TOP/ BLOG/ LECTURE/ ONLINE/ RUINA/ ADDON/ THREAD/ METHUSELAYZE/ IPHONE/ MET_IPHONE/ ENGLISH/ RANKING