アフィリエイト広告を利用しています
ファン
検索
<< 2023年12月 >>
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
最新記事
(12/20)KI cad インストールしてみよう
(04/11)【JAVA】チョロメを外部から動作させます。 幽霊が操作してるような
(07/29)spartan3 を cy7c68013 のバルクライトで シリアルコンフィグしてみた
(07/28)ブログ村に参加してみた。いまとのころブログ村からはだれもこない^^;
(07/28)PIC16F1503 を使ってみようかな?? MPLAB 内部クロック
(07/01)からっぽのつぎ のページ きっとはげ に なんか作用するかも
(05/06)GCEでワードプレス 第2 困ったのでやり直し手順
(05/05)https://certbot.eff.org/lets-encrypt/centosrhel7-apache をみてハマったこと
(04/28)フェドラ をつかって switchbot をアクセス する。  ? 未解決
(04/02)【オープンVPN】setsebool -P openvpn_enable_homedirs 1 でうごいた
(04/01)【QT5】わからないのでタイムアウトで自動でキャンセルボタン押すメッセージボックスつくってみた
(03/31)qt5よくわからんのだが メッセージボックスの OKスイッチをタイマーで押してみた。
(03/09)【boost】message queue 使い方 目も目も
(03/08)【バカの一つ覚え】ユニークID作成とそのちょっとした応用
(03/04)【パソコン】【GPIO】いったいこれは?
(02/26)【VHDL入門】ABZ信号から Hsync Vsyncを作り出してみよう その2
(02/26)【VHDL入門】ABZ信号から Hsync Vsyncを作り出してみよう その1
(02/26)【VHDL入門】速度比較 エンコーダーABZ相 ソースファイル付き
(02/25)【VHDL入門】ロータリーエンコーダABZ 出力のサンプル 200Mhz動作?
(02/23)【VHDL入門】UART 送受信繰り返しのテストベンチ作成してみたい
最新コメント
カテゴリーアーカイブ
プロフィール
有象無象さんの画像
有象無象
はげはじめました 禿増されます。励ましのコメントお待ちしてます。  
プロフィール

広告

posted by fanblog

2020年12月30日

OPENCV QT5 C++ matchTemplate マルチスレッド 解説 非GPUモード

shcd.jpg
あんまり需要はないだろうけど 
 マルチスレッド と アフィニティ とかの解説はあるが
 
 OPENVCV でマルチスレッドでのサンプルがないので自分のためだけ?に解説しておく
 あわよくばだれかの役にたてば 幸いです。

やりたいことは リアルタイム処理に近い方法で OPENCVをマルチスレッドでつかう
OS であるLINUXをすべてRAM上に配置
 マルチスレッドも マルチコアであることを意識して 並列化
 動作時間も計測 そんな チャンリンシャン な 話です。
 そんな需要にヒントになればいいなぁ ということです。



OPENCVなどのインストールや ビルドは 別途かきました 2020年12月21日
https://fanblogs.jp/computersettings/archive/16/0 とか です この前後  で
 カーネルビルドや ライブCDモディファイなど 高速化にいい話を書いています。
 私的には 素晴らしい(自画自賛)のめっちゃ読みにくい 日記です。


では 解説です。
 動作させるにあたり インクルードは
#include <opencv2/opencv.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudawarping.hpp>

 リンクは ビルドしたものを
LIBS+=/usr/local/lib64/libstdc++.so.6
LIBS+=-L/usr/local/lib64
LIBS+=-lpthread

LIBS+=/usr/local/lib64/libopencv_core.so
LIBS+=/usr/local/lib64/libopencv_highgui.so
LIBS+=/usr/local/lib64/libopencv_imgproc.so
LIBS+=/usr/local/lib64/libopencv_imgcodecs.so

LIBS+=/usr/local/lib64/libopencv_features2d.so
LIBS+=/usr/local/lib64/libopencv_flann.so
#LIBS+=/usr/local/lib64/libopencv_legacy.so
LIBS+=/usr/local/lib64/libopencv_ml.so
LIBS+=/usr/local/lib64/libopencv_objdetect.so
LIBS+=/usr/local/lib64/libopencv_photo.so
LIBS+=/usr/local/lib64/libopencv_stitching.so
LIBS+=/usr/local/lib64/libopencv_superres.so

LIBS+=/usr/local/lib64/libopencv_videoio.so


 な感じです。 まだ CUDAは起動できていませんが なんとかできるかなぁ?
 今日のところは 通常CPUでの マッチングどえす。

では解説です
 呼び出しは マッチングさせたい形を 登録します。
 QTの リソースにファイルをおいておき これを 読み込み という構造です。
呼び出しは スペード ダイアモンド クラブ ハート様 を ベクターにいれて

heart.png
club.png
diamond.png
spade.png


 自分が作った マッチングというクラス のインスタンスにいれます
 Matching は 
std::vector templates;
templates.push_back(":/Image/spade.png");
templates.push_back(":/Image/diamond.png");
templates.push_back(":/Image/club.png");
templates.push_back(":/Image/heart.png");
matching = new Matching(":/Image/shcd.png",templates);
matching->Disp(true);

delete matching;


shcd.jpg


いよいよこれらを あれします。そしてなにします。

Matching::Matching( std::string srcfilename, std::vector templatefilenames)
{ this->srcfilename=srcfilename;
Img_Ref =loadFromQrc(srcfilename.c_str() );
for(size_t i=0;i<templatefilenames.size();i++)
{
cv::Mat tml= loadFromQrc(templatefilenames.at(i).c_str() );
Img_templates.push_back(tml);
imshow(templatefilenames.at(i).c_str() , tml);
qDebug()<<" filename="<<srcfilename.c_str();
}

Img_Ref.copyTo( img_display );
Img_results.resize(templatefilenames.size());//画像の数 画像の大きさじゃないので勘違いなしで
mcs.resize(templatefilenames.size());
mythreads.resize(Img_templates.size());
this->laptimes.resize(Img_templates.size());
run();

 いよいよ これからはしらせる run() です なにがランなのかというと おおざっぱすぎるのですが
 ここで準備した ものを テンプレート関数に かけます
 もっとまともな名前がいいのですが・・・
 run のなかでは さらに マルチスレッドで _run() を ハート す・・・・ 4つハシラせます。
ちなみに ここの loadFromQrc は 
 Qtのリソースファイルを マットに変換している関数です。 OPENCVは qtのリソースなんかよめませんもん。
cv::Mat Matching::loadFromQrc(QString qrc, int flag)
{
//double tic = double(getTickCount());

QFile file(qrc);
cv::Mat m;
if(file.open(QIODevice::ReadOnly))
{
qint64 sz = file.size();
std::vector buf(sz);
file.read((char*)buf.data(), sz);
m = cv::imdecode(buf, flag);
return m;
}else
{

// double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();
qDebug() << "OpenCV loading time: " ;

return m;
}
}


ランは アフィニティ設定 してます あってるのかな?
スレッドを起動して そのスレッドをプロセッサに割り付けます。
 あとは 時間計測です。


void Matching::run()
{
std::chrono::system_clock::time_point start, end; // 型は auto で可
start = std::chrono::system_clock::now(); // 計測開始時間
for( unsigned int i=0;i(i))->native_handle();
int rc = pthread_setaffinity_np( pth, sizeof(cpu_set_t), &cpuset);
if (rc != 0) {
std::cerr << "Error calling pthread_setaffinity_np: " <<rc << "\n";
}

}
for( unsigned int i=0;ijoin();mythreads.at(i)=nullptr; }
end = std::chrono::system_clock::now(); // 計測終了時間
double elapsed = std::chrono::duration_cast(end-start).count(); //処理に要した時間をミリ秒に変換
qDebug()<<"elaped "<< elapsed <<"("<<mcs.at(0).x<<","<<mcs.at(0).y<<")"
<<this->laptimes.at(0)<<" "
<<"("<<mcs.at(1).x<<","<<mcs.at(1).y<<")"<<this->laptimes.at(1)<<" "
<<"("<<mcs.at(2).x<<","<<mcs.at(2).y<<")"<<this->laptimes.at(2)<<" "
<<"("<<mcs.at(3).x<<","<<mcs.at(3).y<<")"<<this->laptimes.at(3)<<"ms";
}

  いよいよ あれです。 
動作試験なので いいかげんに match_method を4つ苦し紛れにつっこんでいます。
メンバーにしたほうがいいかもしれませんけどね
GPU は まだ使っていません。 やりかけみたいな そして まだGPU使い方
は 今日のところは知りません。 
おそらく  GPUに アップロードして おいて  マッチングして 取り出す みたいな
 話しです。それをこれから ネットで探します。 
GPU演算は 噂でオーバーヘッドがおおきいと聞いたからです。 ロードセーブする時間が必要でしょう。


int match_method[4];
void Matching::_run(int i)
{ std::chrono::system_clock::time_point start, end; // 型は auto で可
start = std::chrono::system_clock::now(); // 計測開始時間
cv::Mat * tpl = &this->Img_templates.at(static_cast(i));
cv::Mat *result =&this->Img_results.at(static_cast(i));

cv::cuda::GpuMat imgGpuSrc, imgGpuDst;
cv::cuda::GpuMat ImgGpu_Ref;
imgGpuSrc.upload(*tpl);
ImgGpu_Ref.upload(Img_Ref);

/// Create the result matrix
int result_cols = Img_Ref.cols - tpl->cols + 1;
int result_rows = Img_Ref.rows - tpl->rows + 1 ;
result->create( result_cols, result_rows, CV_32FC1 );
/// Do the Matching and Normalize
matchTemplate( Img_Ref, *tpl, *result, match_method[i] );
normalize( *result, *result, 0, 1, NORM_MINMAX, -1, Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( *result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method[i] == cv::TM_SQDIFF || match_method[i] == cv::TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }

rectangle( *result, matchLoc, Point( matchLoc.x + tpl->cols , matchLoc.y + tpl->rows ), Scalar::all(0), 2, 8, 0 );

Mat cut_img(Img_Ref,Rect(matchLoc.x,matchLoc.y,tpl->cols, tpl->rows));
Mat gray_img;
cvtColor(cut_img, gray_img,cv::COLOR_RGB2GRAY);
Moments mu = moments( gray_img, false );
Point2f mc = Point2f( mu.m10/mu.m00 , mu.m01/mu.m00 );
mcs.at(i)=mc;
circle( img_display,Point( matchLoc.x + mc.x , matchLoc.y + mc.y ), 4, Scalar(255,255,100), 2, 4);
rectangle( img_display, matchLoc, Point( matchLoc.x + tpl->cols , matchLoc.y + tpl->rows ), Scalar::all(0), 2, 8, 0 );
end = std::chrono::system_clock::now(); // 計測終了時間
double elapsed = std::chrono::duration_cast(end-start).count(); //処理に要した時間をミリ秒に変換
this->laptimes.at(i)=static_cast(elapsed);

}



表示がいいかげんになのですが 全体で46ミリ秒  ハード スペード ・・・ が
それぞれ 37 39 45 32 ミリ秒かかっています。
そして 4つのスレッドが すべて済んだら 全体がおわります。
  並列化の効果がでてるとみていいでしょう。 きっと
直列にすると 37+39+45+32になるはずですが 46ミリで終了してるらしいです。
 つっこみあったら お知らせください。
filename= :/Image/shcd.png
filename= :/Image/shcd.png
filename= :/Image/shcd.png
filename= :/Image/shcd.png
elaped 46 ( 61.2307 , 62.9867 ) 37 ( 45.8407 , 58.4362 ) 39 ( 51.5852 , 59.97 ) 45 ( 64.7638 , 68.8308 ) 32 ms
OpenCV loading time:
EXITTHREAD


 今日のこところは ここまでです。


 











この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/10438953
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
×

この広告は30日以上新しい記事の更新がないブログに表示されております。