先日の Cloud Vision API を使う Python3 編 に続いて Spring Boot Kotlin での Cloud Vision API の OCR のコード覚え書きです。
Python で既に書いたコードを Kotlin に移植しました。 Spring Boot は今まで使う機会がなかったのですが、 今回使って良いと思ったのは gradlew bootJar するだけで executable な単一の jar ファイルを生成してくれることです。
ただ Python のようにスクリプトファイルひとつで処理できるような小さな処理に Spring Boot を使うのは気が重いですね。
まず https://start.spring.io/ へアクセスして、 プロジェクトのベースをつくります。 開発環境の制約は Java8 以上が入っていればOK、というのは敷居が低いですね。
こんな感じに設定しました。
プロジェクトのベースが用意された zip をダウンロードして、ローカル macOS などで適当なディレクトリに展開します。
たくさんファイルやディレクトリがあるのですが、修正するのは以下の2つだけです。
dependencies に必要なライブラリを追記します。
implementation("commons-codec:commons-codec:1.7")
implementation("commons-io:commons-io:2.0")
implementation("org.json:json:20210307")
package jp.osima.myocr
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import java.io.File
import java.io.DataOutputStream
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.URI
import java.net.HttpURLConnection
import org.apache.commons.io.FileUtils
import org.apache.commons.codec.binary.Base64
import org.json.*
@SpringBootApplication
class MyocrApplication
fun toBase64(imageFile: File): String {
return Base64.encodeBase64String(FileUtils.readFileToByteArray(imageFile))
}
fun toRequestJson(imageFile: File): String {
val ocrRequestObject = JSONObject()
ocrRequestObject.put("image", JSONObject().put("content", toBase64(imageFile)))
ocrRequestObject.put("features", JSONArray().put(JSONObject().put("type", "TEXT_DETECTION")))
ocrRequestObject.put("imageContext", JSONObject().put("languageHints", JSONArray().put("ja").put("en")))
return JSONObject().put("requests", JSONArray().put(ocrRequestObject)).toString()
}
fun doPost(apiKey: String, imageFile: File): String {
val bytes = toRequestJson(imageFile).toByteArray(Charsets.UTF_8)
val url = "https://vision.googleapis.com/v1/images:annotate?key=${apiKey}"
val connection = URI(url).toURL().openConnection()
if( connection is HttpURLConnection ){
connection.setRequestMethod("POST")
connection.setDoOutput(true)
connection.setFixedLengthStreamingMode(bytes.size)
connection.addRequestProperty("Content-Type", "application/json; charset=UTF-8")
// 送信
DataOutputStream(connection.getOutputStream()).use { outputStream->
outputStream.write(bytes)
}
// 受信
val resultJson = BufferedReader(InputStreamReader(connection.getInputStream(), Charsets.UTF_8)).use { reader->
reader.readText()
}
connection.disconnect()
return resultJson
}
else {
return "{}"
}
}
fun saveAs(text: String, file: File): Unit {
val pw = file.printWriter()
pw.print(text)
pw.close()
}
fun main(args: Array<String>) {
runApplication<MyocrApplication>(*args){
System.setProperty("java.net.preferIPv4Stack", "true")
if( args.size>2 ){
val apiKey = args[0]
val imageFilePath = args[1]
val resultJsonFilePath = args[2]
val imageFile = File(imageFilePath)
val result = doPost(apiKey, imageFile)
saveAs(result, File(resultJsonFilePath))
}
}
}
処理内容は 前回のエントリーの Python 3 と同じです。
Kotlin なので 関数定義を中心にコードを記述できるのはうれしいですね。
まず実行可能(executable)な jar を生成します。
$ ./gradlew bootJar
すると以下に jar が生成されます。
あとは、実行するだけです。
$ java -jar build/libs/myocr-0.0.1-SNAPSHOT.jar APIKey 画像ファイルパス 結果のJSON保存ファイルパス
以上です。