tqdmをムリヤリprocess safeっぽくするdirty hack

生物界で最大の目(光を検知する器官)を持っているのはダイオウイカおよびダイオウホウズキイカと言われ、その大きさは30〜35cmほどにもなるのだそうです。

さて、世界70億人のPythonプログラマが手放せないのが、tqdmというプログレスバーを簡単に表示できるようにしてくれるライブラリです。
しかしながらtqdmは(当然と言えば当然ですが)複数のプロセスから1つのプログレスバーを管理することができるような設計にはなっていません。
たとえば高速化のためにmultiprocessingを用いて並列処理をしながらプログレスバーを出したいとき、tqdmはそのままでは使えないことになります。

例えば、下記のようなコードで単にtqdmのインスタンスを子プロセスに渡して中でupdateをすると…

import tqdm
import multiprocessing

def worker(pbar):
    pbar.update()

ar = [i for i in range(100)]
with tqdm.tqdm(ar) as pbar:
    jobs = []
    for t in ar:
        job = multiprocessing.Process(target=worker, args=(pbar,))
        job.start()
        jobs.append(job)
    for job in jobs:
        job.join()

実行結果はこんな感じ。

% python usage.py
  1%|▉                                                                                                 | 1/100 [00:00<00:25,  3.89it/s]

こんなふうに、100%まで行ってくれません。
端的に説明すると、100個forkされた内部カウント0の状態をそれぞれ+1するのが100回走るだけ、だからです。

じゃあ内部カウントが常によろしく増えるために、内部カウントを無視して共有メモリで常に正しくカウントしてればいいよね、っていう単純な発想による汚いハックをしてみました。

Continue reading

OpenCVの二値画像からの画素値の取得でハマった

OpenCVの画像形式cv::Matはいろんな格納方式ができて,二値画像ももちろんいけるんですが,画素値を個別にアクセスするときのやり方でうっかりしたミスでハマってしまいました.

ということで自虐を兼ねてメモ.(逆では

//画像を読み込む
cv::Mat img = cv::imread("fugafuga.png", CV_LOAD_IMAGE_GRAYSCALE);

//大津の方法で二値化.こうすると二値画像のフォーマットでMatに格納してくれます
//srcとdstが一緒ですが一応問題ないです
cv::threshold(img, img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

//全画素をPGMフォーマットで出してみる
std::cout << "P1" << std::endl;
std::cout << img.cols << " " << img.rows << std::endl;
for(int y = 0; y < img.rows; y++)
{
    for(int x = 0; x < img.cols; x++)
    {
        //std::cout << img.at<int>(y, x) << " ";    //まちがい!!
        std::cout << static_cast<int>(img.at<unsigned char>(y, x)) << " ";
    }
    std::cout << std::endl;
}

at<int>()はカラー画像のBGRAをごそっと取り出すとき用だったりするので,二値画像の画素値を出すときはat<unsigned char>()を使いましょうというお話でした.static_castはべつにせんでもええです.
ちなみにat<int>()でやると事実上のゴミが出てきます.
何をいまさらこんなところでつまづいてるのか小一時間問い詰めたい.

研究の全てをgitで管理してたら( ・∀・)イイ!!

ここ1ヶ月半くらいかな,研究データの全てをgitで管理してみるようにしました.

画像系の研究なので,テスト画像だったり,テスト画像毎の処理結果だったり,実験を走らせるためのスクリプトだったり,プログラムだったり.
今まではreadme的なテキストファイルに「これはいついつこういう目的でやった実験だよ!(>ヮ<*)」と書いてるだけだったんですが,時間軸方向の管理能力には限界があったのです.

全てをひとつのリポジトリにぶっ込むとリポジトリが肥大化しすぎて(それこそ画像数万枚の実験を何百回となく行うので,バイト数でいうとLinuxカーネルどころじゃない),速度的にさすがに問題が出てくるので,ひとまとまりの実験をひとつのリポジトリにして,全体はsubmoduleとして管理します.
特定の実験のためのアドホックなプログラムはさらにそいつのsubmoduleで,みたいな.

まだ日は浅く管理してる要素の数もそれほどですが,
ドジっ子おさかなさんはしょっちゅう実験ミスするので,こういう形であらゆる実験結果を検証できるようにしておくと非常によいです.

みなさんもいかがでしょうか?