在OpenCV中,使用ROI(Region of Interest)来处理图像的特定区域是一个常见的做法。当需要在多线程环境下对图像的不同区域进行处理时,可以将图像分割成多个区块,并将每个区块分配给不同的线程进行处理。
以下是一个使用C++和OpenCV进行多线程图像分块处理的简单例子:
int main(int argc, char *argv[])
{
cv::Mat src;
cv::Mat dst1(src.size(), CV_8UC1);
src = cv::imread("../../test/img/2.jpg");
/****************单线程******************/
cv::Mat mask(src.size(), CV_8UC1);
cv::Mat roi(mask, {100,100,mask.cols - 200, mask.rows - 200});
roi.setTo(cv::Scalar(255));
cv::imwrite("../../test/img/mask.jpg", mask);
cv::Mat gray;
cvtColor(src, gray, CV_BGR2GRAY);
auto t = clock();
cv::threshold(gray, dst1, 0, 255, CV_THRESH_OTSU);
std::cout << "sigle thread time " << clock() - t << std::endl;
cv::imwrite("../../test/img/2_inp.jpg", dst1);
/****************多线程******************/
cv::Mat dst2(src.size(), CV_8UC1);
cv::Size size = src.size();
// 分成9块 (3x3)
int n = 3;
int widthPerBlock = size.width / n;
int heightPerBlock = size.height / n;
std::vector<std::thread> threads;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int x = j * widthPerBlock;
int y = i * heightPerBlock;
int width = (j == n - 1) ? size.width - x : widthPerBlock;
int height = (i == n - 1) ? size.height - y : heightPerBlock;
cv::Rect roi(x, y, width, height);
threads.push_back(std::thread([&](cv::Rect roi_){
cv::Mat gray_roi(gray, roi_);
cv::Mat mask_roi(mask, roi_);
cv::Mat dst_roi(dst2, roi_);
cv::threshold(gray_roi, dst_roi, 0, 255, CV_THRESH_OTSU);
},roi));
}
}
t = clock();
for (auto& t : threads) {
t.join();
}
std::cout << "9 thread time " << clock() - t << std::endl;
cv::imwrite("../../test/img/2_thread.jpg", dst2);
return 0;
}
图像大小:1760*2432
时间对比:
多线程 | 多线程 |
7ms | 18ms |
左中右依次是:原图 多线程 单线程处理结果