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

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

9abfcaa1f00e1d760acfc83c89b02aed.png

222acaa128d3f7ee4cbe883823ab355d.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

poping 心法

音乐 01.Eamon - (How Could You) Bring Him Home02.The Pussycat Dolls - Buttons03.Most Wanted ft. Fingazz, Volture -From Juvi To The Penitentiary (Instrumental)04.Kaila Yu - Move05.Danity Kane - Show Stopper06.Slick Dogg - Bang On m07.Danity Kane - Show Stop…

html5 video修改默认样式,HTML5中将video设置为背景的方法

主要用到了video标签&#xff0c;css样式&#xff0c;原理是先将video标签利用position:fixed;使video标签脱离文档流&#xff0c;在将他的z-index设置为最低的&#xff0c;比如-9999。再插入的内容自然就覆盖在视频上面了。1.首先&#xff0c;将video插入到网页中&#xff0c;…

ES6语法的学习与实践

ES6是JavaScript语言的新一代标准&#xff0c;是ECMAScript的第六个版本&#xff0c;加入了很多新的功能和语法&#xff0c;在很多框架&#xff0c;如在使用Vue,React等框架的项目中一般都采用ES6语法来编写的&#xff0c;下面对经常用到的ES6语法做简要的介绍。 1.let,const l…

这是一次 docker 入门实践

前言 其实接触 docker 也有一段时间了&#xff0c;但是一直没有做下总结&#xff0c;现在网上关于 docker 的介绍也有很多了&#xff0c;本着好记性不如烂笔头的原则&#xff0c;还是自己再记录一波吧。 实现目标 安装 docker ce 探索 docker 基本概念及用法环境准备 Centos7 6…

html dom概念,js学习之HTML DOM的一些基础概念

经过近一个星期,总算把w3chool上的HTML DOM的实例差不多看了一遍,因为本身对其中的很多都用过,所以看起来也很快,现在就再系统的回顾下HTML DOM的一些概念和基础的东西,大部分都是从w3school上看到的什么是DOMDOM是w3c(万维网联盟)的标准DOM定义了访问HTML和XML的标准"W3C…

关于Java垃圾收集

本文讨论的是使用的最受欢迎的框架之一带来的开销–我敢打赌&#xff0c;几乎没有应用程序不使用java.util.Collections。 本文基于以下事实&#xff1a;框架为例如集合的初始大小提供了默认值。 因此&#xff0c;我们有一个假设&#xff0c;即大多数人不会费心地自行管理其收…

ansys命令流_ANSYS命令流建模3之划分单元+施加弹簧

以马蹄形隧道为例&#xff0c;本文介绍如何添加荷载等隧道如上图所示!设置线单元材料属性&#xff0c;划分单元(二衬单元)lsel,s,,,1,6 !LSEL,Type,Item,Comp,VMIN, VMAX,VINClATT,1,1,3 !给线单元付材料号、实常数、单元类型号 LATT, MAT, REAL, TYPE, ESYSMSHKEY,1 …

Linux 系统中用户切换(su user与 su - user 的区别)

1,su命令 &#xff08;su为switch user&#xff0c;即切换用户的简写&#xff09; 格式&#xff1a;su -l USERNAME&#xff08;-l为login&#xff0c;即登陆的简写&#xff0c;其中l可以省略&#xff09; 如果不指定USERNAME&#xff08;用户名&#xff09;&#xff0c;默认即…

正则表达式常用方法

RegExp对象中的方法 1&#xff0c;test()方法用于检测一个字符串是否匹配某个模式&#xff0c;如果字符串中含有匹配的文本&#xff0c;则返回 true&#xff0c;否则返回 false。 reg规定匹配以a开头的字符串&#xff0c;利用test进行测试&#xff0c;字符串str满足reg匹配规则…

python安装哪个版本好啊_windows10安装哪个版本的Python?

python2除了一些大公司历史遗留问题还在使用&#xff0c;目前中小创公司使用最多的是python3 大公司的一些新项目也开始用python3了 目前来说&#xff0c;python3.5以上的版本都可以 目前使用最多的是python3.7&#xff08;建议你安装这个&#xff09; 最新的是python3.8&#…

mongose + express 写REST API

一、准备工具 先确保电脑已经安装好nodejs 1.mongoose&#xff1b;安装非常简单: npm install mongoose --save 【mongoose封装了mongodb的方法&#xff0c;调用mongoose的api可以很轻松的对mongodb进行操作】 2.express&#xff1b;npm install express --save …

js实现html模板继承,理解JavaScript中的原型和继承

本文主要讲了原型如何在JavaScript中工作&#xff0c;以及如何通过[Prototype]所有对象共享的隐藏属性链接对象属性和方法&#xff1b;以及如何创建自定义构造函数以及原型继承如何工作以传递属性和方法值。介绍JavaScript是一种基于原型的语言&#xff0c;这意味着对象属性和方…

骁龙660是32位还是64位_高通发布骁龙 7c/8c 芯片,以后你可能会在电脑上看到它...

高通的芯片生意早已不局限于移动设备领域&#xff0c;而是进一步深入至 PC 市场。相比强调性能的 X86 芯片&#xff0c;以高通骁龙为代表的 ARM 系芯片则希望突出自己的优势&#xff0c;即更长的电池续航、无风扇设计和全天候的蜂窝网络连接。在骁龙技术峰会的第三天&#xff0…

css3之盒模型

什么是盒模型&#xff1f; css中的每个元素都是一个盒模型&#xff0c; 包括html body元素&#xff0c; 浏览器解析css的时候也会把每个元素看成一个盒子来解析。 盒模型具备的属性有&#xff1a; content 、padding 、margin、border 、background等 盒模型的分类&#xff1…

学计算机的误解,让人误解的六大专业

原标题&#xff1a;让人误解的六大专业隔行如隔山&#xff0c;很多人喜欢看名字猜专业&#xff0c;所以导致很多大学专业被人误解。其实了解一个专业不能仅仅凭借它的名字&#xff0c;也不能断章取义&#xff0c;只取片面意思。接下来就让我们来了解一下有哪些被人误解的专业吧…

杂项:轮询

ylbtech-杂项&#xff1a;轮询1.返回顶部 1、轮询&#xff08;Polling&#xff09;是一种CPU决策如何提供周边设备服务的方式&#xff0c;又称“程控输出入”&#xff08;Programmed I/O&#xff09;。轮询法的概念是&#xff0c;由CPU定时发出询问&#xff0c;依序询问每一个周…

js和css实现手机横竖屏预览思路整理

实现效果&#xff0c;如上图。 首先&#xff0c;实现手机页面在PC端预览&#xff0c; 则先在网上找到一个手机的背景图片&#xff0c;算好大概内间距&#xff0c;用来放预览的页面&#xff0c;我这里是给手机预览页面的尺寸按iphone5的尺寸来的&#xff1b; 一个手机页面在这里…

thinkphp日志泄漏漏洞_【Windows高危漏洞预警】CVE20200601,影响关键加密功能

一、事件报告2020年伊始&#xff0c;NSA发现了一个影响Microsoft Windows加密功能的严重漏洞(CVE-2020-0601)。证书验证漏洞允许攻击者破坏Windows验证加密信任的方式&#xff0c;并且可以启用远程代码执行。该漏洞会影响Windows 10和Windows Server 2016/2019以及依赖Windows的…

第一章计算机网络概述答案,第一章 计算机网络概述[3]

1-07 试在下列条件下比较电路交换和分组交换。要传送的报文共x(bit)。从源站到目的站共经过k段链路&#xff0c;每段链路的传播时延为d(s)&#xff0c;数据率为b(b/s)。在电路交换时电路的建立时间为S(s)。在分组交换时分组长度为p(bit)&#xff0c;且各结点的排队等待时间可忽…

最小路径算法(Dijkstra算法和Floyd算法)

1.单源点的最短路径问题&#xff1a;给定带权有向图G和源点v&#xff0c;求从v到G中其余各顶点的最短路径。 我们用一个例子来具体说明迪杰斯特拉算法的流程。 定义源点为 0&#xff0c;dist[i]为源点 0 到顶点 i 的最短路径。其过程描述如下&#xff1a; 步骤dist[1]dist[2]di…