C++多线程图像分块处理示例

申明: 仅个人小记

前言:大图像的处理,根据实际的操作,可以考虑通过多线程来加速图像的处理。本例中,通过一个简单的求图像的均值例子展现在C++中使用多线程来加速对图像的处理。

基本思想:

  1. 将一张图像分为四个部分(左上,左下,右上,右下)
  2. 创建四个线程,分别计算被指定的部分的总和
  3. 各个线程计算完毕,将部分和累加到一个外部的公共变量totalSum(注意这是对公共变量的写操作,需要加锁)
  4. 统计每个线程各自花费的时间和总共花费的时间
  5. 作为对照,再在主程序中,整体计算图像的总和
  6. 比较数据的正确性和时间花费

本例图像分块效果如图:

程序代码

#include <opencv2/highgui/highgui.hpp>// 提供imread读取图片函数
using namespace cv;

#include <iostream>
#include <thread> // 提供线程类
#include <mutex> // 提供互斥锁类(对部分和进行累加的时候需要加锁),很好用

using namespace std;

mutex mtx;// 定义一个互斥锁
long totalSum;// 总和
const enum RangeSpecify{LEFT_UP, LEFT_DOWN,RIGHT_UP,RIGHT_DOWN};

void ImageAverage(Mat & img, enum RangeSpecify r)// 线程代码
{
    int startRow, startCol, endRow, endCol;
    switch (r){
    case LEFT_UP: 
        startRow = 0;
        endRow = img.rows / 2;
        startCol = 0;
        endCol = img.cols / 2;
        break;
    case LEFT_DOWN:
        startRow = img.rows / 2;
        endRow = img.rows;
        startCol = 0;
        endCol = img.cols / 2;
        break;
    case RIGHT_UP:
        startRow = 0;
        endRow = img.rows / 2;
        startCol = img.cols / 2;
        endCol = img.cols;
        break;
    case RIGHT_DOWN:
        startRow = img.rows / 2;
        endRow = img.rows;
        startCol = img.cols / 2;
        endCol = img.cols;
        break;
    }
    double t = (double)getTickCount();
    long sum = 0;
    for (int i = startRow; i < endRow; i++) {
        for (int j = startCol; j < endCol; j++) {
            sum += img.at<unsigned char>(i, j);
        }
    }
    mtx.lock();// 在访问公共变量totalSum 之前对其进行加锁
    totalSum += sum;
    mtx.unlock();// 访问完毕立刻解锁

    cout << r << " : " << sum << endl;
    cout << "task completed! Time elapsed " << (double)getTickCount() -t << endl;// 打印本次线程时间花费
}

int main(void)
{
    Mat src = imread("image//bigimg.png", CV_LOAD_IMAGE_GRAYSCALE);


    double t = (double)getTickCount();
    thread t0(ImageAverage, src, LEFT_UP);
    thread t1(ImageAverage, src, LEFT_DOWN);
    thread t2(ImageAverage, src, RIGHT_UP);
    thread t3(ImageAverage, src, RIGHT_DOWN);

    t0.join();// 等待子线程t0执行完毕
    t1.join();
    t2.join();
    t3.join();

    cout << endl <<"多线程总时间花费:" << (double)getTickCount() - t << endl;
    cout << "图像均值(多线程): " << totalSum*1.0 / (src.cols*src.rows) << endl << endl;

    // 验证准确性
    long sum =0;

    t = (double)getTickCount();
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            sum += src.at<unsigned char>(i, j);
        }
    }

    cout << "参照时间花费:" << (double)getTickCount() - t << endl;
    cout << "参照均值: " << sum*1.0 / (src.rows*src.cols) << endl<<endl;

    system("pause");
    return 0;
}

运行结果

简要分析

  1. 运行结果可以看到四个线程各自花费的时间,四个线程的花费时间总额显然低于整体的时间花费。
  2. 运行均值数据结果一致

By Jack Lu 2017年7月7日 21:09:33

  • 7
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值