线程 invalid use of void expression_线程池给你写好了,想加速拿来用就行哈

1184437acf9a5f9a7436e256ff53fe47.png

图像拼接实现见

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);#endif

3. 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);#endif

5. 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. 显示:

7262ff1595a9a99f7dfff0c115f115fd.png

ee10b8fda06168129b23648bdd2cfbd7.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值