图像拼接实现见

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

opencv 多线程加速_线程池给你写好了,想加速拿来用就行哈相关推荐

  1. 第十章_多线程(2)_线程池原子性并发工具类

    目录 一.线程池 1 - 线程状态 2 - 线程池 3 - Executors线程池 二.Volatile 三.原子性 四.并发工具类 1 - 并发工具类-Hashtable 2 - 并发工具类-Co ...

  2. Java多线程之线程池的手写改造和拒绝策略

    Java多线程之线程池的手写改造和拒绝策略 目录 自定义线程池的使用 四种拒绝策略代码体现 1. 自定义线程池的使用 自定义线程池(拒绝策略默认AbortPolicy) public class My ...

  3. Java多线程系列--“JUC线程池”06之 Callable和Future

    转载自  Java多线程系列--"JUC线程池"06之 Callable和Future Callable 和 Future 简介 Callable 和 Future 是比较有趣的一 ...

  4. linux下c语言线程传参数,【linux】C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0...

    C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0 本贴问题,之前已经提问过一次,当时已经解决了,原贴在这里https://segmentfault.com/q/1 ...

  5. future 线程报错后_线程池运用实例——一次错误的多线程程序设计以及修复过程...

    写在前面的话 写下这篇文章只为了回顾之前在实际工作中犯的一个极其二逼的错误,用我的经历来提示后来者,诸位程序大神,大牛,小牛们看到此文笑笑即可,轻拍轻拍... 1 背景 有这么一个需求,我们的系统(后 ...

  6. java开源线程池_线程池 - Java 并发性和多线程 - UDN开源文档

    线程池 线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用.因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等. 我们可以把并发执行的任务传递给一个 ...

  7. Java多线程设计模式(4)线程池模式

    前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将"委托消息的一端"和"执行消息的一端&qu ...

  8. java多线程抽奖_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码...

    导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...

  9. 掌握JAVA多线程的利器-线程池

    为什么80%的码农都做不了架构师?>>>    相信大多数接触过多线程的朋友都会有这样的困惑,明明使用了多线程,为何还是一团糟?用下面两幅图再合适不过了: 理想情况下的多线程VS 现 ...

最新文章

  1. flume源码学习8-hdfs sink的具体写入流程
  2. 一晚上就能让你小腹变小的方法 - 健康程序员,至尚生活!
  3. java 连接sqlserver2005_JAVA用jdbc连接SQLServer2005
  4. 2.1.3 计算机网络之编码与调制
  5. 通用权限实现的核心设计思想
  6. DWZ与百度编辑器的IE8以下上传图片兼容问题
  7. 放大器的传递函数_保证放大器的稳定性什么最重要?反馈电阻一定要选对!
  8. 又到618,.NET 千万级秒杀架构到底有多牛
  9. elasticsearch 中文分词
  10. 树形动态规划 java_树形动态规划
  11. 云端战争是一场马拉松,未来格局不会一家独大
  12. java调用geth_php调用以太坊geth API说明
  13. java计算机毕业设计民宿运营管理网站源码+mysql数据库+系统+lw文档+部署
  14. Html和css算是编程语言吗,不被承认的编程语言
  15. 鸿蒙系统清理垃圾,极速清理系统垃圾 一举收回上G磁盘空间
  16. Http协议的身份认证
  17. HRBUSTOJ 1313 火影忍者之~静音 【模拟】【排序】
  18. off文件转obj文件
  19. Mac下压缩和解压rar文件的方法
  20. 配置windows iis

热门文章

  1. 机器人教育发展_得于人工智能发展,机器人教育低龄化越来越普及
  2. Linux Socket API Connect 函数详解
  3. OSI七层网络模型与TCP/IP四层网络模型
  4. shell获取当前执行脚本的路径
  5. 仅使用HTML和CSS实现的标签云效果
  6. 计算机如何学会自动地进行图像美学增强?
  7. 网页设计html加音频,HTML5网页中如何嵌入音频,视频?
  8. 前端渲染与后端渲染之间的区别?
  9. 计算机硬件知识竞赛题库,电脑知识竞赛题库.pdf
  10. mysql 数据如何存储,MySQL如何存储数据