OpenCV 中 parallel_for_理解
OpenCV 中 parallel_for_函数的具体用法,这个函数是OpenCV提供的并行化计算工具,能帮你高效低利用多核CPU加速循环类的计算任务。
一、parallel_for_ 核心概念
parallel_for_ 本质是OpenCV对多线程的封装,它会自动将一个大的循环任务拆分成多个子任务,分配到不同的CPU核心上并行执行,核心优势是:
无需手动管理线程创建/销毁,OpenCV内部自动处理;
适配不同核心数的CPU,兼容性强
语法简洁,只需定义“要并行执行的任务逻辑”即可。
它的核心参数:
/
// void parallel_for_(const Range &range, const ParallelLoopBody &body, double nstripes = -1.);
/
Range:指定循环的范围(如Range(0,1000)对应循环变量从0到999
parallelLoopBody:抽象类,需自定义子类并重写operator()实现具体的并行逻辑;
nstripes:可选,指定拆分的子任务数,-1表示由OpenCV自动决定(推荐)
测试代码:
点击查看代码
#include<opencv2/core.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
#include<chrono>
#include<filesystem>
#include <windows.h>
using namespace cv;
using namespace std;
using namespace chrono;
namespace fs = std::filesystem;
//自定义并行任务类:继承 ParallelLoopBody,重写 operator()
class BrightnessAdjustTask :public ParallelLoopBody {
private:
Mat& img;//待处理图像(引用传递,避免拷贝)
float brightness; //亮度调整系数
public:
//构造函数:
BrightnessAdjustTask(Mat &_img, float _brightness):img(_img),brightness(_brightness){}
//核心:重写operator(),定义每个线程要执行的子任务
void operator()(const Range& range) const override {
//获取当前线程的ID(唯一标识)
thread::id tid = this_thread::get_id();
//打印:现成ID+负责的行范围[start,end)
cout << "[线程" << tid << "] 处理行范围:"
<< range.start << "~" << range.end
<< "(共" << range.end - range.start << "行) " << endl;
//range.start -range.end 是当前线程负责的行范围
for (int i = range.start; i < range.end; i++) {
//获取第i行的像素指针(uchar 对应 8位图像)
uchar* row_ptr = img.ptr<uchar>(i);
for (int j = 0; j < img.cols * img.channels(); j++) {
//调整亮度,确保像素值在0~255范围内
row_ptr[j] = saturate_cast<uchar>(row_ptr[j] * brightness); //see1 saturate_cast
}
}
}
};
int main() {
//1.读取图像
//Mat img = imread("D:\\pic\\shalabowa.jpeg",1);
string img_path = "E:\\VSWorkSpace\\CppLearn\\CppLearn\\x64\\Debug\\1.jpg";
Mat img = cv::imread(img_path, IMREAD_COLOR);
cout << "读取成功!图片尺寸:" << img.rows << "x" << img.cols << endl;
//imshow("测试图片", img);
//waitKey(0); // 按任意键关闭窗口
if (img.empty()) {
cout << "图像读取失败!" << endl;
return -1;
}
float brightness = 1.5;// 亮度提高50%
//2. 串行遍历(对比性能)
auto start_serial = high_resolution_clock::now(); //see 怎么理解high_resolution_clock
Mat img_serial = img.clone();
for (int i = 0; i < img_serial.rows; i++)
{
uchar* row_ptr = img_serial.ptr<uchar>(i);
for (int j = 0; j < img_serial.cols * img_serial.channels(); j++)
{
row_ptr[j] = saturate_cast<uchar>(row_ptr[j] * brightness);
}
}
auto end_serial = high_resolution_clock::now();
double time_serial = duration_cast<milliseconds>(end_serial - start_serial).count();
cout << "串行执行时间:" << time_serial << " ms" << endl;
//3.并行遍历(使用parallel_for_)
auto start_parallel = high_resolution_clock::now();
Mat img_parallel = img.clone();
//定义并行任务对象
BrightnessAdjustTask task(img_parallel, brightness);
//执行并行循环:Range(0,img.rows)表示按行拆分任务
parallel_for_(Range(0, img_parallel.rows), task,5);
auto end_parallel = high_resolution_clock::now();
double time_parallel = duration_cast<milliseconds>(end_parallel - start_parallel).count();
cout << "并行执行时间:" << time_parallel << " ms" << endl;
imwrite("D:\\pic\\see\\parallel_test\\serial_result.jpg", img_serial);
imwrite("D:\\pic\\see\\parallel_test\\parallel_result.jpg", img_parallel);
}
测试结果如下:可以看出即使在多线程中增加了一些打印语句速度也明显提升
点击查看代码
读取成功!图片尺寸:1600x2406
串行执行时间:255 ms
[ INFO:0@0.499] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\parallel\registry_parallel.impl.hpp (96) cv::parallel::ParallelBackendRegistry::ParallelBackendRegistry core(parallel): Enabled backends(3, sorted by priority): ONETBB(1000); TBB(990); OPENMP(980)
[ INFO:0@0.501] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load E:\opencv\build\x64\vc15\bin\opencv_core_parallel_onetbb460_64d.dll => FAILED
[ INFO:0@0.503] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_onetbb460_64d.dll => FAILED
[ INFO:0@0.503] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load E:\opencv\build\x64\vc15\bin\opencv_core_parallel_tbb460_64d.dll => FAILED
[ INFO:0@0.505] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_tbb460_64d.dll => FAILED
[ INFO:0@0.506] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load E:\opencv\build\x64\vc15\bin\opencv_core_parallel_openmp460_64d.dll => FAILED
[ INFO:0@0.507] global c:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\utils\plugin_loader.impl.hpp (67) cv::plugin::impl::DynamicLib::libraryLoad load opencv_core_parallel_openmp460_64d.dll => FAILED
[线程23268] 处理行范围:1280~1600(共320行)
[线程20792] 处理行范围:0~320(共320行)
[线程23868] 处理行范围:320~640(共320行)
[线程23256] 处理行范围:960~1280(共320行)
[线程27300] 处理行范围:640~960(共320行)
并行执行时间:112 ms
E:\VSWorkSpace\CppLearn\x64\Debug\CppLearn.exe (进程 22056)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。

浙公网安备 33010602011771号