opencv 多线程加速_线程池给你写好了,想加速拿来用就行哈
生活随笔
收集整理的這篇文章主要介紹了
opencv 多线程加速_线程池给你写好了,想加速拿来用就行哈
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
圖像拼接實現見:
OpenCV源碼系列|圖像拼接1
OpenCV源碼系列|圖像拼接2
耗時在調用函數:
Mat pano;?Ptr?stitcher?=?Stitcher::create(mode);?Stitcher::Status?status?=?stitcher->stitch(imgs,?pano)能否將這一步放進線程池里進行加速呢?
1. 測試函數:
#include "t.h"#include #include #include #include #include #include #include #include"opencv2/imgproc/imgproc.hpp"#include "opencv2/imgcodecs.hpp"#include "opencv2/stitching.hpp"#include "omp.h"using namespace cv;using namespace std;Mat img=imread("./1.png");//線程池初始化void threadpool_init(threadpool_t *pool, int threads);//往線程池中加入任務void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg);//摧毀線程池void threadpool_destroy(threadpool_t *pool);bool divide_images = false;Stitcher::Mode mode = Stitcher::PANORAMA;vector imgs;string result_name = "result.jpg";void printUsage(char** argv);int parseCmdArgs(int argc, char** argv);//任意添加自己的代碼實現void* mytask(void *arg){ clock_t start,end; start=clock(); Mat pano; Ptr stitcher = Stitcher::create(mode); Stitcher::Status status = stitcher->stitch(imgs, pano); if (status != Stitcher::OK) { cout << "Can't stitch images, error code = " << int(status) << endl; exit(0); } imwrite(result_name, pano); cout << "stitching completed successfully\n" << result_name << " saved!"; free(arg); end=clock(); cout<<"圖像拼接時間: "<double)(end-start)/CLOCKS_PER_SEC<< return NULL;}//測試代碼int main(int argc, char* argv[]){ clock_t start,end; start=clock(); int retval = parseCmdArgs(argc, argv); if (retval) return EXIT_FAILURE; threadpool_t pool; //初始化線程池,最多三個線程 threadpool_init(&pool, 10); // int i; //創建十個任務 //for(i=0; i < 10; i++) // { int *arg = new int((sizeof(int))); *arg = 0; threadpool_add_task(&pool, mytask, arg); // } threadpool_destroy(&pool); end=clock(); cout<<"多線程運行時間: "<double)(end-start)/CLOCKS_PER_SEC<< return EXIT_SUCCESS; //return 0;}void printUsage(char** argv){ cout << "Images stitcher.\n\n" << "Usage :\n" << argv[0] <<" [Flags] img1 img2 [...imgN]\n\n" "Flags:\n" " --d3\n" " internally creates three chunks of each image to increase stitching success\n" " --mode (panorama|scans)\n" " Determines configuration of stitcher. The default is 'panorama',\n" " mode suitable for creating photo panoramas. Option 'scans' is suitable\n" " for stitching materials under affine transformation, such as scans.\n" " --output \n" " The default is 'result.jpg'.\n\n" "Example usage :\n" << argv[0] << " --d3 --try_use_gpu yes --mode scans img1.jpg img2.jpg\n";}int parseCmdArgs(int argc, char** argv){ clock_t start,end; start=clock(); if (argc == 1) { printUsage(argv); return EXIT_FAILURE; } for (int i = 1; i < argc; ++i) { //查看幫助 if (string(argv[i]) == "--help" || string(argv[i]) == "/?") { printUsage(argv); return EXIT_FAILURE; } //在像素較大時候,開啟這個模式 else if (string(argv[i]) == "--d3") { divide_images = true; } else if (string(argv[i]) == "--output") { result_name = argv[i + 1]; i++; } else if (string(argv[i]) == "--mode") { //僅僅是重疊度高的可用 if (string(argv[i + 1]) == "panorama") mode = Stitcher::PANORAMA; //實際測試 scans 模式比 panorama 適用范圍更為廣泛 else if (string(argv[i + 1]) == "scans") mode = Stitcher::SCANS; else { cout << "Bad --mode flag value\n"; return EXIT_FAILURE; } i++; } else { //終端讀取一系列圖片 Mat img = imread(argv[i]); if (img.empty()) { cout << "Can't read image '" << argv[i] << "'\n"; return EXIT_FAILURE; } //對圖片進行裁剪 if (divide_images) { Rect rect(0, 0, img.cols / 2, img.rows); imgs.push_back(img(rect).clone()); rect.x = img.cols / 3; imgs.push_back(img(rect).clone()); rect.x = img.cols / 2; imgs.push_back(img(rect).clone()); } else imgs.push_back(img); } } end=clock(); cout<<"圖像讀取時間: "<double)(end-start)/CLOCKS_PER_SEC<< return EXIT_SUCCESS;}線程池對應的定義與實現
2. c.h
#ifndef _CONDITION_H_#define _CONDITION_H_#include //封裝一個互斥量和條件變量作為狀態typedef struct condition{ pthread_mutex_t pmutex; pthread_cond_t pcond;}condition_t;//對狀態的操作函數int condition_init(condition_t *cond);int condition_lock(condition_t *cond);int condition_unlock(condition_t *cond);int condition_wait(condition_t *cond);int condition_timedwait(condition_t *cond, const struct timespec *abstime);int condition_signal(condition_t* cond);int condition_broadcast(condition_t *cond);int condition_destroy(condition_t *cond);#endif3. c.cpp
#include "c.h"//初始化int condition_init(condition_t *cond){ int status; if((status = pthread_mutex_init(&cond->pmutex, NULL))) return status; if((status = pthread_cond_init(&cond->pcond, NULL))) return status; return 0;}//加鎖int condition_lock(condition_t *cond){ return pthread_mutex_lock(&cond->pmutex);}//解鎖int condition_unlock(condition_t *cond){ return pthread_mutex_unlock(&cond->pmutex);}//等待int condition_wait(condition_t *cond){ return pthread_cond_wait(&cond->pcond, &cond->pmutex);}//固定時間等待int condition_timedwait(condition_t *cond, const struct timespec *abstime){ return pthread_cond_timedwait(&cond->pcond, &cond->pmutex, abstime);}//喚醒一個睡眠線程int condition_signal(condition_t* cond){ return pthread_cond_signal(&cond->pcond);}//喚醒所有睡眠線程int condition_broadcast(condition_t *cond){ return pthread_cond_broadcast(&cond->pcond);}//釋放int condition_destroy(condition_t *cond){ int status; if((status = pthread_mutex_destroy(&cond->pmutex))) return status; if((status = pthread_cond_destroy(&cond->pcond))) return status; return 0;}4. t.h
#ifndef _THREAD_POOL_H_#define _THREAD_POOL_H_//線程池頭文件#include "c.h"//封裝線程池中的對象需要執行的任務對象typedef struct task{ void *(*run)(void *args); //函數指針,需要執行的任務 void *arg; //參數 struct task *next; //任務隊列中下一個任務}task_t;//下面是線程池結構體typedef struct threadpool{ condition_t ready; //狀態量 task_t *first; //任務隊列中第一個任務 task_t *last; //任務隊列中最后一個任務 int counter; //線程池中已有線程數 int idle; //線程池中kongxi線程數 int max_threads; //線程池最大線程數 int quit; //是否退出標志}threadpool_t;//線程池初始化void threadpool_init(threadpool_t *pool, int threads);//往線程池中加入任務void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg);//摧毀線程池void threadpool_destroy(threadpool_t *pool);#endif5. t.cpp
#include "t.h"#include #include #include #include #include //創建的線程執行void *thread_routine(void *arg){ struct timespec abstime; int timeout; printf("thread %d is starting\n", (int)pthread_self()); threadpool_t *pool = (threadpool_t *)arg; while(1) { timeout = 0; //訪問線程池之前需要加鎖 condition_lock(&pool->ready); //空閑 pool->idle++; //等待隊列有任務到來 或者 收到線程池銷毀通知 while(pool->first == NULL && !pool->quit) { //否則線程阻塞等待 printf("thread %d is waiting\n", (int)pthread_self()); //獲取從當前時間,并加上等待時間, 設置進程的超時睡眠時間 clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += 2; int status; status = condition_timedwait(&pool->ready, &abstime); //該函數會解鎖,允許其他線程訪問,當被喚醒時,加鎖 if(status == ETIMEDOUT) { printf("thread %d wait timed out\n", (int)pthread_self()); timeout = 1; break; } } pool->idle--; if(pool->first != NULL) { //取出等待隊列最前的任務,移除任務,并執行任務 task_t *t = pool->first; pool->first = t->next; //由于任務執行需要消耗時間,先解鎖讓其他線程訪問線程池 condition_unlock(&pool->ready); //執行任務 t->run(t->arg); //執行完任務釋放內存 free(t); //重新加鎖 condition_lock(&pool->ready); } //退出線程池 if(pool->quit && pool->first == NULL) { pool->counter--;//當前工作的線程數-1 //若線程池中沒有線程,通知等待線程(主線程)全部任務已經完成 if(pool->counter == 0) { condition_signal(&pool->ready); } condition_unlock(&pool->ready); break; } //超時,跳出銷毀線程 if(timeout == 1) { pool->counter--;//當前工作的線程數-1 condition_unlock(&pool->ready); break; } condition_unlock(&pool->ready); } printf("thread %d is exiting\n", (int)pthread_self()); return NULL;}//線程池初始化void threadpool_init(threadpool_t *pool, int threads){ condition_init(&pool->ready); pool->first = NULL; pool->last =NULL; pool->counter =0; pool->idle =0; pool->max_threads = threads; pool->quit =0;}//增加一個任務到線程池void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg){ //產生一個新的任務 task_t *newtask = (task_t *)malloc(sizeof(task_t)); newtask->run = run; newtask->arg = arg; newtask->next=NULL;//新加的任務放在隊列尾端 //線程池的狀態被多個線程共享,操作前需要加鎖 condition_lock(&pool->ready); if(pool->first == NULL)//第一個任務加入 { pool->first = newtask; } else { pool->last->next = newtask; } pool->last = newtask; //隊列尾指向新加入的線程 //線程池中有線程空閑,喚醒 if(pool->idle > 0) { condition_signal(&pool->ready); } //當前線程池中線程個數沒有達到設定的最大值,創建一個新的線性 else if(pool->counter < pool->max_threads) { pthread_t tid; pthread_create(&tid, NULL, thread_routine, pool); pool->counter++; } //結束,訪問 condition_unlock(&pool->ready);}//線程池銷毀void threadpool_destroy(threadpool_t *pool){ //如果已經調用銷毀,直接返回 if(pool->quit) { return; } //加鎖 condition_lock(&pool->ready); //設置銷毀標記為1 pool->quit = 1; //線程池中線程個數大于0 if(pool->counter > 0) { //對于等待的線程,發送信號喚醒 if(pool->idle > 0) { condition_broadcast(&pool->ready); } //正在執行任務的線程,等待他們結束任務 while(pool->counter) { condition_wait(&pool->ready); } } condition_unlock(&pool->ready); condition_destroy(&pool->ready);}6. 顯示:
總結
以上是生活随笔為你收集整理的opencv 多线程加速_线程池给你写好了,想加速拿来用就行哈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 西安治疗多囊卵巢综合症最好的医院推荐
- 下一篇: python闭包的应用场景_简单谈谈Py