suzuzusu日記

(´・ω・`)

ARP tableを監視して部屋にいるか簡易通知する方法

行きたい先に目的の人がいるかどうか簡易的に知るにはどうすべきか考えたときに同じサブネットにラップトップやスマートフォンを接続しているならARP tableのMACアドレスを見て簡易的に判断できると思ったのでやってみる

  1. 事前にMACアドレスを教えてもらう
  2. pingをサブネット内の全IPに送ってARP tableを更新する
  3. ARP tableを見てMACアドレスがあれば部屋にいると判断する

以下そのスクリプト(PowerShell)

$mac_address_target="xx-xx-xx-xx-xx-xx"

while($TRUE){
    foreach ($i in @(2..254)){
        Start-Process -WindowStyle hidden -FilePath ping -ArgumentList (" -n 1 xxx.xxx.xxx." + $i.ToString())
    }
    sleep 5

    $arp_data = -split ( arp -a | Select-String $mac_address_target )

    if($arp_data.Length -gt 1){
        echo "join"
        # 通知(ex slack, etc...)
        break
    }
    
    sleep 300

}

正直pingをブロードキャストアドレスに飛ばしてなぜ返ってこないのか分からない

Mandelbrot, Intel AVX, CImg

Intel AVXのサンプルを動かしたのでそのメモ

画像出力にはCImgを使った

  • 環境
    • Visual C++ 2017
#include <immintrin.h>
#include <complex>
#include "CImg.h"

using namespace std;
using namespace cimg_library;

// simple code to compute Mandelbrot in C++
void MandelbrotCPU(float x1, float y1, float x2, float y2,
    int width, int height, int maxIters, unsigned short * image)
{
    float dx = (x2 - x1) / width, dy = (y2 - y1) / height;
    for (int j = 0; j < height; ++j)
        for (int i = 0; i < width; ++i)
        {
            complex<float> c(x1 + dx*i, y1 + dy*j), z(0, 0);
            int count = -1;
            while ((++count < maxIters) && (norm(z) < 4.0))
                z = z*z + c;
            *image++ = count;
        }
}

void MandelbrotAVX(float x1, float y1, float x2, float y2,
    int width, int height, int maxIters, unsigned short * image)
{
    float dx = (x2 - x1) / width;
    float dy = (y2 - y1) / height;
    // round up width to next multiple of 8
    int roundedWidth = (width + 7) & ~7UL;

    float constants[] = { dx, dy, x1, y1, 1.0f, 4.0f };
    __m256 ymm0 = _mm256_broadcast_ss(constants);   // all dx
    __m256 ymm1 = _mm256_broadcast_ss(constants + 1); // all dy
    __m256 ymm2 = _mm256_broadcast_ss(constants + 2); // all x1
    __m256 ymm3 = _mm256_broadcast_ss(constants + 3); // all y1
    __m256 ymm4 = _mm256_broadcast_ss(constants + 4); // all 1's (iter increments)
    __m256 ymm5 = _mm256_broadcast_ss(constants + 5); // all 4's (comparisons)

    float incr[8] = { 0.0f,1.0f,2.0f,3.0f,4.0f,5.0f,6.0f,7.0f }; // used to reset the i position when j increases
    __m256 ymm6 = _mm256_xor_ps(ymm0, ymm0); // zero out j counter (ymm0 is just a dummy)

    for (int j = 0; j < height; j += 1)
    {
        __m256 ymm7 = _mm256_load_ps(incr);  // i counter set to 0,1,2,..,7
        for (int i = 0; i < roundedWidth; i += 8)
        {
            __m256 ymm8 = _mm256_mul_ps(ymm7, ymm0);  // x0 = (i+k)*dx 
            ymm8 = _mm256_add_ps(ymm8, ymm2);         // x0 = x1+(i+k)*dx
            __m256 ymm9 = _mm256_mul_ps(ymm6, ymm1);  // y0 = j*dy
            ymm9 = _mm256_add_ps(ymm9, ymm3);         // y0 = y1+j*dy
            __m256 ymm10 = _mm256_xor_ps(ymm0, ymm0);  // zero out iteration counter
            __m256 ymm11 = ymm10, ymm12 = ymm10;        // set initial xi=0, yi=0

            unsigned int test = 0;
            int iter = 0;
            do
            {
                __m256 ymm13 = _mm256_mul_ps(ymm11, ymm11); // xi*xi
                __m256 ymm14 = _mm256_mul_ps(ymm12, ymm12); // yi*yi
                __m256 ymm15 = _mm256_add_ps(ymm13, ymm14); // xi*xi+yi*yi

                                                            // xi*xi+yi*yi < 4 in each slot
                ymm15 = _mm256_cmp_ps(ymm15, ymm5, _CMP_LT_OQ);
                // now ymm15 has all 1s in the non overflowed locations
                test = _mm256_movemask_ps(ymm15) & 255;      // lower 8 bits are comparisons
                ymm15 = _mm256_and_ps(ymm15, ymm4);
                // get 1.0f or 0.0f in each field as counters
                // counters for each pixel iteration
                ymm10 = _mm256_add_ps(ymm10, ymm15);

                ymm15 = _mm256_mul_ps(ymm11, ymm12);        // xi*yi 
                ymm11 = _mm256_sub_ps(ymm13, ymm14);        // xi*xi-yi*yi
                ymm11 = _mm256_add_ps(ymm11, ymm8);         // xi <- xi*xi-yi*yi+x0 done!
                ymm12 = _mm256_add_ps(ymm15, ymm15);        // 2*xi*yi
                ymm12 = _mm256_add_ps(ymm12, ymm9);         // yi <- 2*xi*yi+y0 

                ++iter;
            } while ((test != 0) && (iter < maxIters));

            // convert iterations to output values
            __m256i ymm10i = _mm256_cvtps_epi32(ymm10);

            // write only where needed
            int top = (i + 7) < width ? 8 : width & 7;
            for (int k = 0; k < top; ++k)
                image[i + k + j*width] = ymm10i.m256i_i16[2 * k];

            // next i position - increment each slot by 8
            ymm7 = _mm256_add_ps(ymm7, ymm5);
            ymm7 = _mm256_add_ps(ymm7, ymm5);
        }
        ymm6 = _mm256_add_ps(ymm6, ymm4); // increment j counter
    }
}


int main()
{
    const int width = 512;
    const int height = 512;
    const int num_pixels = width*height;

    unsigned short image[num_pixels];

    //MandelbrotCPU(0.29768, 0.48364, 0.29778, 0.48354, width, height, 4096, image);
    MandelbrotAVX(0.29768, 0.48364, 0.29778, 0.48354, width, height, 4096, image);

    CImg<unsigned short> ci(width, height, 1, 3);
    unsigned short *p_ci = ci.data();
    unsigned short *p_image = image;
    for (int k = 0; k < 3; k++) {
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                *p_ci = *p_image % (30 * (k + 1));
                p_ci++;
                p_image++;
            }
        }
        p_image = image;
    }
    ci.display();

    return 0;
}

参考

f:id:suzuzusu:20170719032606j:plain

software.intel.com

The CImg Library - C++ Template Image Processing Toolkit

Pure C Project in Visual Studio

今まで雑にwin32コンソールでCを書いていたがVisual StudioでCを書くときのメモ

  1. 空のsolutionを作る
  2. 空のproject追加
  3. main.cを追加
  4. projectのプロパティ -> 構成プロパティ -> C/C++ -> すべてのオプション -> コンパイル言語の選択 を Cコードとしてコンパイル/TCにする
  5. projectのプロパティ -> 構成プロパティ -> C/C++ -> システム -> サブシステム を コンソール(/SUBSYSTEM:CONSOLE)

重複あり組み合わせ C++11

メモとして

#include<functional>
#include<vector>
#include<iostream>

using namespace std;

template<class T>
vector<vector<T>> combinations_with_replacement(const vector<T> n, int r) {
    vector<vector<T>> result;

    function<void(const vector<T>, int, vector<T>, vector<vector<T>>*)> f = [&f](const vector<T> n, const int r, const vector<T> acc, vector<vector<T>>* result) {
        if (r <= 0) {
            (*result).push_back(acc);
            return;
        }
        for (auto itr = n.begin(); itr != n.end(); ++itr) {
            vector<T> tmp_acc = vector<T>(acc);
            tmp_acc.push_back(*itr);
            f(n, r - 1, tmp_acc, result);
        }
    };

    f(n, r, {}, &result);
    return result;
}

int main(){
    auto result = combinations_with_replacement<int>({1, 2, 3, 4}, 2);
    for (auto i : result) {
        for (auto j : i) {
            cout << j << " ";
        }
        cout << endl;
    }
    return 0;
}

/*
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
3 4
4 1
4 2
4 3
4 4
*/

whywaitaフィルタ

この記事はwhywaita Advent Calendar 2016 - Adventar 21日目の記事です。

www.adventar.org

whyさんについて

whyさんは私が所属している電気通信大学MMAの先輩です。 実は高校が一緒だったりとなにかと縁があったりなかったりします。 whyさんのイメージとしてはなんかインフラ強そうな印象があります。 初めて会った時の印象は覚えてないのですがMMAの部室で再履の実験のレポートを何人かの先輩と一緒になって書いていたことは覚えています。 あと純粋だった私は本名を橘和板だと信じていたので本名聞いた時はなんで偽名使ってるんだろう、過去に悪いことしたのかなと思ったことがあります。

whywaitaとは?

突然ですが哲学的な問いをここで提示します。 いったいインターネット上に存在するwhywaitaとは何なのでしょうか。 何をもって私たちはwhywaitaを認識しているのでしょうか。

"whywaita"という文字列がwhywaitaという存在を一意にしているという意見もあると思いますが昔使ってたIDをwhywaita_oldと仮定します。 whywaitaもwhywaita_oldもwhyさんであるということは一緒なのにIDが違うと全く別の存在になるのでしょうか。仮に他のsnsのサービスでwhywaitaというIDを取得することができずwhywaita_というIDであった場合も同じことが言えると思います。

ここで現実に置き換えて考えてみましょう。例えば私がwhyさんと道ですれ違います。その時私はIDでwhyさんという存在を判断していませんし小さい子供みたいに名札に書いてある文字列から判断しているわけではありません。私はwhyさんの顔からwhyさんであるという判断をします。

ここでインターネットに戻って考えてみましょう。現実の顔に相当するものつまりwhywaitaのあのアイコンでもって認識しているという結論が導かれますね。snsでも急にアイコンを変えられると「誰だこの人?」となったことが誰しも経験していると思います。

whywaita

ここから私は全人類whywaita計画という計画を思いつきました。

whywaitaフィルタ

ffmpegのfilterとしてFrei0rを利用してwhywaitaフィルタというものを作ってみました。

こちらにdllを一応置いておきますがgithubにソースは上げたので信用できない場合はbuildしてみてください。

github.com

使い方

# buildしたfilter DLLのmat33.dllをC:\Program Files (x86)\frei0r\lib\frei0r-1\whywaita.dllに置いたとしましょう

# FREI0R_PATH環境変数を設定
$ export FREI0R_PATH="C:\Program Files (x86)\frei0r\lib\frei0r-1"
# powershellの場合は以下のようにする
# Set-Item env:FREI0R_PATH -value "C:\Program Files (x86)\frei0r\lib\frei0r-1"

# whyさんのアイコン画像を取ってきたものをC:\tmp\whywaita.pngとします
export WHYWAITA_IMG="C:\tmp\whywaita.png"

# OpenCVで顔認識に使われているカスケードファイルをC:\opencv\build\etc\haarcascades\haarcascade_frontalface_default.xmlにあるとします
export CASCADE_FILE="C:\opencv\build\etc\haarcascades\haarcascade_frontalface_default.xml"


$ ffmpeg -i INPUT.mp4 -vf "frei0r=whywaita" OUTPUT.mp4

カスケードファイルをアニメ顔を認識するものに変更すると2次元でも顔認識してくれます。

ultraist.hatenablog.com

全人類whywaita計画

実際にwhywaitaフィルタをかけた画像、動画をご覧ください。

f:id:suzuzusu:20161221160805j:plain

f:id:suzuzusu:20161221160816j:plain

f:id:suzuzusu:20161221160822j:plain

f:id:suzuzusu:20161221160826j:plain

f:id:suzuzusu:20161221160830j:plain

f:id:suzuzusu:20161221160833j:plain

僕の同期のbenevolent0505もwhywaitaになりました。最初はかなりはしゃいで協力してくれたんですが顔をあまり動かすと顔として認識にてくれなくなるので結局かなりおとなしい動画になってしまいました。あと途中で飽きたと言ってテンション自体もかなり下がってしまいました。ちなみにフレームごとに検査したので顔ばれしているフレームは除去しました。

さいごに

今回はカスケード分類器という特徴量ベースの顔認識を行いましたが動画などを見てみるとわかると思いますが顔でないものを顔と認識したり精度の面でかなり難があります。最近は猫も杓子もDeepLearningしているみたいなのでDeepLearningを用いたwhywaitaフィルタを作れたらいいかなと少し思いました。

ffmpegとFrei0r

windows環境でFrei0rをffmpegで使うための実行環境設定備忘録

ffmpegにはfrei0r対応のバイナリをBuilds - Zeranoe FFmpeg から持ってくる

visual studioでビルドしようとしたがうまく行かなったのでmingwでビルドする

TDM-GCC : Download, Download | CMake からTDM-GCC, cmakeをインストールする

Index of files.dyne.org/frei0r/ からfrei0r持ってくる

frei0rのディレクトリで以下のコマンドを実行する

cmake -G "MinGW Makefiles"
mingw32-make.exe
mingw32-make.exe install

成功するとC:/Program Files (x86)/frei0r が出来上がるのであとは以下のようにすれば使用することができる

# frei0rのdllの場所を環境変数にセットする
Set-Item env:FREI0R_PATH -value "C:\Program Files (x86)\frei0r\lib\frei0r-1"
# frei0rのフィルターはfrei0r=hogefugaでセットする
ffplay -f lavfi -i mandelbrot -vf frei0r=sobel

ちなみにwindowsffmpegでinputをwebcameraにする方法も記述する

# 使えるカメラが表示される
ffmpeg -list_devices true -f dshow -i dummy

# 私の環境下ではLogicool HD Pro Webcam C920を用いた
ffplay -f dshow -i video="Logicool HD Pro Webcam C920"  -vf frei0r=cartoon