メモ帳DPA

ぐぐってあまり引っかからないような何かがあったら書いたりする

自分が家に居るかどうかセンサ類無しで検知して照明空調を自動制御させる

やりたいこと

  • 自分が家に戻った際に、ディスプレイ、エアコン、照明を自動でONにする
  • 自分が家から出た際に、ディスプレイ、エアコン、照明を自動でOFFにする

閃いた方法

最初は部屋の扉に赤外線センサでも付けて判別しようかと思っていたんだけれども、もっと良い方法を思いついた。
よく考えたら外出時は端末を常時持ち歩いているので、端末が自宅のLANに繋がっている時は自分が存在すると判別できる。
単純かつ追加機器も一切要らない上にセンサ類を使うよりも確実に思える。

やったこと

  1. 携帯端末のMACに対するDHCPサーバの払い出しIPアドレスを固定する
  2. 端末に対してping打って疎通を見る
  3. 結果に応じ学習リモコンを制御

リモコンはAVC300を使っているがPCから制御の効く学習リモコンなら何でも良い。

別に学習リモコンが無い環境でも、特定アプリ立ち上げたりとかWOLさせたりとかいろいろと応用が効くと思う。

Autohotkeyスクリプト

超絶単純なのでAHKじゃなくても何でも書けるはず。

Loop{
	runwait, %ComSpec% /c ping 192.168.1.5 | find "=32" , ,Hide
	if Errorlevel ;未接続時処理
	{
		if (status=FALSE)
			continue

		ControlClick,Button49,AVC300 ; モニタ電源
		Sleep,2000
		ControlClick,Button33,AVC300 ; ライト切
		Sleep,2000
		ControlClick,Button32,AVC300 ;エアコン切
		
		status:=FALSE
	}
	else ;接続時処理
	{
		if (status=TRUE)
			continue

		ControlClick,Button49,AVC300 ; モニタ電源
		Sleep,2000
		ControlClick,Button38,AVC300 ; ライト入
		Sleep,2000
		ControlClick,Button31,AVC300 ; エアコン入

		status:=TRUE
	}
}
  • 状態が変化した際にしか動かないようにしたので、自動で立ち上がった後手動で切っても勝手に上げ直したりもない。
  • pingでわざわざfindしてるのは応答しようがしまいが戻り値が0だったから。
  • pingタイムアウトや回数を減らすと誤爆があったので、安全寄りにデフォのままで良いやってことにした。

良い

かなり正確というか完璧に判断して制御してくれている。
日々の動作が数アクション完全に無くなるってのはかなり気分が良い。


備考:一部Android端末がARPに応答しない件

一部Android端末に、ARPリクエストに応答しないバグ?があるらしく、使ってたのが対象機器だったようで見事に同事象が起きた。
Automateitで、該当のネットワークへの接続をトリガに、http://制御するPCのIP へのバックグラウンドアクセスするルールを作り、端末側からARPテーブル更新させるようにして回避した。

関連

介護用ベッドサイドテーブルのすすめ

言いたいこと

介護用ベッドサイドテーブルすごい使い勝手良いしヤフオクで1万くらいで安く買えるからおすすめ。

使用例

ベッドから横挿し可能かつ全面カバーできる幅がある

f:id:de0:20150110163246j:plain

完全にサイドテーブルとしても切り替え可能

f:id:de0:20150104204528j:plain

通常のデスクに加えてL字デスク的運用

f:id:de0:20150104204329j:plain

自炊時の作業卓

f:id:de0:20150104164436j:plain


キャスター式で一本軸かつ天板がかなり広いって点が重要。
非常に取り回しが良い。

以前のと何が違うか

広い

以前のが42x50cmだったのに対し90x45cmある。
倍以上の幅があり、小さめの普通のデスク程度の面積がある。

安定感高い

支柱は端に一本だけあるだけだがぐらつきが少ない。
耐荷重(スペックには書いてない)も結構高いと思われる。

昇降が容易

ガス式でレバーひとつで調整が可能。
いちいちネジ調整したりが不要。


でかい液晶使わないのであれば普通の机捨ててもこれ一個で行けそうな気がする。
簡易的な構成としては、普通のベッド+ノートPC+介護テーブル だけでもかなり快適な空間が実現出来ると思う。



購入

定価は5万かそれ以上するようだが、ヤフオクでちょくちょく安く出品されており、だいたい1万前後で買える模様。

オフィスチェアとかもそうだが、家具系は全体的に中古だとかなり安くなるっぽい。
自分は12000円で買えたが、もっと安く終了していた場合もあった。

主要な品のリストはAmazonで見れる(値段は高い)ので、適当に当たりをつけておきオークションアラート設定しておけばそのうち買えると思う。


関連

音ゲープレイ中何見てるか調べた+EyeTribe雑感

作った


雑感

良い点はほぼ前回書いてる通りなので、以下に追加で気になった点を書く。

The Eye Tribe 買ったので視線制御で手足を使わず本を読む - メモ帳DPA

見えてる領域に視線そのまま表示すると引きづられる

慣れれば何とかなりそうだが、地味に影響あるので分離したほうがよいと思われる。
ログを取るなり別撮りで合成するか等の手間が掛かるので割と面倒である。


画面は大きすぎても小さすぎてもよくない

でかすぎると端の精度が落ちる。「 The monitor must be max 24”」とある通りなのでこれは仕方ない。
下限については特に記載が無かったが、小さすぎるものも止しておいたほうが良い。
距離が近づくせいもあると思うが、キャリブレーションの難易度が上がり頭動かして良いエリアがだいぶ狭まる。
6.2は無理、9.7でもかなり厳しい。15~26インチくらいがベストな気がする。


ゲーム無理でしょ

公式のPVでWinタブっぽいのにEyeTribe貼り付けて手持ちでFruitNinjaやってる様子があるが、そもそも操作自体を高精度にするのが難しい上、上記の画面サイズの理由もあり実際全然使い物にならんと思う。
カーソル動かないか、爆弾切りまくるか、そうでないにしても手を前に突き出して固定する筋トレと同時プレイすることになるし誇大広告感ある。


同画面に表示さえできれば何でも使える

キャリブレートの際見ていた画面と同じ画面を見る状況にさえすれば、同座標を見ていることになる。
ソフト自体はWin/Macのみ対応だが、測定対象としては同画面から出力さえできれば何でも使える。
タブレットからEyeTribeの接続された機器にVNCすれば、難易度は高いが無理やりキャリブレート出来なくはない。
キャリブレート時のみ一時的にPCつなげば済むので、環境が許すなら表示側に外部入力さえ使えればサイネージでもゲーセンの筐体でもなんでもいけるかと。


ディスプレイ設置ユニットほしい

これも公式にディスプレイ下部にスタンド使わずくっつけてる絵があるが実際には付いてこない。
画面の前に三脚置くの結構邪魔なのであれも付けて欲しかった。
ある程度上向きの角度をつけないとならないので、そのまま貼り付けるだけでは使えず、三脚使わないと実用的な認識ができない。




EyeProofについて

http://www.eyeproof.net/

公式から出た解析用webアプリ。
抽選式のβ版だがEyeTribe持ってると数日でアカウント貰える。


今のところ静止画に対しヒートマップとスキャンパスを作成可能。ヒートマップはこれを使った。


解析対象をWeb上から登録した上でそれと連動するデスクトップアプリのレコーダを起動しデータ収集する。

多数のサンプルからのデータ収集を前提としているらしく、登録時に氏名年齢性別のデータを付加させることが出来る。解析時に特定の対象群のみに絞るような処理やそれを元にした統計処理が出来るっぽい。


選択した可視化の形式が保持されないので一枚一枚選ばなきゃならなかったり、
解析時の画像サイズが解像度に依存しないので高解像度液晶だと画面真ん中に小さすぎる表示になったり、など細かい点は気になったが全体として使い勝手は悪くないしまだβなのでそのうち何とかなると思う。


対応形式増やすつもりもあるようでwebサイトの解析はまもなく対応すると書いてある。
この調子で動画にも対応してほしい。


ソース

SDKが優秀なのでサンプルにちょっと書き足しただけ。簡単。


描画の仕方いじるだけでも地味に遊べる。
やる気はないけどメディアアートとかそういう方向に使えるんじゃねと思った。


import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.Graphics;

import com.theeyetribe.client.GazeManager;
import com.theeyetribe.client.GazeManager.ApiVersion;
import com.theeyetribe.client.GazeManager.ClientMode;
import com.theeyetribe.client.IGazeListener;
import com.theeyetribe.client.data.GazeData;

public class draw extends JPanel
{
	//ウィンドウサイズ
	final static int winwidth = 854;
	final static int winheight= 480;

	//○のサイズ
	static final int ovalsize = 30;
	//描画数
	static final int trackmax = 30;


	//解像度取得
	static java.awt.GraphicsEnvironment env = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
	static java.awt.DisplayMode displayMode = env.getDefaultScreenDevice().getDisplayMode();
	static int width = displayMode.getWidth();
	static int height = displayMode.getHeight();

	static int[][] positions = new int[trackmax][2];


	public static void main(String[] args){
	    JFrame frame = new JFrame();

		draw app = new draw();
		frame.getContentPane().add(app);

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    frame.setSize(winwidth, winheight);
		frame.setTitle("");
		frame.setVisible(true);


		final GazeManager gm = GazeManager.getInstance();
		boolean success = gm.activate(ApiVersion.VERSION_1_0, ClientMode.PUSH);

		final GazeListener gazeListener = new GazeListener(frame);
		gm.addGazeListener(gazeListener);

		Runtime.getRuntime().addShutdownHook(new Thread()
		{
			@Override
			public void run()
			{
				gm.removeGazeListener(gazeListener);
			 gm.deactivate();
			}
		});
	}

	public void paintComponent(Graphics g){

		g.clearRect(0, 0, winwidth, winheight);

		for ( int i = positions.length-1; 0 <= i ; --i ) {
			//グラデーションかける
			Color c = new Color(255 - i * (255/positions.length),
								0,
					            i * (255/positions.length),
					            80 - i * (80/positions.length) );
			g.setColor(c);

			//ポイント間の直線
			if(i!=0){
				g.drawLine(positions[i-1][0], positions[i-1][1], positions[i][0], positions[i][1]);
			}

			//ポイント
			int size = ovalsize - (ovalsize/2 * i / positions.length);
			g.fillOval(positions[i][0] - size/2, positions[i][1] - size/2, size, size);

			if(i==0){
				g.setColor(Color.WHITE);
				size = ovalsize / 2;
				g.fillOval(positions[i][0] - size/2, positions[i][1] - size/2, size, size);
			}
		}
	}

	private static class GazeListener implements IGazeListener
	{
		static JFrame parent;
		public GazeListener(JFrame frame) {
			parent = frame;
		}

		@Override
		public void onGazeUpdate(GazeData gazeData)
		{
			int Xpos = (int) gazeData.smoothedCoordinates.x;
			int Ypos = (int) gazeData.smoothedCoordinates.y;

			//履歴の保持
			for ( int i = (positions.length-1); 0 < i; --i ) {
				positions[i][0] = positions[i-1][0];
				positions[i][1] = positions[i-1][1];

			}
			positions[0][0] = Xpos * winwidth / width;
			positions[0][1] = Ypos * winheight/ height;

			if(Xpos == 0 && Ypos ==0){
				positions[0][0] = positions[1][0];
				positions[0][1] = positions[1][1];
			}

			parent.repaint();

			if(Xpos ==0 && Ypos ==0){
				return;
			}
		}
	}
}

The Eye Tribe 買ったので視線制御で手足を使わず本を読む

The Eye Tribe買った

これ

The Eye Tribe

これは何か

$99で買える視線追跡デバイスです。
目の動きを検出し入出力に使えるようになります。

これまでこの手のデバイスは専門的なくっそ高いものを使うか赤外線webcamを頭に固定して自作するかの二択だったんですが、
専用の安価な装置はこれが初なんじゃないかと思います。


先駆者としては以下が詳しい。

The Eye Tribe Trackerを使った視線の記録 - ならば
http://strangelet.hatenablog.jp/entry/2014/03/30/134912

気になったこと

置き場所に結構制約がある

It is important that the Tracker is centered relative to the monitor. The monitor must be max 24”. Note the Tracker should not be positioned above or next to the monitor as the tracking will not function optimally.

http://dev.theeyetribe.com/start/

画面は24インチまで、モニタの中央かつ下限定です。Kinectのように画面上に置くと認識しません。
自分と画面の間に三脚で立つ形になるので常設すると視界の端に入って若干気になります。

実際のところ39インチモニタでも使えましたが、画面端での精度が落ちます。

ちょっと重い

Core i7 3770で常時CPU20〜40%くらい使います。
今のところ別に困るレベルではないものの貧弱なPCだときついかも。

認識エリアが限られる

http://dev.theeyetribe.com/start/

図の位置に頭が入っている必要があります。
姿勢を崩したりするとすぐ外れるのでエリアを意識する必要があり若干面倒ではあります。
ベッドで寝ながら使いたかったんですがしょっちゅう外れるので無理でした。
(それでも完全固定が必要なITU Gaze Trackerに比べれば大幅に認識域が広いのは確かなのですが)

Win/Mac限定

iPadあたりの適当な非対応機器でも視線記録くらいには使えるんじゃないかと甘く見てましたが無理でした。

うまいこと調整できれば使えないこともなさそうですが、

  • VNCで誤魔化してキャリブレーションしてみたがあまり正確でない
  • 液晶下に置く必要があるという制約により操作時に手で領域を塞ぐ
  • 画面まで近いので認識エリアが狭い

のでなかなか厳しかったです。


実用編

何やるにしても自作しないとならない

ソフトは通信用のサーバとキャリブレーションツールしかないので全部自作する必要があります。
最初に文句ばかり書いてしまいましたがそれ以外さして不満もなく精度も結構高いです。

Basics | eyetribe-docs

仕様などはここにありますが、要は視線座標を得るくらいしかないので結構組み込みは簡単です。

割り切り大事

マウス操作はそこそこ思い通りに追従してはくれるものの細かいところの操作までは厳しいので実用的でありませんでした。
とりあえずはある程度割り切って、Leeyesで自炊本を読むときのページ送りに使うことにします。

画面左下を見たらページ送り(下キー)、画面右上を見たらページ戻り(上キー)を送るだけ。
サンプルにちょこっと手加えただけの超単純なものです。

普通に読み進めるだけで何もしなくてもページが切り替わってくのでなかなか快適です。

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;

import com.theeyetribe.client.GazeManager;
import com.theeyetribe.client.GazeManager.ApiVersion;
import com.theeyetribe.client.GazeManager.ClientMode;
import com.theeyetribe.client.IGazeListener;
import com.theeyetribe.client.data.GazeData;

public class eyeControl
{

	//角から何px範囲で操作するか
	final static int areasize  = 700;
	//最速何ms間隔で操作するか
	final static int sleeptime = 1000;
	//何回同エリアで操作するか
	final static int threshold = 5;

	//位置調整
	final static int prevOffsetX = -100;


	//解像度取得
	static java.awt.GraphicsEnvironment env = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
	static java.awt.DisplayMode displayMode = env.getDefaultScreenDevice().getDisplayMode();
	static int width = displayMode.getWidth();
	static int height = displayMode.getHeight();

	//右上
	static int prevx1 = width  - areasize +prevOffsetX;
	static int prevx2 = width  +prevOffsetX;
	static int prevy1 = 0;
	static int prevy2 = areasize;

	//左下
	static int nextx1 = 0;
	static int nextx2 = areasize;
	static int nexty1 = height - areasize;
	static int nexty2 = height;


	//操作ごとに登録
	static keySend prev = new keySend(prevx1,prevy1, prevx2,prevy2, KeyEvent.VK_UP);
	static keySend next = new keySend(nextx1,nexty1, nextx2,nexty2, KeyEvent.VK_DOWN);


	public static void main(String[] args)
	{
		System.out.println(nextx1 + "," + nextx2 + "/" + nexty1 + "," + nexty2);
		System.out.println(prevx1 + "," + prevx2 + "/" + prevy1 + "," + prevy2);

		final GazeManager gm = GazeManager.getInstance();
		boolean success = gm.activate(ApiVersion.VERSION_1_0, ClientMode.PUSH);

		final GazeListener gazeListener = new GazeListener();
		gm.addGazeListener(gazeListener);

		Runtime.getRuntime().addShutdownHook(new Thread()
		{
			@Override
			public void run()
			{
				gm.removeGazeListener(gazeListener);
			 gm.deactivate();
			}
		});
	}

	static class keySend{
		int fromX;
		int fromY;
		int toX;
		int toY;
		int keycode;

		int count;

		static Robot robot;
		static boolean waitflg;

		keySend(int X1, int Y1, int X2, int Y2,int key){
			fromX = X1; toX   = X2;
			fromY = Y1; toY   = Y2;
			keycode = key;

			count = 0;
			waitflg = false;

			try {
				robot = new Robot();
			} catch (AWTException e) { e.printStackTrace(); }
		}
		void send(int Xpos, int Ypos){
			if (waitflg){ return; }

			if( (fromX < Xpos) && (Xpos < toX) && (fromY < Ypos) && (Ypos < toY)  ){
				count++;
				if ( count < threshold ){ return; }

				waitflg=true;

				robot.keyPress(keycode);
				robot.keyRelease(keycode);

				System.out.println(keycode + " \t X:" + Xpos + "\t Y:"+ Ypos);

				try{
					Thread.sleep(sleeptime);
				}catch(InterruptedException e){}

				count=0;
				waitflg=false;
			}else{
				count=0;
			}
		}

	}

	private static class GazeListener implements IGazeListener
	{
		@Override
		public void onGazeUpdate(GazeData gazeData)
		{
			int Xpos = (int) gazeData.smoothedCoordinates.x;
			int Ypos = (int) gazeData.smoothedCoordinates.y;

			prev.send(Xpos,Ypos);
			next.send(Xpos,Ypos);

		}
	}
}

操作よりは記録向きだと思う

アイディア次第でいろいろ作れそうな気はしますが、視線操作を積極的に取り入れるべき場面はあまり無いように思います。
公式のPVでは、レシピ動画送り、楽譜送り、ページ送り、ゲームなどを紹介していましたが、実際のところゲーム以外フットペダルで済みます。
ゲームは何かしら視線制御に対応したものが出ない限り現状ではどう考えても手でやったほうがましです。


記録用途についてはいろいろと調べようがありそうです。
今のところ環境が整ってないので出来てませんが音ゲーの視線位置の追跡なんかは面白そうな気がします。気が向いたらそのうちやる。


なおエロゲーにつきましてはおおむね以下に近い結果になりましたことをここに報告して記事を終えます。

http://strangelet.hatenablog.jp/entry/2014/03/26/205039

4kアップコンバータ Seiki U-Vision 買った

これは何か

1080p映像をを2160p(4k)にアップコンバートする装置。

激安4k液晶 Seiki SE39UY04 買った - メモ帳DPA

で買ったやけに安い4kモニタと同メーカー(Seiki)が出しています。


2016年には8kなんて話もあるようですがそれ以前に4k映像が全くもって出る気配がありません。多分今後もろくに期待できないでしょう。

広いディスプレイ用途として4kモニタを買ったとは言え、4k映像があるならあったほうが嬉しいのは確かです。アップコンバートして4k映像を作ろうってのが現状一番現実的な方法になるかと思います。


購入

Seikiの液晶を過去に買っておりユーザ登録していた人は無料でもらえるそうです。
が、登録していたのですがどういうわけか結局送られてきてこないので購入。


モニタの時と同様、米Amazonから普通に日本の住所宛に買えます。
4kアップコンバータなんて多分他に存在してないので比較対象も何もありませんが凄まじくニッチな品の割に結構安いんじゃないかとは思います。

Amazon.com: Seiki SU4KC1 U-Vision Up Converting Cable: Electronics

Item Subtotal $46.99
Shipping & Handling $12.98
Total Before Tax $59.97
Shipment Total $59.97

注文から到着まで11日でした。

Amazon.com: Seiki SU4KB1 U-Vision Up Converting Adapter: Electronics

なお10ドル増しになりますがケーブル一体型でない版もあるっぽいです。


製品内容

箱にケーブル一本入ってるだけです。紙切れの一枚すらもありません。
説明は箱にあるこれで全てです。普通に機器間のHDMIケーブルとして接続に使い適当なUSB端子から給電するだけ。


仕様

細かい仕様について大した情報が見つからず買ってみるまで分かりませんでしたが、箱にしっかりちゃんと乗っていました。

ソース 出力
480p@60Hz 1080p
576p@50Hz 1080p
720p@50/60Hz 1080p
1080p@50/60Hz 1080p
1080p@24/25/30Hz 2160p

これ以外の出力では効果を得られません。インタレースは非対応。
アプコンに加えて、全パターンとも Picture Quality Enhancement がかかるとのことです。
おそらくその効果により色調が若干明るめに調整されます。他にもいろいろやってるのかもしれませんが具体的な効果は謎です。

思ってたのとちがう

アプコン後の出力が30Hzになるのは把握していましたが、他にも罠がありました。1080p@24Hz/25Hz/30Hz でないと4kになりません。720p以下はもちろん1080p@50Hz/60Hzでも駄目で、FullHD出力になります。


PS3用に買ったんですが、基本的に60Hz固定されるため、4kになる効果は得られません。(例外としてBD再生時のみは24Hzが使えそうな気もしますが未確認)
EDIDエミュレータで30Hz液晶として認識させても、PS3は30Hz出力してくれません。


出力の周波数設定できる機器ってあまり無いので、すごく対応機器が絞られて使い勝手悪いです。


ゲーム機等では周波数調整出来ませんが、PCなら好きな出力形式を選べるので、
普通に4k出力できるPCに繋いでおいて、動画再生時のみ1080pにしてアプコンかかるようにするという手もあります。
(色々と倒錯してる感じはありますが)

効果

4k対応のHDMIキャプチャボードなんて持っておらず現在10万円位するので写真で妥協です。
画像ちょっと大きめ。

遅延

原理上遅くなることはあっても早くなることは無いはずですが、感じられるレベルの遅延はありませんでした。
EX波動拳ブロッキング(5フレだっけ?)や、ウィネブ・グルスヴッヘルの入力(2フレ?)などのそこそこシビアな目押しも違和感なく成功したので、大幅に遅れる感じでは無いと思われます。


割り切るなら使える

基本的に良い品ではあるのですが、1080p@24/25/30Hz で無いと4kにならない仕様が本当に恐ろしく不便です。これさえなければ…

アプコン自体は確かに効果を実感でき、なかなか綺麗になります。
上記の比較は写真なので分かり辛いですが、特に文字のような細かいものはアプコンの有無で相当差が出ます。
また、720p以下→1080pでも意外と効果が大きいので、4k液晶持ってなくてもこれを導入するのはありかもしれません。

誰かにパクられている250favs超えの元ツイートを公式RTするbot を作った ( @pakurares / @unpakuris )

これ

@

これは何か

誰かにパクられている250favs超えの元ツイートを公式RTするbotです。

要するに @ の対象を パクリツイッタラー殺すべし で検出したパクられ側に変えたものです。

どんどん量産され続けているコピペbotとは違い公式RTなので原作者が辿れます。


「パクられてるツイート元をRTするbot」が名前です。
この前は何も考えず数秒で思いついた「パクリツイッタラー殺すべし」って名前つけてしまったばっかりに元ネタ通じてない人に僕がパクリに親を殺された人みたいに思われているので今度はちゃんと考えようと思ったけどうまい具合に思いつかず結局ラノベみたいになったのでだれかネーミングセンスの養い方を教えてくれ。

意図など

先日、パクっているユーザをブロックするツールを作りましたが、公開時は確か50くらいだったパクリが一ヶ月で1000件を超えました。
画像の一致についても検出するよう後から機能を追加しましたが、こちらも650件(テキストパクリと重複あり)検出されています。
クロール対象を広げたり記号表記のゆれを吸収するようにした影響もあるので単純にこのペースで増え続けるわけではありませんが想像を超えるえらい量で驚いてます。


250favs獲得しているツイートのおよそ1%強はパクリです。
これを多いと見るか少ないと見るかは人によるかとは思いますが、どちらにせよ現状無限に湧き続けており、今後も消えることはなさそうに感じます。


ブロックはブロックで良いのですが、若干暖簾に腕押し感あるのも否めないので、せっかく集めた情報を後ろ向きでないもうちょいポジティブな方向の他の使い道をと思いついた副産物がこれです。
前回のはパクリ側を処理するのに対し今回のはパクられ側にフォーカスしたもので、対みたいなもんですね。


ちなみにコピペの問題についてはこちらにこれ以上ないくらい纏まっているのでご覧ください。

今回の作成にあたり、ソース(特にbot.rb)も含め全面的に参考にしています。


対象の話

パクられてかつ両方250favsに達するようなものは、基本的に発信者が誰かについての依存度が低いものになります。
例えば有名人がお箸転がったなうとか書くとファンが爆笑して無数の星が付くことになるかと思いますが、他の人が書いても真顔でスルーされるだけなので、あまりパクられないかパクられても伸びない傾向にあります。
極端な例A / 極端な例B ※短いので元々パクリの判定外ですけど)


また、あるジャンルに通じていないとさっぱり理解できないようなものもあまりパクられていないように見えます。
どちらかと言うと万人に受けるような物やジャンルの規模が大きめのものほうがパクられがちです。
(個人的にはある程度尖ってるほうが好きですが処理上今回は切り捨てます)


実際の所、全部とは決して言えませんがパクられるようなツイートは単体で見てある程度面白い場合が多いです。
上記の通り、知らない人が見てもさっぱり面白くないようなものはそこそこ除外されますし、結果的に、評価の高いもののまとめとしてそれなりに使い物になるのではと期待しています。


処理について

収集したパクられツイート群からランダムに公式RTしていきます。
パクリツイッタラー殺すべしのDBをそのまま流用してるので、同様に対象は自動的に増えていきます。
対象はテキストの一致で検出されたものとと画像の一致で検出されたものの両方を使用します。


ただし、以下は除外します。

  • 一度でもパクリ側として検出されているユーザ
  • "@"を含む
  • プロフィールか本文にそれぞれ適当に設けてあるNGワードを含む
  • お気に入りがRT数より多い


NGワードは、〜ならRT、拡散、速報、過剰な草、botっぽい名前などを設定しています。あんまり厳しくはしていません。

なお、通常の広まり方で RT<fav となるケースは少なく、最後の条件を満たすものは高確率で対象のフォロワーを中心としたごく内輪で完結しているような内容(大量の副垢での爆撃等も含む)になります。


一応フィルタリングはしているものの、真のオリジナルじゃないものも時には出てくるかと思いますので、その場合は是非教えてください。


対象は結構なストックがある上に今後も増え続けるはず(現時点で1000くらいある)なので、そんなに頻繁に同じ人ばかり当たらないのではと思っていますが、過去のツイートが掘り返されるのを鬱陶しいと感じる原作者の方がいるかもしれません。
その際はお手数ですがご連絡いただければ除外します。

ついでにもう一個あるよ

@

こっちは収集したパクられツイート群ではなく、収集したツイート群全てからランダムに公式RTします。
250favs超えてて上記の除外条件に引っかからない物全てが対象になるので結構玉石混交です。


とりあえず, @ は3時間おき、@ は1時間おきで動きます。


DB欲しい方は差し上げます

パクられていないものも含めて、250favs超えのツイートの情報が結構な量(現時点で8万強)蓄積されています。

もともとよそのサービスから集めてきたものですし、いろいろな使い道がありそうなので公開したいところなのですが、サイズがちょっと大きいのと、業者がパクリbotの材料に流用すると嫌なので個別に送付します。

@ まで連絡いただければ送付します。

収集しているデータ
  • 時間
  • userid
  • tweetid
  • 本文
  • クライアント名
  • 画像url
  • 画像のsha1

他の公式RTbot

性質上RTしている側の存在は認識されにくいのもあり仕方ないですが、あまり見つからないですね。
bot側が非常に見えにくいことが公式RT方式の最大の欠点でありパクリbotに勝ち目のないポイントであるのが歯痒いところです。


せっかくなのでここで紹介しておきます。
一部はパクリツイッタラー殺すべしの情報収集元として使わせてもらっています。



パクリbotの元ツイート


RT数が急激に伸びているもの


一定数のお気に入りを獲得したもの


非公式RTが多くされているもの


艦これ画像


他にもあればぜひ教えて下さい。

パクリツイートしてる連中を一括ブロックするツール「パクころ」作った

概要

パクリで250favs以上稼いだユーザをブロックする
パクリ側をお気に入り登録していたらオリジナル側に付け替える

ここからどうぞ↓
パクころ
※8/30 ドメインを xvs.jp から de0.biz に変えました。(理由は後述)

意図

  • kill1000favs の対象外部分をカバーしようと思った
  • パクツイの森 は片っ端から拾ってしまいブロック対象として使うには精度が粗かった
  • ぱくったー は更新止まり気味だった
  • 上記の既存のパクリ検出は検出だけだったので自身のTLから見えなくしたかった
  • 星つけたのが後からパクリと判明したらイラッと来るのでどうにかしたかった

Kill 1000favs
おいでよ パクツイの森 #パク森
ぱくったー / Pakutter - うさだBlog / ls@usada's Workshop

検出のポリシー

  • @favstar250_ja、@favstar500_ja、@favstar1000_ja のいずれかによりRTされていること
  • 本文の長さが20文字以下でないこと
  • 本文が一致する他ユーザのツイートが存在すること
  • 上記を満たすツイート群のなかで投稿日時が最古ではないこと
  • useridがホワイトリストに載っていないこと(※3/22追加)
  • 投稿元クライアント名が「Tweet Button」「Tumblr」「Hatena」 でないこと(※3/23追加)
  • 判定の際に本文は ハッシュタグ、改行、スペース と 「」「」【】()()『』。、.,!!??・…'"’” を除去したものを用いる(※追加)

何もしなくても放っておけば蓄積が増えて勝手にどんどん精度が上がり続けていくのがポイントです。
とりあえず一週間放置してみてみましたが、一日5件前後くらいのペースで対象が増えています。
250favs以上なのでマックスコーヒーくらいクソ甘い基準のはずなんですがそれでもどんどん湧いてくるのでひどい状況だなあと思います。


なお、一旦パクりパクられの判定が行われても、判定は毎回過去にさかのぼってアップデートされます。
例えば、古い順に「ツイートA(オリジナル) → ツイートB(Aのパクリ) → ツイートC(AまたはBのパクリ) 」とした場合、ある時点でAが250favs到達していない場合はBがオリジナルと判定されますが、後からAも250favsに到達した場合は、AがオリジナルでBCがパクリと改めて判定されます。


現状自分のブロック基準に照らしてブロックして全く問題ないアカウントのみが検出されているように見えますが、もし何かいい感じの条件案あれば教えてください。
今後何らかの原因で誤検出がたくさん出てきたり他に良い条件付けが見つかった場合には、条件付けを変えるかもしれません。

ただし、明確な基準を設けて機械的に一定のラインを引きたいと思ってます。ブラックリスト/ホワイトリストのような人為的な選択や、 謎の複雑な重み付けのような処理は基本的には無しにしたいところです。



※3/22追記
ホワイトリストはなるべく無しにしたいと言ったが速攻で撤回しますさーせん。


乙ゲーのメーカーはキャラクター単位で複数の公式のtwitterアカウントを用意するケースが結構あるようです。全く知りませんでしたすいません。
以下の様な文面が各アカウントから投稿されブロック対象となっていました。

金久保誉 on Twitter: "ぬ・ぬぬぬーん、ぬ・ぬぬぬーん、ぬ・ぬ・ぬーんぬぬーん♪"
東月錫也 on Twitter: "ぬ・ぬぬぬーん、ぬ・ぬぬぬーん、ぬ・ぬ・ぬーんぬぬーん♪"
陽日直獅 on Twitter: "ぬ・ぬぬぬーん、ぬ・ぬぬぬーん、ぬ・ぬ・ぬーんぬぬーん♪"

こういった複垢使うケースはアカウントの文脈をわからないとパクリと全く区別がつきません。

この場合の機械的な判断は困難というか不可能なので、やっぱりホワイトリスト機能を付けました。運用でカバー。
誤検知がある場合はご連絡いただれけば、ここに適宜追加することとします。


しょっちゅう出てくるようでしたらまた考えますが、複数の公式アカウントが存在し、同一の文面を投稿し、全アカウントが250favsに到達する、ようなケースは多分滅多にないかと思ってます。



データの収集

基礎となるデータの部分は favstar に全面的に寄生しています。当然、登録していない人やbanされている人は対象になりませんし、収集対象のbotが停止した場合にも収集を継続できません。


オリジナルがあってもfavstarのbotに拾われるまで検出できないのはこの方式上避けられないので仕様です。favstarに頼らずにいい感じに処理出来る何か他の良い方法思いついたら教えてください。


twitterの制限で3200件までしか過去ログを取得できないので、favstarbotの全件を取得できていません。誰か下さい。なんでもしますから。


なお、一度収集されたら元ツイートを消しても本ツールのDBにはそのまま残ります。従って、パクリを消してもブロックの対象からは外れません。また、オリジナル側が消えた場合でもパクリはパクリ扱いのままとなります。
もし対象から外してほしい場合はパクリを消した上で私に連絡いただければ個別に対処するかもしれません。


他のお気に入り収集サービス

収集対象として、aclog や favlook あたりの併用も考えましたが、とりあえず現状では favstar だけで何とかなっているので、寄生のためにtwitter外のサイトに負荷かけるのもなんだか申し訳ないので保留としています。(そもそも本当は自分でデータ収集まですべきなのかもしれませんが)

※追記:favstarだけだと割りと取りこぼしも多いので補足としてaclogとさまざまなめりっとからも取得するようにしました。


Twitter 分析サービス - aclog
ふぁぼるっく 注目 fav


本題のツール自体の話から逸れますが、aclogは 非常に充実したapi が揃っていてあって驚きました。
今回は250favs以上の抽出の用途としては直接は使えなかったので覗いただけで終わりましたが、物凄く有用だと思います。
apiを使用している例どころかaclogに言及しているサイト自体ほとんど見つかりませんでしたが、いろいろとfavstarを凌いでいるのでもっと評価されるべきだと思います。

表示について

自分のブロック済みユーザの状態は見ていません。なので、ブロック済みのユーザでもリストに出てきます。その場合、外してもブロック解除などはしません。単純に本当に何もせずそのままです。
ブロック済みのユーザについてはもう一回ブロックしてもしなくても一緒です。

※3/24追記 :ブロック済みはデフォルトでは表示しないようにしました。タブから切り替え可能。


お気に入りの付け替えについて

お気に入りの付け替えは自分のお気に入り一覧最新200件に入っている場合が対象になります。


公式のwebからでも起こるのでツール自体とは別の話ですが、これを書いている2014/3時点で、twitterのお気に入りリストの挙動がたまにおかしいです。
登録したものがリストに載らなかったり、登録順でない変な位置に挿入されたりします。
リストに載らない場合正直どうしようもないのでまたあとで試すか諦めて下さい。

※追記
対象を最新1200件に増やしました。

リストは登録順ではなくtweetid降順だったようです。また、ブロックするとリストに載らなくなるようです。
(ブロックする前に付け替えているので付け替えは働きます)

使ったものなど

えーぴーあいとかぴーえっちぴーとかウェブアプリ周り一式全くわからんところから始めましたが、製作期間は一日数時間かける4日で出来ました。Google先生と先人たちはすごい。
言い訳にする訳じゃないですが素人の習作みたいなところは正直あると思うので、もしかすると変な挙動とかがあるかもしれません。その際はぜひマサカリ投げて教えて下さい。よろしくお願いします。


FAQ(適宜追記)

使わない機能まで許可を要求されてるように見える

twitterの許可設定がread、read+write、read+write+DMの三種類しかないのでこれで最小限である。
もうちょい機能単位で細かく設定できると良いんだけどtwitter側的にはあんまり変える気はないっぽい


はちま禁止ぶろったーの二の舞では

この失敗例は認識しており、これらを踏まえて意識的に以下の動作にしている。

  • 判定アルゴリズムを明確にする
  • なぜ対象と判定されたかを参照可能にする
  • 処理を手動選択にする

ホワイトリストは唯一人の手が入ってしまう点であるが、リスト入り"しない"ことの制御にしか介入できないので、ブラックリストを手動管理するのとは全く性質が異なる。

自動でブロックして欲しい

上記の理由によりブロック処理を自動化するつもりはない。

リスト表示が重い

レンタルサーバなのでスペックがしょぼいってのもあるんだけど、それ以上に以下の理由での影響が大きいのであんまり改善は期待できない。
非同期処理とかにしたら多少ましに見せられたかもしれないなと思ってはいるが今更作りなおす気があんまりしない。

  • ブロック状況(blocks/ids)を取得しているため
  • フォロー状況+ユーザ情報(users/lookup)を取得しているため
  • 特に初回は単純に対象ユーザが数千人出るためブラウザ側としても重い
実行が重い

これも同様にあんまり改善が期待できない。
そんな頻繁に使うもんでもないし大目に見て欲しい。

  • お気に入り一覧(favorites/list)取得してるので時間がかかる
  • ブロック(blocks/create or users/report_spam)がtwitter仕様上一件ずつしか行えない
tweetbutton等の定型文が引っかかってしまうのでは

そもそもサイトの紹介で250favs行くものは大抵何かしらいい感じのコメントを付加している。
保険として一応それっぽいクライアントは除外するようにしたが、tweetbutton,tumblr,hatenaからの定型文そのままでブロック対象として検出されたのは25万ツイート収集した現状で0件である。


パクリくらいしても良くね

これを読んで欲しい
というかそこにRTボタンがあるでしょ。

ソースくれ

あんまり公開するの前提にしてなかったし覚えながら継ぎ足し継ぎ足しして作ったのでぐっちゃぐっちゃだったりファイルにキーが入ってたりする。
githubに上げるの正直現状では躊躇われるので欲しい人は連絡してくれれば個別で送る。
そのうち整理できたら公開したいとは思うが整理できるのかわからない。

スパム報告の上限に合わせて選択できるようにして欲しい

このツールの対象に検出されることは必ずしもスパムであることを意味しないので片っ端からスパム報告するべきでない。
そもそもスパム報告機能はおまけ扱い程度で付けたのであんまりいじる気はない。

微妙に改変したパクリを認識できないのでは

パクリであっても判定条件にマッチしないものは対象とはしないので仕様である。
末尾に@なしのユーザ名を付加したり語尾をキャラに合わせて改変したりするものは検出できない。
ただ意外とそういうものでも複数のパクリbot間で共食いしあってブロック対象として結果的に割と検出できたりする。

RTは移し替えないのか

お気に入りと違ってRTはするタイミング的なものがあると思う。
検出した場合は詳細へのリンクが表示されるので取り消すなりオリジナルをRTし直すなり放っておくなり任意で判断して欲しい


アカウント潰しきれてないのでは

多少ブロックされた程度じゃ滅多に凍結されるもんでもないし、そもそもTwitter公式がどうにかしない限り確実に無限に沸くのでアカウントの存在自体は割とどうでもよいと思う。
これは完全にネーミングが良くなかったですが、自分から見える範囲のノイズを減らすのが主目的であり、どっちかというと住み分けをしたいだけだったりする。
普通は数10favsみたいなパクリが自分のTLに流れてくる確率は低いと思うので、別にブロックしてもしなくても見え方そんなに変わらんだろうし、そういうのが一杯流れてくるようだったらフォローしてる人考えなおしたほうが良いと思う。


しきい値を250favsから下げてほしい

安サーバなのでストリーミング系が使えない。
良い具合の収集方法思いつかないのと、現状既に重いのが余計に重くなる問題がある。
今の収集法のままやるとメインの取得元が250のfavstarbotであり精度が落ちそうなので現状変える気はない。
希望するならソース差し上げるので作っても良いです。


名前が酷い

わかる
そんなに使う人大勢いないと思ってくっそ適当に付けたがもうちょいちゃんと考えればよかったと思う
→「パクころ」に変えた。

検索で引っかからなくなった


こういうことっぽい。どうするか考え中。
ドメイン変えた。