ZawaWorks’s diary

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

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

ProcessingからNode.jsにテキストデータを送る

はじめに

 前回はProcessingがサーバー側でクライアント側のNode.jsがテキストメッセージを送ることを試みました。(前回の記事)今回は他の記事にもあるようなNode.jsからProcessingにテキストメッセージを送ることをnetモジュールを用いて行おうと思います。

 

コードを書く前に

  前回と同じくclientフォルダーとserverフォルダーを作成しました。clientフォルダーには「client.pde」、serverフォルダーには「server.js」というファイルを生成しました。今回Node.js側ではnetモジュールを使用するので、serverフォルダーに「npm install net」でnetモジュールをインストールしましょう。

 

コードを書く

 server.jsとclient.pdeのコードは以下の通りです。

 

server.js
var net = require('net');

var port = 3000;//適当なポート番号
var host = '127.0.0.1';//IPアドレス


var server = net.createServer((socket) => {
socket.on('data', (data) => {
console.log(`${data}`);//送られたテキストデータを表示
socket.write(data);
socket.pipe(socket);
});
socket.on('end', () => {
console.log('Server: Client Disconnected');
});
});

server.listen(port, host);

 

client.pde
import processing.net.*;

Client myClient;

int port = 3000;//server.jsで指定されたポート番号
String host = "127.0.0.1";

void setup() {
myClient = new Client(this, host, port);
myClient.write("Hello world!");
}

 

 実行

 まずはじめにserver.jsを「node server.js」で実行してから、client.pdeを起動させてください。コマンドプロンプトに「Hello world!」と表示されれば成功です。

 

 

引用元
naturalclar.com

Client::write() \ Language (API) \ Processing 2+

Node.jsからProcessingにテキストメッセージを送る

はじめに

 Node.jsとProcessingで変数やテキストメッセージを共有する記事は多々ありました。しかし、それらはNode.jsがサーバー側でクライアント側のProcessingがテキストメッセージを送るものでした。この記事はその逆で、Processingがサーバー側でクライアント側のNode.jsがテキストメッセージを送ることを試みました。

 

コードを書く前に

  自分はclientフォルダーとserverフォルダーを作成しました。clientフォルダーには「client.js」、serverフォルダーには「server.pde」というファイルを生成しました。今回Node.js側ではnetモジュールを使用するので「npm install net」でnetモジュールをインストールしましょう。

 

コードを書く

 client.jsとserver.pdeのコードは以下の通りです。

 

server.pde
import processing.net.*;

int port = 3000; // 適当なポート番号を設定

Server server;

void setup() {
server = new Server(this, port);
}

void draw() {
Client client = server.available();
if (client !=null) {
String whatClientSaid = client.readString();
if (whatClientSaid != null) {
println(whatClientSaid); // client.jsからのメッセージを出力
}
}
}

 

client.js
var net = require('net');

var port = 3000;//適当な数字を入れる
var host = 'xxxx';//IPアドレスを書く

var client = new net.Socket();

client.connect(port, host, () => {
console.log('Client: Connected to Server');
client.write("Hello world!");
});


client.on('close', () => {
console.log('Client: Disconnected from Server');
});

 

 実行

 まずはじめにserver.pdeを実行してから、client.jsを起動させてください。下の画像のようにProcessingのコンソール画面に「Hello world!」と表示されれば成功です。

f:id:ZawaWorks:20170912131137p:plain

 

引用元

 

qiita.comnaturalclar.com

Node.js:Webmoを動かしてみた

はじめに

Webmoとは電子工作の知識がなくてもJavaScriptで制御できるモーターです。このWebmoはNode.js用のライブラリがあり、それを使ってNode.jsで制御することが可能です。

今回はNode.jsでのWebmoの制御の仕方をまとめました。

 

環境設定

Webmoの事前知識

WebmoはPCとwi-fi接続しないと制御することができません。wi-fi接続の方法を知らない方はWebmoの始め方を読んでから次に進んでください。

 

準備と実行

1.適当にフォルダーを作る

今回は「webmo」というフォルダーを作成しました。

 

2.コマンドプロンプトで以下のコマンドを実行

 

 npm init -y

npm install webmo-client-nodejs --save

これで「webmo」フォルダーの中に「package.json」というファイルと、「node_modules」というフォルダーができているはずです。

 

3.index.jsファイルの作成

「webmo」フォルダーの中に「index.js」というファイルを作成してください。ここにWebmoを制御するコードを書きます。今回は「毎秒90度のスピードで回転して2秒後に止まる」コードを書きました。

 

例:毎秒90度のスピードで回転して2秒後に止まる

var WebmoWs = require('webmo-client-nodejs').ws
var motor = new WebmoWs("webmo.local")

motor.onopen = () => {
motor.rotate(90)
setTimeout(() => { motor.stop(); motor.close(); }, 2000)
}

 

※注意

Webmoの始め方にもありますが、WebmoはBonjour を利用し、webmo.localへ接続しています。WindowsのPCにはBonjourが入っていないため、それをインストールするか、「new WebmoWs("webmo.local")」の「webmo.local」をIPアドレス「192.168.42.1」に変更してください。

4.PCをWebmoにwi-fi接続をする

何度も言いますが、WebmoはPCとwi-fi接続しないと制御することができません。実行前にPCとWebmoがwi-fi接続されているか確認してください。

5.実行

あとは実行コマンドを打つだけです。実行コマンドは以下の通りです。

node index.js

 

まとめ

こんな感じでWebmoはNode.jsで簡単に制御することができます。Webmo制御に使える関数一覧はこちらのサイトに載っています。皆さんもぜひWebmoを使ってみてはいかがでしょうか?

 

参考資料

www.npmjs.com

Webmoの始め方(v0.1.1)