algonote

There's More Than One Way To Do It

Deep Learningでマンガの自動翻訳(をしたかった)

日本のマンガの海外販売では以前より公式翻訳がないことに起因するファンサブ(非公式字幕)の権利問題が起きている。Deep LearningによりOCRと自動翻訳の精度が上がれば、問題が解決するかもしれない。

ブラックジャックによろしくのページをいくつかGoogle Cloud Vison APIに通して、マンガのテキストをどこまで認識できるか試してみる。

画像をjson化、jsonからHTML化

こちらの記事のコードを使用してOCRを実行、json化した。 a244.hateblo.jp

次に、jsonをいい感じにHTML化する。 巨大なのでパースが大変。

  • text_box.rb
IMAGE_WIDTH = 878
IMAGE_HEIGHT = 1240
SCALED_WIDTH = 480

SCALE_FACTOR = SCALED_WIDTH.to_f/IMAGE_WIDTH

class Point
  def initialize(x, y)
    @x = x * SCALE_FACTOR
    @y = y * SCALE_FACTOR
  end

  attr_accessor :x, :y
end

class TextBox
  def initialize(p0, p1, text, font_size=nil)
    @p0 = p0
    @p1 = p1
    @text = text
    if font_size == nil
      @font_size = (height * 0.9).round(1)
    else
      @font_size = font_size
    end
  end

  def top
    (@p0.y).round(1)
  end

  def left
    (@p0.x).round(1)
  end

  def height
    (@p1.y - @p0.y).round(1)
  end

  def width
    (@p1.x - @p0.x).round(1)
  end

  def +(tb)
    if @p0.x < tb.p0.x
      p0 = @p0.clone
      p1 = tb.p1.clone
      text = @text + " " + tb.text
    else
      p0 = tb.p0.clone
      p1 = @p1.clone
      text = tb.text + " " + @text
    end

    font_size = ((@font_size + tb.font_size)/2.0).round(1)
    TextBox.new(p0, p1, text, font_size)
  end

  attr_accessor :p0, :p1, :text, :font_size
end
  • json2page
#!/usr/bin/env ruby
# coding: utf-8

require 'json'
require 'pp'
require './lib/text_box'

if ARGV[0] == nil || ARGV[0] == '-h' || ARGV[0] == '--help'
  puts "Usage: json2page jsonfile > output.html"
  puts "       json2page jsondir output_dir"
  exit
end

def json_to_text_box(json_file)
  File.open(json_file) do |file|
    results = JSON.load(file)

    text_boxes = []
    if results["responses"][0].empty?
      next
    end
    results["responses"][0]["text_annotations"][1..-1].each do |ta|
      p0 = ta["bounding_poly"]["vertices"][0]
      p0 = Point.new(p0["x"], p0["y"])
      p1 = ta["bounding_poly"]["vertices"][2]
      p1 = Point.new(p1["x"], p1["y"])
      text = ta["description"]

      tb = TextBox.new(p0, p1, text)
      text_boxes.push(tb)
    end

    divs = []
    divs.push("<div class=\"koma\">")
    base = json_file.split("/")[-1][0...-5]
    divs.push("  <img src=\"assets/img/#{base}.jpg\"/>")
    text_boxes.each do |tb|
      style = "font-size: #{tb.font_size};width: #{tb.width};height: #{tb.height};left: #{tb.left};top: #{tb.top};"
      div = "  <div class=\"box\" style=\"#{style}\">#{tb.text}</div>"
      divs.push(div)
    end
    divs.push("</div>")
    if ARGV[1] == nil
      puts divs.join("\n")
    else
      return divs.join("\n")
    end
  end
end

if ARGV[0][-5..-1] == ".json"
  json_to_text_box(ARGV[0])
else
  json_files = Dir.glob(File.join(ARGV[0], "*.json"))
  json_files.each do |json_file|
    output_base = json_file.split("/")[-1][0...-5]
    output_filename = output_base + ".html"
    output_htmlfile = File.join(ARGV[1],output_filename)
    File.open(output_htmlfile, 'w') do |file|
      file.write(json_to_text_box(json_file))
    end
  end
end

結果

適当にCSSをこしらえて表示する。 白背景でテキストボックス表示したらよく見えなかったので、以下の画像は選択反転させている。

f:id:hiromichinomata:20170717193705p:plain f:id:hiromichinomata:20170717203430p:plain

Credit: ブラックジャックによろしく佐藤秀峰

間違いの考察

  • 一部文字が抜けている。(24 HOURS, 2HOURS)
  • 吹き出しをまたいでいてもくっついてしまう。
  • 縦書きを認識できない
  • 効果音文字を認識できない。

ある程度認識できているが、翻訳のベースに使うにはまだまだか。