はじめに
Darknet(yolo)をpythonから使いたいなと思い、
デフォルトで入っているdakrnet.pyを参考に作ろうと思ったのですが、
そのコードには画像を保存する方法が書かれていませんでした。
とりあえず調べてみるかと、こちらの記事を参考に画像を保存するコードを実装したのですが、
jpg形式以外で保存することができませんでした。
どうしてもpngで保存したかった私は、
しぶしぶ、忌まわしきC言語で書かれたソースを読むことにしました。
結論
以下のようにすれば、png形式等で保存可能です。
class CtypesEnum(IntEnum):
"""A ctypes-compatible IntEnum superclass."""
@classmethod
def from_param(cls, obj):
return int(obj)
class IMTYPE(CtypesEnum):
PNG = 0
BMP = 1
TGA = 2
JPG = 3
lib = CDLL("libdarknet.so", RTLD_GLOBAL)
save_image_options = lib.save_image_options
save_image_options.argtypes = [IMAGE, c_char_p, IMTYPE, c_int]
# -------------------中略-----------------------
save_image_options(image, "predictions".encode('utf-8'), 0, 80)
1.コードの確認
参考にさせていただいた記事で呼ばれている関数 save_imageは、保存用の関数 save_image_optionsの導入に使用されている関数で、
指定imageをJPG形式で保存するというものでした。
void save_image(image im, const char *name)
{
save_image_options(im, name, JPG, 80);
}
この save_image_optionsの第三引数は、darknet.hで定義されているenum型の変数でした。
typedef enum{
PNG, BMP, TGA, JPG
} IMTYPE;
あれ、ctypesでenumってどう表現すればいいんだ???
2.ctypesでenumを表現する。
こちらの記事にありました。
from enum import IntEnum
class CtypesEnum(IntEnum):
"""A ctypes-compatible IntEnum superclass."""
@classmethod
def from_param(cls, obj):
return int(obj)
class IMTYPE(CtypesEnum):
PNG = 0
BMP = 1
TGA = 2
JPG = 3
lib = CDLL("libdarknet.so", RTLD_GLOBAL)
save_image_options = lib.save_image_options
save_image_options.argtypes = [IMAGE, c_char_p, IMTYPE, c_int]
これでいけます。
Enum型は自作データ型に当たるようで、from_param() クラスメソッドを実装しなければならないようです。
ドキュメント
オチ
これを書いているときに気づきました。
よく考えると、enum型ってint型で代用できるので
わざわざclassで定義するまでもなく、c_intと定義してしまえば十分じゃね?と
lib = CDLL("libdarknet.so", RTLD_GLOBAL)
save_image_options = lib.save_image_options
save_image_options.argtypes = [IMAGE, c_char_p, c_int, c_int]
save_image_options(image, "predictions".encode('utf-8'), 0, 80)
学生時代から忌まわしきとかいって避けてたツケが回ってきてる。。。
ctypesの勉強にはなったからよかったと思いたい。