掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
Delphiで画像から顔領域や目の領域を認識検出(Haar Cascades識別器)するクラスを作りましたが、処理速度と精度の両方を高くする畳み込み方法がわからない (ID:150742)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
自己レスです。 とりあえず、TTask/ITaskを使用して並列プログラミングにより処理速度を高速化してみました。 ループ開始(窓サイズを少しずつ大きくしていく) ループ開始(画像に対して窓を少しずつ横に移動していく) ループ開始(画像に対して窓を少しずつ縦に移動していく) tasks[0]~tasks[MaxWorkerThreadsCount-1]・・・窓の縦の位置が少しずつ違う --------------------------------------------------------------- ループ開始(Haar Cascadesのステージ1~25までのループ) ループ開始(features Rectのループ) 積分画像からリーフ値を合計していく ループ終わり 各ステージ毎にカスケード型識別器処理を行い失敗したらループを抜ける ループ終わり --------------------------------------------------------------- tasks[0]~tasks[MaxWorkerThreadsCount-1]を並列に実行 ループ終わり ループ終わり ループ終わり MaxWorkerThreadsCountの値はTThreadPool.Default.MaxWorkerThreadsから取得しました。 コア数×25の値になるそうで、8コア搭載のパソコンを使っている場合は、最大200スレッドを並列に同時実行することになります。 処理速度は随分速くなりましたが、CPUリソースの使用率はかなり高くなりました。 TTask/ITaskの使用には注意点がありまして、エンバカデロ社の説明ページのようにTTask/ITaskの使用を行うと引数がまともに渡せませんでした。 例えば以下のソースコードの場合、 tasks[0]にはvalue=0の値が渡され、tasks[1]にはvalue=1の値が渡されると思っていたのですが 実際には、tasks[0]とtasks[1]に渡される値が0だったり1だったり、まるでランダムのように変化しました。 (デバッグ時のステップ実行で1行ずつ止めると期待通りの値が渡されますが・・・) タスク(スレッド)の開始・終了順序が保証されないことを考えると、これが「当たり前」なのかもしれません。 function RunStage(v:Integer); begin ・・・ end; procedure TForm1.MyButtonClick(Sender: TObject); var tasks: array of ITask; value: Integer; begin value := 0; tasks[0] := TTask.Create(procedure() begin RunStage(value); end); tasks[0].Start; value := value+1; tasks[1] := TTask.Create(procedure() begin RunStage(value); end); tasks[1].Start; TTask.WaitForAll(tasks); end; 仕方なく、かなり面倒ですが、TTask/ITaskから派生したクラス THaarStagesTask = class(TTask, ITask) を作ってコンストラクタでプライベート変数に値を保持するようにしました。 さらに、TTask/ITaskから派生したクラスの複数のインスタンスから同時に同じオブジェクトにアクセスするので System.MonitorEnter と System.MonitorExit を使って同時アクセスを保護しました。 並列プログラミングがこんなに大変とは思っていませんでした・・・。 上記を踏まえたTTask/ITaskを使用したHaar Cascadesのクラスのソースコードを公開しました。 https://mam-mam.net/delphi/haar_cascade.html#fast
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.