はじめに
画像から特定の部分を切り出して機械学習や深層学習をさせようとした時、対象の画像を切り出すための仕組みが必要だったので、ラベリングを支援するためのWebアプリケーションを作ってみた。
画像とラベルについて
画像に0からの連番で「xxx.png」というファイル名をつけて保存します。
ここでは、重量計のメーターをサンプルに使用し、下図のとおり左上と左下の座標とメーターの値をラベリングするものとします。
ちなみに、画像のサイズは1280x720。
機能
対象物の左上をクリックし、右下をクリックするとクリックした座標を取得してテキストボックスに入力し、メーターの値を入力するテキストボックスにフォーカスを移す。
メーターの値を入力し終わったら、ボタンをクリックして送信することで、データを記録します。
新しいデータの設定が終わったら、次の画像を表示します。
フォルダ構成
- index.rb
スクリプト用ファイル - img
画像保存用フォルダ - db ラベルデータ保存用フォルダ
データベース準備
以下のコマンドを実行し、テーブルを作成。
$ sqlite3 db/param.db
SQLite version 3.6.20
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> CREATE TABLE `param` (
...> id integer,
...> left integer,
...> right integer,
...> top integer,
...> bottom integer,
...> val integer
...> );
sqlite> .exit
$ sudo chown -R apache db
スクリプト作成
index.rb
#!/usr/bin/env ruby
require "cgi"
require "sqlite3"
cgi = CGI.new()
puts cgi.header()
# データベースへの接続
db = SQLite3::Database.new("db/param.db")
# パラメータの受取
$_GET = {}
cgi.params.each do |key, val|
$_GET[key] = val[0]
end
# ファイル番号設定
id = 0
if $_GET.size > 0 then
id = $_GET["id"].to_i
end
# ラベルデータ保存
if $_GET["submit"] == "set" then
# 古いデータの削除(なくても実行)
sql = "DELETE from param WHERE id=#{id}"
db.execute(sql)
# 新しいデータの保存
sql = <<EOF
INSERT INTO param
VALUES (
#{id},
#{$_GET["left"]},
#{$_GET["right"]},
#{$_GET["top"]},
#{$_GET["bottom"]},
#{$_GET["val"]}
);
EOF
db.execute(sql)
id += 1
end
filename = sprintf("%03d.png",id)
# 既存データの取得
sql = "SELECT * FROM param WHERE id=#{id}"
left = 0
right = 0
top = 0
bottom = 0
val = 0
rs = db.execute2(sql)
flg = false
rs.each do |row|
if flg then
left = row[1].to_i
right = row[2].to_i
top = row[3].to_i
bottom = row[4].to_i
val = row[5].to_i
end
flg = true
end
# HTMLの作成
html = <<EOF
<html>
<head>
<title>LABELING TOOL for ML</title>
<style>
* {
font-size: 15px;
margin: 0px;
padding: 0px;
}
div {
border: 0px solid #F00;
}
form td {
padding: 5px;
}
#page {
width: 800px;
}
#head {
background-color: #CCC;
height: 100px;
}
#head .title {
font-size: 30px;
line-height: 100px;
padding-left: 10px;
}
#body {
background-color: #FFF;
}
#foot {
background-color: #CCC;
height: 50px;
}
</style>
<script>
var img;
var frm;
function init() {
img = document.getElementById("img");
frm = document.forms.params;
}
function get_point(e) {
r = 1280 / 800
x = e.pageX * r;
y = (e.pageY - 100) * r ;
if (frm.pos.value=="left") {
frm.left.value = Math.round(x);
frm.top.value = Math.round(y);
frm.pos.value = "right";
} else {
frm.right.value = Math.round(x);
frm.bottom.value = Math.round(y);
frm.val.focus();
}
}
</script>
</head>
<body onload="init()">
<div id="page">
<div id="head">
<div class="title">LABELING TOOL for ML</div>
</div>
<div id="body">
<div id="img">
<img src="img/#{filename}" width="100%" onclick="get_point(event);" />
</div>
<form name="params">
<table>
<tr>
<td> </td>
<td>ID:</td><td><input type="text" name="id" size=5 value="#{id}" /></td>
<td><input type="submit" name="submit" value="load" /></td><td> </td>
</tr>
<tr>
<td><input type="radio" name="pos" value="left" checked /></td>
<td>LEFT:</td><td><input type="text" name="left" size=5 value="#{left}" /></td>
<td>TOP:</td><td><input type="text" name="top" size=5 value="#{top}" /></td>
</tr>
<tr>
<td><input type="radio" name="pos" value="right" /></td>
<td>RIGHT:</td><td><input type="text" name="right" size=5 value="#{right}" /></td>
<td>BOTTOM:</td><td><input type="text" name="bottom" size=5 value="#{bottom}" /></td>
</tr>
<tr>
<td> </td>
<td>VALUE:</td><td><input type="text" name="val" size=5 value="#{val}" /></td>
<td> </td><td> </td>
</tr>
<tr>
<td> </td>
<td> </td><td><input type="submit" name="submit" value="set" /></td>
<td> </td><td> </td>
</tr>
</table>
</form>
</div>
<div id="foot">
</div>
</div>
</body>
</html>
EOF
# HTMLの出力
puts html
完成図
作成したラベルデータで画像を切り出してみると、こんな感じ(^-^)
これでラベリング作業を外注する準備ができました!