アイデアとしては単純で、画像情報に落としたあとで全漢字pairに対して全pixelの一致数をカウントするだけ。
これの時にはリアルに全漢字でやろうとしてたんだけど、2万字=>4億ペアなので断念した。常用漢字1945文字を対象とする。
ActiveRecordやら何やら使いたかったけど、普通にやると結構面倒だったのでrailsでプロジェクト作ってscript/runnerした。
rake db:migrateで
create_table :chars do |t|こんなのと
t.column :char, :string
t.column :byte, :integer
end
add_index :chars, :char
add_index :chars, :byte
create_table :similarities do |t|こんなの作った後、
t.column :char1_byte, :integer
t.column :char2_byte, :integer
t.column :similarity, :integer
end
add_index :similarities, [:char1_byte, :similarity]
add_index :similarities, :similarity
#!/usr/bin/env /path/to/yours/kanji_rails/script/runnerこんな感じ。20x20の画像オブジェクトを明朝体のtrue type fontとRMagickを用いて全漢字分生成し、色情報を配列に入れた後、各ピクセルの一致をそれぞれカウントしてDBに流し込む。
$KCODE = "u"
require 'jcode'
require 'RMagick'def diff_a(a1, a2)
result = 0
(0..399).to_a.each{|i| result +=1 if a1[i] == a2[i]}
result
endchars_a = []
open("kanji.txt").each_line do |line|
line.chomp
chars_a << line.split(/\s/)
end
chars_a.flatten!puts "chars retrieved"
chars_h = Hash.new {|h, k| h[k] = {}}
chars_q = []
chars_a.each do |char|
i = eval("0x#{char.unpack('C*').map{|i| i.to_s(16)}.join}")
chars_h[char][:byte] = i
chars_q << {
:byte => i,
:char => char
}
endputs "chars analyzed"
chars_a = chars_a.sort_by{|c| chars_h[c][:byte]}
Char.create(chars_q)
puts "chars created"pos = 0
chars_a.each do |char|
img = Magick::ImageList.new()
img.new_image(20,20)
text = Magick::Draw.new
text.gravity(Magick::CenterGravity)
text.stroke('transparent')
text.fill("black")
text.font("mincho.ttf")
text.font_size(20)
text.text(0,0,char)
text.draw(img)
px_a = []
20.times do |x|
20.times do |y|
px_a << (img.pixel_color(x,y).intensity.to_i != 255)
end
end
chars_h[char][:px_a] = px_a
pos += 1
puts "#{pos} chars pixel analyzed" if pos % 100 == 0
end
puts "chars pixel analyzed"pos = 0
similarity_q = []
chars_a.each do |char1|
chars_a.each do |char2|
next if char1 == char2
similarity_q << {
:char1_byte => chars_h[char1][:byte],
:char2_byte => chars_h[char2][:byte],
:similarity => diff_a(chars_h[char1][:px_a], chars_h[char2][:px_a])
}
pos += 1
if pos % 1000 == 0
Similarities.create(similarity_q)
similarity_q = []
puts "#{pos} char pairs analyzed"
end
end
end
今一こういうデータのバッチ生成をどこに置くのかを分かってないです。ひょっとしたらmigrationにしちゃった方がよいのかもしれません。
で、会社に行ってる間にある程度検索可能な状態になったところで、適当なSQLを書いて上位ペアを500件抽出し、Cytoscapeで可視化してみる。
出来上がったのがこちら。
クリックで全体表示
とりあえずのびのび犬がちゃんと抽出できて良かった。
コメント (5)
わおう。。すごいですね。
人間が認識できるフォント全部でやってみたりしたら、ネットワークから漢字認識に必要なものが...とかならないですかね。
投稿者: gly | 2007年12月15日 14:23
openCVとかで画像認識ってことかなあ。それも確かに面白そうだね。
このデータの別の使い方そのうち示すから、要チェキよろ。
投稿者: negipo | 2007年12月16日 22:22
うまい。
最近RNA二次構造とかで、二次元boolean alignmentについてひとつアイディアがあるから今度教える。
エントロピーを使った非常に簡単なやつ。
そもそもWindowsとかに漢字の絵を書くと検索してくれるやつあるけど、あれはどうやっているんだろう?
ってか何やるつもり?
投稿者: nzm | 2007年12月17日 03:56
RNA二次構造とか最早懐かしいな。是非教えてほしい。
手書き文字認識はまたちょっと違う手法らしいよ。筆を置いた位置からの軌跡の集合でマッチングだってこないだきょうたに聞いた。よくわからないけど。
やりたいのは文章にノイズをのせること。面白いかどうかはわからん。
投稿者: negipo | 2007年12月17日 10:27
ぼーっと眺めてたら右上に六-本-木があるのを発見したwww
投稿者: negipo | 2007年12月19日 10:07