opencvはフリーの画像処理ライブラリで使い勝手がよいのですが、画像ファイルを読み込むimreadとimwriteは注意が必要です。

pathlibに対応していない

pathlibはファイルのディレクトリやパスをオブジェクト指向的に扱うことの出来る標準のバッケージで、python3.6からサポートされています。

しかし、opencvの引数にこれを渡してもだめです。 Noneが返ります。

strとして渡す必要があります。

パスが間違っていても例外発生しない

Noneが返ってきます。  

モノクロ画像を読み込んでもRGBの3チャンネルになる

RGBすべての値が同じnumpyが返ってきます。 1チャンネルのデータが欲しいときは引数にcv2.IMREAD_GRAYSCALEを設定する必要があります。

img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

日本語パスng

日本語pathに対応してません。

Optunaの目的関数に引数を渡す方法

optunaは最適な機械学習のハイパーパラメータを探索するツールです。 以下はよくあるoptunaのサンプルです。

import optuna

# 目的関数
def objective(trial):
  x = trial.suggest_uniform('x', -10, 10)

  return (x - 2) ** 2

study = optuna.create_study()
study.optimize(objective, n_trials=100)

objectiveはtrial以外の引数を取りません。 ですが、他の引数を渡したい事もあります。

こういう場合はfunctools.partialを使う事で実現できます。

import optuna

# 目的関数
def objective2(trial, a):
  x = trial.suggest_uniform('x', -10, 10)

  return (x - a) ** 2

objective = functools.partial(objective2, a=2)
study = optuna.create_study()
study.optimize(objective, n_trials=100)

なお、公式のFAQに他の方法も掲載されてます。 FAQ — Optuna 2.3.0 documentation

Pythonプログラムの高速化(lru_cache)

時間のかかる計算の回数を少なくするために、その計算結果を何度も再利用したいことがあります。 そういう場合、辞書等に一時的に格納する方法が思いつきますが、実装してみるとコードが読みにくく保守性が悪いです。

このような場合、lru_cacheというデコレートを使うと便利です。関数の出力値を自動で保存してくれて、次回の呼び出しではその保存値を返してくれます。

import functools

@lru_cahce()
def calc_heavy():
    calc heavy...
    return score

インスタンスメソッドに使いたい場合は、methodtoolsのlru_cacheを用いるとよいです。

pip install methodtools
import methostools

class Hoge:
    def __init__(self):
        pass
    
    @methodtools.lru_cahce()
    def calc_heavy():
        calc heavy...
        return score

Python Dict型の便利な使い方

Python には dict というkey: valueの組を保持する基本型があります。

これを使っていると、コード量が増え面倒だと思う場面が多々あります。 Pythonにはコーディングを楽にする仕組みがあるので紹介します。

get()メソッド

getはdict型のメソッドです。 dictを使っていると、キーの存在確認をするコードを書くことがあります。

if key in dic:
    return dic[key]
else:
    return None 

get()メソッドを使うと、キーの存在確認をするif文を省くことができます。

return dic.get(key, None)

この文の意味は、「getはkeyに対応する要素を取得する。keyが存在しなければNoneを返す。」です。

defaultdict型

defaultdicrtはdict型のサブクラスで、Pythonに標準で用意されています。 デフォルトのvalue値を初期化する関数を引数に追加することができ、valueの初期値の代入するコードを書かなくて良くなります。

例えば、dictのvalueにlistを保持するデータ構造を扱いたいとします。 これを普通にdict型で書くと

dic = {}
dic['key'] = []
dic['key'].append(123)

という書き方になります。 defaultdictを使うと以下になり、valueの初期値代入を省くことができます。

from collections import defaultdict
dict = defaultdict(list)
dict['key'].append(123)

ちなみに、list関数はlist型を生成する関数です。初期値は[]が設定されます。

内包表現

{}のない方表現を使うと、簡単に辞書を作成することができます。

dic = {i:func(i) for i in range(i)} 

参考

Not using get() to return a default value from a dict — Python Anti-Patterns documentation

8.3. collections --- コンテナデータ型 — Python 3.6.12 ドキュメント

python tkinter Listboxの使い方

pythonのドキュメントにtkinterのListboxの説明がないので、このエントリーにまとめておきます。 tkinter --- Tcl/Tk の Python インタフェース — Python 3.7.8 ドキュメント

コンストラク

import tkinter as tk
tk.Listbox(master, **option)
引数 説明
exportselection False・・・他のWidgetフォーカスを取得したときに、このWidgitが選択を保持できるようにする。フォーカスを移したときにselectionのbakcgraoudカラーが消えるのを防ぐことができる。参考 python - How to keep selections highlighted in a tkinter Listbox? - Stack Overflow
selectmode single・・・1個
browse(デフォルト)・・・
multiple・・・複数
extended・・・

メソッド

メソッド 説明
insert(index, element) index - 挿入するindex番号。tk.ENDを指定すると末尾にinsertする。element - insertする要素のtext
delete(i1, i2) i1からi2のindexの要素を削除する。0, tk.ENDを指定するとすべてのアイテムを削除する。
bind(event, callback) event-bindするEvent
"<Key>","<KeyPress>" -> キーが押された。-Xを末尾に指定すると、特定のキー(-XをつけるとXキー)のみ検出するようになる。
callback - イベントが発生したときに呼ばれるcallback関数。callback関数にはevent引数が必要。