Starsand’s Knowledge

IT技術の検証、トラブル対応、作成したものを公開します。自分のペースで好きなことを

Helm json: cannot unmarshal string into Go struct field ConfigMapVolumeSource.spec.template.spec.volumes.configMap.defaultMode of type int32

概要

helmで (少なくとも)volumes.configMap.defaultMode を指定する際、ファイルパーミッションの指定は8進数ではなく10進数に直して指定する必要がありそうです。

対応方法

--set your.field=493

発生したエラーとコマンドライン

helm install redis-session-store --create-namespace --namespace prod \
::
    --set master.extraVolumes[0].configMap.defaultMode=0755 \


Error: INSTALLATION FAILED: 2 errors occurred:
        * StatefulSet in version "v1" cannot be handled as a StatefulSet: json: cannot unmarshal string into Go struct field ConfigMapVolumeSource.spec.template.spec.volumes.configMap.defaultMode of type int32
        * StatefulSet in version "v1" cannot be handled as a StatefulSet: json: cannot unmarshal string into Go struct field ConfigMapVolumeSource.spec.template.spec.volumes.configMap.defaultMode of type int32

また、755とした場合でも、Pod自体はRunningとならず、describeからは権限について言及されます。

kubectl describe

  Warning  FailedCreate      78s (x16 over 4m2s)  statefulset-controller  create Pod redis-session-store-master-0 in StatefulSet redis-session-store-master failed error: Pod "redis-session-store-master-0" is invalid: [spec.volumes[5].configMap.defaultMode: Invalid value: 755: must be a number between 0 and 0777 (octal), both inclusive, spec.containers[0].volumeMounts[6].name: Not found: "conf"]

参考・他

ドキュメントを読み込んだわけではないので自分の見落としなだけな可能性はありますが、検索時に日本語の情報がうまくヒットしなかったので記載。

参考

github.com

【OCR】Tesseract 読み取り精度向上のために試した3つの事とその結果

少し前置きが長いので必要な方は下記リンクで飛んでください

背景

先に公開しているゲーム操作自動化プログラムに付随する画像のようなツールを作っていました。

appimage

このツールでは画像を元にGUI操作をさせるものです。
※ロックを自動で解除する事が目的のツールです。

この画像内の表部分をTesseractを利用して取得し、取得した文字については一切の加工をしていない状態です。

Tesseractを扱ったことがない方はこれぐらいこのように読めて当然。
と思う方もいらっしゃると思いますが、画像をそのまま読ませるだけでは期待する精度が出ないこともままあります。

以前同様のプログラムを作成した事が有り、その際は期待から外れるパターンをテストで見つけて正規表現で置換を繰り返すという方法でアプローチしました。
%の記号が特に鬼門で、96と認識されたりすることが多かったのですが、前後の表現と組み合わせると正規表現での処理は困難で最終的に実用レベルには至りませんでした。

その際に読み取り精度向上のためにできそうなことは考えてはいたのですが、本記事はその実践内容を紹介します。

正直、綺麗なやり方か?と言われるとそうではなく、高度なことでもなく当たり前だと思われる方もいらっしゃることと思います。
しかし、検索する限りでは自分のケースに対応できるような手法が紹介されている記事をうまく見つけられませんでした。

ですのでこれが誰かの役に立てば幸いです。


目次

対象・前提条件
  • Pythonの基本的な文法がわかる。
  • OpenCVやPillowの基本的な処理・文法がわかる。
要点
  • 読み取らせる範囲を絞り、1行単位に分割する

    • LineBoxBuilderを利用して行を取得
  • 誤認識1されやすい箇所をマスクする

    • テンプレートマッチングで座標を取得
  • 画像は二値化する

サンプルで使用する画像

読み取らせる範囲を絞り、1行単位に分割する。

これはやらなくても良い結果が得られるなら不要です。
どちらかと言うと全体的な処理の都合でそうしたところがあります。2

LineBoxBuilderを利用して行を識別

import pyocr
import cv2
from PIL import Image

tools = pyocr.get_available_tools()
tool  = tools[0]

# 文字と認識された座標の取得
res = tool.image_to_string (
    Image.open(target),
    lang = 'jpn',
    builder = pyocr.builders.LineBoxBuilder(tesseract_layout=6)
)

# 描画とプレビューをする場合は以下
out = cv2.imread(Image_to_write_rectangle)
for d in res:
    cv2.rectangle(out, d.position[0], d.position[1], (0, 0, 255), 1) )

cv2.imshow('Rectangle Drew', out)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果

※事前に白黒で取得した座標を元にカラー画像上に描画しています。
※コード中の対象画像はこちらの画像です。

検出した座標で画像を切り抜いて保存

# LineBoxBuilderで検出された座標を取得
# ( (左上頂点x ,y), (右下頂点 x, y) ) で格納されます。  
coords = res[0].position

# 切り取る範囲を設定します。
# 検出結果によっては文字を削ってしまうので必要に応じて margin を与えて画像サイズを調整します。  
margin = 3
box = (
    coords[0][0] - margin,
    coords[0][1] - margin,
    coords[1][0] + margin,
    coords[1][1] + margin,
)

# 画像を保存します。
# baseimage から box で指定された領域を切り取ります。  
baseimage = Image.open(baseimage_path)
baseimage.crop(box).save(filepath, quality=100)

誤認識されやすい箇所をマスクする

OpenCVのテンプレートマッチングを利用し、マスクしたい座標を取得後塗りつぶします。

import cv2

# テンプレートを検出したい画像とテンプレートを読み込む
origin = cv2.imread(origin_image_path)
template = cv2.imread(template_image_path)

# cv2.minMaxLocを利用して、類似率の高い座標を取得する。
retvals = cv2.minMaxLoc(
    cv2.matchTemplate(origin, template, cv2.TM_CCOEFF_NORMED)
)

# origin から塗りつぶしたい領域(area)を設定する。
area = (
    retvals[3][0],
    retvals[3][1],
    retvals[3][0] + template.shape[1],
    retvals[3][1] + template.shape[0]
)

# origin から area を塗りつぶす
cv2.rectangle(
    origin,
    pt1=( area[0], area[1] ),
    pt2=( area[2], area[3] ),
    thickness= -1,
    color=(0, 0, 0)
)

# プレビューする場合は以下
cv2.imshow('Filled', origin)
cv2.waitKey(0)
cv2.destroyAllWindows()


# 類似率に基づいてTrue / Falseを判別する。
# 最も高い類似率が0.9を超えればTrueそうでない時はFalse
if retvals[1] > 0.9:
    print('True')
else:
    print('False')

結果
,

使用画像(テンプレートを検出したい画像)
,

使用画像(テンプレート(一部)3)
,

マスクするだけだと読み取る値も空白などになってしまうので、マッチング時に類似率が一定以上ならばTrueとして値を格納、出力の際はTrueかどうかを見て値を付与するようにしました。
今回の例では%画像での類似率が高い時は、出力時に%を付与するような流れです。

なお、テンプレートは検出したい画像よりもサイズが小さい必要があります。
そのため、テンプレートが大きい場合は可能な限り前の工程でマスクすることも検討してください。

類似率についてはcv2.minMaxLocの[1]の値が最も高い類似率を示します。 www.tutorialexample.com


画像は二値化する

よくある方法ですが、画像は二値化することで認識率が向上します。
二値化すること、というよりは、二値化することで曖昧な境界を調整するというイメージ。
今回はOpenCVの機能でやりましたが、numpyを使って多次元配列を直接いじる方法もあります。

import cv2

#画像の各ピクセルを見て binaryThreshold の値を元に type の基準で二値化する
binaryThreshold = 190
target = cv2.imread(target_image_path, 0)
ret, binaried = cv2.threshold(target, binaryThreshold, 255, cv2.THRESH_BINARY_INV)

結果


もっと削ってもいいぐらいかなと個人的には思います。
cv2.imshow()では拡大するとピクセルの値が見れるので大雑把なあたりを付けて微調整しました。


builders.TextBuilder(tesseract_layout)の値

3つの事。と言いつつ4つ目なのと根拠はオプションでそう言われている…というレベルです。
今回は1つの画像に1行という前提のために7でやりました。


元々の操作自動化アプリについて starsand.hateblo.jp


  1. 人間が期待する値が返ってこないこと。

  2. 後の工程で利用するテンプレートマッチングは返ってくる値は1つでないこともあり、一つだけ欲しい。という場合には何らかの方法を用いる必要があります。

  3. 念の為色ごとにテンプレート分けてます。

【Python】GUI操作自動化によるゲーム内装備品の自動強化・OCRによる装備品一覧とステータスの取得

少し前にPythonで作ったGUI自動化プログラム。
Androidエミュレータを利用して、Dragon Village Mというゲームに向けて作ってます。

非公開のつもりでいたのですが、事情によって公開の必要が出てしまったので
それならまぁついでに載せとくか。みたいな感じです。

Github内のドキュメントにだいたいのことが記載してあるので、興味があればそちらを見てください。

装備品自動強化

github.com

装備品一覧の作成及びステータス自動取得

github.com

※実際に試したり中身は見ないでね。(自分なりにでも綺麗に書き直そうとしなかったので)
※予告なく非公開にする場合が有ります。

IT系技術のメモをはてなへ移転します。

markdownで記事書きたいのでHatena Blogへ移行します。

  • 自分がやっていてつまづいたけど、検索でうまく出てこなかったトラブル
  • 検索したけど、外国語でしかナレッジがなかった
  • 勘でやったらなんとかなった

みたいなものが中心ですが、作ったものも上げられたらいいなと思ってます。

blogofstarsand.blog.fc2.com

FC2ブログで公開している技術系記事のリンクは以下です。


日付 タイトル 概要
2022-04-22 BLOG OF STARSAND☆ データサイエンス100本ノック 構造化データ加工編ガイドブック Linux(Ubuntu)で dss-postgres コンテナが立ち上がらない(could not translate host name "db" to address: Temporary failure in name resolution) パーミッションが原因のDockerのトラブル対応
2022-04-05 BLOG OF STARSAND☆ ModuleNotFoundError: No module named 'flask._compat'の対応 Flaskで出たエラーの対応
2022-04-02 BLOG OF STARSAND☆ seleniumからChromeが起動しない SeleniumChromeが起動しない
2022-02-23 BLOG OF STARSAND☆ 【PowerShell】多分Windows Server向け、 Firewallの情報をGUI風に取得する PowerShellWindows Firewallの情報をGUI風に取得
2020-06-28 BLOG OF STARSAND☆ いいのかわからないけどKali LinuxにZabbix5.0をインストール(Apache,Postgresql) Kali Linux に Zabbix をインストール
2020-06-14 BLOG OF STARSAND☆ Wake On LANが動作しない場合の対処 Wake On Lan利用時のトラブル対応
2020-06-14 BLOG OF STARSAND☆ Remmina、Linuxへ接続時にxrdpログイン画面が点滅してログインできない事象と対応 Remmina利用時のトラブル対応
2020-06-03 BLOG OF STARSAND☆ Raspberry Pi 4 / Kali Linux 解像度変更(4K/WQHD) Raspberry Pi 4B での解像度変更
2020-05-18 BLOG OF STARSAND☆ Catalyst WS-C3560G-24TS-S 静音化ファン交換 Ciscoスイッチの静音化