ZawaWorks’s diary

ProcessingやNode.jsなどプログラミング技術の話をします。

Android×Processing:adb input touchscreen編

はじめに

 この記事ではProcessingを使ってAndroid端末を操作しようと思います。

環境設定

'input touchscreen'

 タッチや直線のスワイプといった単純な操作にはinput touchscreenを使います

タッチの場合
  • adb shell input touchscreen tap x y
  • 画面上の座標の(x,y)にタップする命令
  • xとyは10進数
スワイプの場合
  • adb shell input touchscreen swipe x1 y1 x2 y2 t
    • (x1,y1)から(x2,y2)までをスワイプする命令
    • tはミリ秒 f:id:ZawaWorks:20171029022807p:plain

Processingとの連帯

今回使う命令
launch()
例:adb shell input touchscreen tap x y
String [] AdbTap = {"adb","shell","input","touchscreen","tap",str(x),str(y)};//xとyはString型に変換


launch(AdbTap);
input tapの場合

コード

String [] AdbTap = {"adb", "shell", "input", "touchscreen", "tap", "", ""};
  
  void setup() {
    size(360, 640);//Xperoa XZの解像度は 1080 x 1920
    background(0, 0, 255);
  }
  
  void draw() {
    if (!mousePressed) return;
  
    fill(-1);
    ellipse(mouseX, mouseY, 15, 15);
  
    AdbTap[5] = str(mouseX*3);
    AdbTap[6] = str(mouseY*3);
  
    launch(AdbTap);
  }

デモ

youtu.be

input Swipeの場合

コード

ArrayList<PVector>vector = new ArrayList();
Boolean launch_able = true;

int time = 100;

void setup() {
  size(360, 640);
  background(0, 0, 255);
}

void draw() {
  background(0, 0, 255);

  for (int i=0; i<vector.size(); i++) {
    PVector v = vector.get(i);

    fill(-1);
    ellipse(v.x, v.y, 20, 20);
  }

  if (vector.size() != 2) return;

  PVector v1 = vector.get(0);
  PVector v2 = vector.get(1);
  stroke(-1);
  line(v1.x, v1.y, v2.x, v2.y);

  if (!launch_able)return;
  launch("adb shell input touchscreen swipe"+" "+ v1.x+" "+ v1.y+" "+v2.x+" "+v2.y+" "+time);
  launch_able = false;
}

void mousePressed() {
  if (vector.size()%2 == 0) {
    vector = new ArrayList();
    launch_able = true;
  }

  vector.add(new PVector(mouseX, mouseY));
}


デモ

youtu.be - t = 100のときとt = 50のときを比較

GitHub

github.com

参考資料

www.excite.co.jp

 

Android×Processing:adb getevent編

はじめに

 前に紹介したadbコマンドをProcessingと組み合わせてみました。この記事ではAndroid端末のタッチイベントをProcessingを使ってリアルタイムでアニメーションします。

環境設定

  • Processing3.3.6
  • Xperia XZ
  • Windows10

おさらい

 adbのgeteventコマンドが分からない方は前の記事を読んでから次へ進んでください。

zawaworks.hatenablog.com

実装方法

 今回使うコマンドはadb shell getevent -ltです。これで得たログデータをテキストファイルに書き込み、それをProcessingで読み込みます。

用意するディレクト

  • AdbGeteventフォルダー
    • AdbGetevent.pde
    • dataフォルダー
      • pos.txt

AdbGetevent.pde

void setup() {
  size(360, 640);

  //テキストファイルを空に
  PrintWriter output;  
  output = createWriter("data/pos.txt");
  output.close();
}

void draw() {
  background(0, 0, 255);

  //テキストファイルを読み込む
  String []lines = loadStrings("data/pos.txt");

  float posX = 0;
  float posY = 0;

  for (int i=0; i<lines.length; i++) {

    int getx_point = lines[i].indexOf("ABS_MT_POSITION_X ");
    int gety_point = lines[i].indexOf("ABS_MT_POSITION_Y ");


    if (getx_point != -1) { 

      String result = lines[i].substring(getx_point+21, getx_point+29);

      posX = unhex(result) / 3.0;//Processingの画面に合わせる

      continue;
    }

    if (gety_point != -1) {

      String result=lines[i].substring(gety_point+21, gety_point+29);

      posY = unhex(result)/3.0;//Processingの画面に合わせる

      noStroke();
      fill(-1);
      ellipse(posX, posY, 10, 10);
    }
  }
}

使い方

  • はじめにAdbGetevent.pdeを実行させる
  • dataディレクトリの中でadb shell getevent -lt > pos.txt
  • スマホを操作するとジェスチャの動きが描画される

デモ


Processing×ADBコマンド:getevent編

  • 使用したアプリ

play.google.com

GitHub

github.com

Processing:コマンドプロンプトを開いてみた

はじめに

 今回はProcessingでコマンドプロンプトを開くことを試みました。今回見つけた方法をそれまでの失敗を含めて紹介していきたいと思います。

環境設定

  • Windows10
  • Processing 3.2.1

launch()を使ってみる

 launch()はProcessingからファイルを実行できる命令です。 たとえば

void setup(){
  launch("notepad.exe");

}

というコードを実行すればメモ帳が開かれます。これの応用でlaunch("cmd.exe")と書き直して実行しました。

しかし動かない!

 ここで躓いた僕はいろいろと原因を探してみました。

絶対パスが原因?

 このサイトを見ると、絶対パスにしたことで解決した例がありました。それを参考にlaunch("C:\\Windows\\System32\\cmd.exe")と入力してみました。

しかし動かない!

 

リファレンスを読んでみた

 ここで諦めそうになった僕ですが、リファレンスを読み返してみました。するとこんな一文が……。

This function behaves differently on each platform. On Windows, the parameters are sent to the Windows shell via "cmd /c".

 どうやらlaunch()に書いた文字列をコマンドプロンプトに送って実行してるようです。コマンドプロンプトcmd.exeを開くときstart cmd.exeと打つので試しに以下のようなコードを書きました。

void setup(){
  launch("start cmd.exe");

}

 これを実行すると……。

f:id:ZawaWorks:20171024003501p:plain

動いた!!! 

 当初の目的通り、Processingでコマンドプロンプトを開くことに成功しました!

ついでに

 これで目的は達成しましたが、ついでに開いたコマンドプロンプトが実行したpdeファイルの入ったディレクトリ行くようにする方法も見つけました。これはバッチファイルというものを使います。バッチファイルはコマンドプロンプトで実行する命令をまとめたテキストファイルです。これに指定したディレクトリをたどり着き、かつ、コマンドプロンプトを実行するという命令を書き込みます。それをlaunch()で実行します。

コード
void setup() {
  PrintWriter output = createWriter("data/test.bat");
  output.println("cd"+" "+sketchPath());
  output.println("start cmd.exe");
  output.flush();
  output.close();

  launch(dataPath("test.bat"));
}
実行の様子

f:id:ZawaWorks:20171024003051p:plain

(sketchPath()dataPath()が分からない人はこちらを参考にしてください)

最後に

 ただ開くだけだとlaunch("start cmd.exe")でいいですがバッチファイルを使った方が汎用性があるように感じました。Windowsユーザの皆さんは試してみると良いかもしれません。

参考・参照サイト

JavaScript:コード画像をテキストファイルに変換する

はじめに

 僕が通っている大学ではCMP実習という授業があり、そこでHTMLやCSSJavaScriptを教えてもらいます。その課題で「JavaScriptのライブラリを使ったプログラムを作ってきてね」と言われたので僕はTESSERACT.jsという文字認識ライブラリを使いコード画像をテキストファイルに変えるWebサービス「ImageCode」を作りました。今回はそれを作った背景とコードについて解説していきたいと思います。

 

ImageCodeを作った理由

 以前、プログラミングの記事を読んでいて「使いたい!」と思ったコードがありました。しかし、それをコピペすることができませんでした。なんとそのコード、画像ファイルだったんです。たぶんテキストエディタに書いたコードをスクショして貼り付けたのだと思います。仕方なく僕はそのコードを画像のまま写すことに……。

 そうやって画像のコードを写すのは億劫でした。そこで僕は「コードの画像をそのままテキストファイルにすればいいのでは?」と考えてImageCodeを作りました。

 

環境設定

TESSERACT.js

f:id:ZawaWorks:20171011044647p:plain

 画像に書いてある文章を文字認識してくれるライブラリです。現在、英語、中国語、ロシア語に対応しています。今回はプログラミングコードを文字認識するため、英語の文字認識を使います。ブラウザで使うときはHTMLに下記のURLをscriptタグに入れればOKです。

 

 GitHubに上がっているサンプルは下記の通りです。 

Tesseract.recognize(myImage)
.progress(function (p) { console.log('progress', p) })
.then(function (result) { console.log('result', result) })
 

 このmyImageに画像URLを入力するとresultに文字を抽出した結果がJSON形式で返されます。progressは現在の進行状況を教えてくれます。今回は使わないので省きました。

 

画像ファイルを選択して表示させる

mementoo.info 上の記事を参考に自分のPCのフォルダーから画像を選択し、描画と画像情報の取得するコードを作りました。

 

HTML側

<img src="" id="original">
<input type="file" onchange="reader.readAsDataURL(this.files[0])">

JavaScript

var img = document.getElementById('original')
var reader = new FileReader()

reader.onload = function () {
//アップロードした画像データをimgタグに挿入
img.src = reader.result
}

original.onload = function () {
//画像をテキストデータに変える処理を書く
 
}

 

textareaの文字をテキストファイルとして保存

 文字認識で取得したコードはtextareaに設定し、保存ボタンを押したらそれをテキストファイル化しダウンロードするようにします。

 

oshiete1.nifty.com textareaの文字列のテキストファイル化は上の記事を参考にしました。変更点は三つあります。まず今回は僕が親しんでいるpdeファイル(Processingのファイル)にしたいため「text/plain」を「application/processing」に、「.txt」を「.pde」に変えています。もう一つの変更点はデフォルトのファイル名を「myText」から「sketch」にしていますが、これは単純に好みです。

 コードは以下の通りになります。

 

HTML側

<input id="name" placeholder="ファイル名">.pde<br>
<textarea id="text" rows="10" cols="50" value=""></textarea>
<button onclick="TextSave()">保存</button>

JavaScript

function TextSave() {

var text = document.getElementById('text').value
var name = document.getElementById('name').value || 'sketch'


var blob = new Blob([text], { type: 'application/processing' })


var link = document.getElementById('DL_link')

link.href = window.URL.createObjectURL(blob)


if ('download' in link) {
link.download = name + '.pde'
link.click()


} else {

link.textContent = '右クリックから名前を付けて保存してください'

}

}

 

最終コード

 さてこれらのコードを組み合わせていきます! ついでにCSSも書きました。

 

index.html

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ImageCode</title>
<link rel="stylesheet" href="./css/style.css">
<div id="inputer">
<input type="file" id="input" value=""
onchange="reader.readAsDataURL(this.files[0])">
<button onclick="TextSave()">保存</button>
<a id='DL_link'></a>
</div>
id="original">
tesseract.js/1.0.10/dist/tesseract.js'></script>
<script src="./js/main.js"></script>
</head>

<body>
<div id="code">
<h2>コード</h2>
<input id="name" placeholder="ファイル名">.pde<br>
<textarea id="text" rows="10" cols="50" value=""></textarea>
</div>


</body>

</html>

 imgタグにはデフォルトで「画像をアップロード」と書かれた画像を挿入しています。

main.js


var img = document.getElementById('original')
var reader = new FileReader()

reader.onload = function () {
img.src = reader.result
}

//画像が変わったら実行
original.onload = function () {
//画像をテキストデータに変える
Tesseract.recognize(img)
.then(function (result) {
document.getElementById("text").value = result.blocks[0].text;
})
}


//テキストファイルを保存する関数
function TextSave() {

var text = document.getElementById('text').value
var name = document.getElementById('name').value || 'sketch'


var blob = new Blob([text], { type: 'application/processing' })


var link = document.getElementById('DL_link')

link.href = window.URL.createObjectURL(blob)


if ('download' in link) {
link.download = name + '.pde'
link.click()


} else {

link.textContent = '右クリックから名前を付けて保存してください'

}

}

 

style.css

img{
margin: 0px;
float : left;
width: 50%;
height: auto;
border: 5px solid #000;
}

#inputer{
float : right;
}

#code{
margin-top: 0px;
margin-bottom: 0px;
margin-left: 0px;
margin-right: 5%;
float : right;
}


@media screen and ( max-width:1000px ){
img{
width: 80%;
}

#inputer{
float : left;
}

#code{
float : left;
}

}

 

GitHub

github.com

完成図

f:id:ZawaWorks:20171011055523p:plain

 

 こちらのリンクからデモを体験できます。(ImageCode)僕は下の画像を使ってコード生成をしました。(ライブラリの性能的に誤字が発生するのでなるべく発生しないように工夫した画像ですので、)下の画像で試すのを推奨します。

推奨画像

 f:id:ZawaWorks:20171011054828p:plain

最後に

 生のJavaScriptに触れたことがあまりなく、授業で習ったばかりでHTMLやCSSの書き方もおぼつかないところがあると思いますが、なんとか完成させることができました。

 今回はpdeファイル限定ですが、今後は他のファイルでも対応させたり、文字認識の性能を上げていきたいと思います。

Processing:絶対パスを返してくれるsketchPath()

はじめに

 ProcessingでTwitter botに画像をツイートさせようとしたら、「画像の相対パスではなく絶対パスを送ってくれないとダメです!」と言われてしまいました。そのときはその画像があるフォルダーまで「C:\Users\Documents\・・・\image.png」と書いきましたが、毎回これをやるのはだるいですよね。それで今回はその問題を解決してくれる「sketchPath()」と「dataPath()」について紹介しようと思います。

 

sketchPath()とdataPath()

 百聞は一見に如かず、まずは下のコードと出力データをご覧ください。

f:id:ZawaWorks:20171008214633p:plain

 

 なんとなくわかった方もいると思いますが、詳しく説明していきます。


フォルダやファイルの構成

フォルダとファイルは下のような構成になっています。

f:id:ZawaWorks:20171008211353j:plain

sketchPath()

 sketchPath()は実行するpdeファイルが入っているフォルダーの絶対パスを返してくれる命令です。今回の場合は「C:\Users\Documents\path_search」を返してくれます。

 またそのフォルダー内のフォルダやファイルを参照するときは「sketchPath("image1.png")」や「sketchPath("data/image2.png")」と書きます。

 まとめるとこんな感じです。

f:id:ZawaWorks:20171008213220p:plain

dataPath()

 次にdataPath()についてです。dataPath()は実行するpdeファイルと同じフォルダーの中にあるdataフォルダー絶対パスを返してくれます。今回の場合は「C:\Users\Documents\path_search\data」を返してくれます。

 つまり、先ほどの 「sketchPath("data/image2.png")」は「dataPath("image2.png")」と書き換えることが可能です。

 ここで注意なのですがsketchPath()の場合は「sketchPath()」と書くだけで絶対パスを返してくれましたが、dataPath()の場合はカッコの中にString型を入れなければいけません。「C:\Users\Documents\path_search\data」と返してほしいときは「dataPath("")」と書きしょう。

 まとめるとこんな感じです。

f:id:ZawaWorks:20171008213115p:plain

 

おわりに

 今までProcessingで絶対パスが指定できないイライラがこれで解消できました!

 便利な命令ですので、ぜひ使っていきましょう。

 

参考資料

forum.processing.org

 

Processing: length? length()? size()?

はじめに

 Processingで配列や文字列、ArrayListなどを使っているときにいつも「これって列の長さ出すのlengthだっけ? length()だっけ? size()だっけ?」悩んでしまいます。というわけで同じ悩みを持つ人がいると信じてここにまとめておきます。

環境設定(一応)

Processing3.2.1

length

 lengthは配列の長さを求めるときに使います。

int [] num ={1, 2, 3};

println(num.length);//「3」と出力される

 

length()

 length()は文字列の長さを求めるときに使います。

String str = "length";

println(str.length());//「6」と出力される

 

size()

 size()はArrayListJSONなどの長さを求めるときに使います。配列、文字列以外はsize()と覚えておくといいかもしれません。

ArrayList<Integer> num = new ArrayList();

for (int i=0; i<9; i++) {
num.add(i);
}

println(num.size());//「9」と出力される

 

最後に

 lengthは配列、length()は文字列、それ以外はsize()

 これを覚えておけばもう間違えることはありません!
 それでも間違えそうになったらまたこの記事を参考にしていただければと思います。
 


 

ADB : Androidのタッチイベントを取得してみた

はじめに

 スマートフォンでユーザがどこをタッチしたのかのログデータを取得したい人に朗報です。Android端末ならそれができます。それを実現するのが「ADBコマンド」です。

 

環境設定

 

準備

 今回の記事ではADBコマンドを使います。ADBコマンドを導入する方法をざっくり言うと以下の通りです。

  1. JDKのインストール
  2. Android SDKツールのインストール
  3. Pathを通す

 

詳しくは「windowsでadbコマンドを使えるようにする方法」を参照してください。

 

ADBコマンド

今回扱うコマンドは以下の通りです。これをコマンドプロンプトに入力してください。


1. adb devices

PCに接続されてるデバイスが表示されます。

f:id:ZawaWorks:20170925142027p:plain

2.  adb shell getevent

タップした座標やどれくらいの強さでタップしたかを取得し、そのデータをリアルタイムで返してくれる。


f:id:ZawaWorks:20170925113318p:plain

ちなみに何の結果が帰ってきているかは以下の表の通りです。

f:id:ZawaWorks:20170925114847p:plain

TouchContext: タッチ操作の挙動分析に基づく 人のコンテキスト認識 より引用

 

 

ちなみに「adb shell getevent -tl」で見やすい形でデータが帰ってきます。

Gyazo

 

3. adb shell getevent>hoge.txt

 先ほどのコマンドに「>hode.txt」とつけると、今までコマンドプロンプトに表示されていたデータがhoge.txtに書き込まれます。そのときデータはコマンドプロンプトには表示されなくなります。

 
参考資料

woshidan.hatenablog.com

Android Record and Playback | FatTuba.com