申明: 仅个人小记
前言:大图像的处理,根据实际的操作,可以考虑通过多线程来加速图像的处理。本例中,通过一个简单的求图像的均值例子展现在C++中使用多线程来加速对图像的处理。
基本思想:
- 将一张图像分为四个部分(左上,左下,右上,右下)
- 创建四个线程,分别计算被指定的部分的总和
- 各个线程计算完毕,将部分和累加到一个外部的公共变量totalSum(注意这是对公共变量的写操作,需要加锁)
- 统计每个线程各自花费的时间和总共花费的时间
- 作为对照,再在主程序中,整体计算图像的总和
- 比较数据的正确性和时间花费
本例图像分块效果如图:
程序代码
#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;
}
运行结果
简要分析
- 运行结果可以看到四个线程各自花费的时间,四个线程的花费时间总额显然低于整体的时间花费。
- 运行均值数据结果一致
By Jack Lu 2017年7月7日 21:09:33