赞
踩
cv::parallel_for_
函数进行多线程处理。这个函数接受一个 cv::Range 对象和一个 cv::ParallelLoopBody
对象作为参数。cv::Range 表示要处理的数据范围,cv::ParallelLoopBody 表示要执行的任务。cv::ParallelLoopBody
是 OpenCV 中的一个类,用于多线程处理图像或视频数据。它是一个纯虚类,需要子类继承并实现它的 operator()
函数。cv::parallel_for_
函数时,OpenCV 会将数据范围分成多个子范围,并创建多个线程来执行 cv::ParallelLoopBody
中的任务。每个线程负责处理其中一个子范围。当所有线程都完成任务后,cv::parallel_for_
函数才会返回。因此,cv::ParallelLoopBody 的作用就是实现并行处理算法,以提高图像或视频处理的速度。它可以在 OpenCV 中使用多线程来处理大量数据,从而使算法更加高效。
#include <functional>
#include <iostream>
#include <opencv2/opencv.hpp>
class GrayscaleTransform : public cv::ParallelLoopBody {
public:
GrayscaleTransform(cv::Mat &image) : img(image) {}
virtual void operator()(const cv::Range &range) const {
for (int r = range.start; r < range.end; ++r) {
for (int c = 0; c < img.cols; ++c) {
cv::Vec3b &pixel = img.at<cv::Vec3b>(r, c);
uchar gray = cv::saturate_cast<uchar>(
0.299 * pixel[2] + 0.587 * pixel[1] + 0.114 * pixel[0]);
pixel[0] = gray;
pixel[1] = gray;
pixel[2] = gray;
}
}
}
private:
cv::Mat &img;
};
int main() {
cv::Mat image = cv::imread("../lena.png");
if (image.empty()) {
std::cerr << "Failed to read image" << std::endl;
return 1;
}
GrayscaleTransform transform(image);
cv::parallel_for_(cv::Range(0, image.rows), transform);
cv::imshow("Grayscale Image", image);
cv::waitKey(0);
return 0;
}
GrayscaleTransform
类,继承自 cv::ParallelLoopBody
,并实现了 operator()
函数。在 operator() 函数中,使用 cv::saturate_cast
函数来将每个像素的 RGB 值转换为灰度值,并将其赋值给每个通道。然后,将 GrayscaleTransform
的实例传递给 cv::parallel_for_
函数,该函数将数据范围划分为多个子范围,并创建多个线程来执行 GrayscaleTransform::operator()
函数。cv::parallel_for_(cv::Range(0, image.rows), transform);
函数接受两个参数:一个 cv::Range 对象和一个 cv::ParallelLoopBody 对象。
cv::Range 表示要处理的数据范围,这里是 cv::Range(0, image.rows),表示从第 0 行到最后一行,这是对整个图像进行处理。
transform 是一个 GrayscaleTransform
类的实例,也就是继承了 cv::ParallelLoopBody
类的自定义类,它的 operator() 函数将在多个线程上并行执行。
cv::parallel_for_
函数会将数据范围划分成多个子范围,并创建多个线程来执行 GrayscaleTransform::operator()
函数,从而实现图像的并行处理。
同样的功能,将具体的处理代码解耦到客户端:
#include <fstream>
#include <functional>
#include <iostream>
#include <opencv2/opencv.hpp>
/**
* @brief Helper class to do OpenCV parallelization
*
* This is a utility class required to build with older version of opencv
* On newer versions this doesn't seem to be needed, but here we just use it to
* ensure we can work for more opencv version.
* https://answers.opencv.org/question/65800/how-to-use-lambda-as-a-parameter-to-parallel_for_/?answer=130691#post-id-130691
*/
class LambdaBody : public cv::ParallelLoopBody {
public:
explicit LambdaBody(const std::function<void(const cv::Range &)> &body)
: body_(body) {}
void operator()(const cv::Range &range) const override { body_(range); }
private:
std::function<void(const cv::Range &)> body_;
};
void processImage(cv::Mat &image) {
// Create a lambda function to transform the image
auto transform = [&](const cv::Range &range) {
for (int i = range.start; i < range.end; ++i) {
// Process image row i here
for (int c = 0; c < image.cols; ++c) {
cv::Vec3b &pixel = image.at<cv::Vec3b>(i, c);
uchar gray = cv::saturate_cast<uchar>(
0.299 * pixel[2] + 0.587 * pixel[1] + 0.114 * pixel[0]);
pixel[0] = gray;
pixel[1] = gray;
pixel[2] = gray;
}
}
};
// Create a LambdaBody object and use it to parallelize the image processing
LambdaBody body(transform);
cv::parallel_for_(cv::Range(0, image.rows), body);
}
int main() {
// Load an image
cv::Mat image = cv::imread("../lena.png");
if (image.empty()) {
std::cerr << "Failed to read image" << std::endl;
return 1;
}
// Process the image
processImage(image);
// Display the processed image
cv::imshow("Processed Image", image);
cv::waitKey(0);
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。