图像的滤波操作是指对图像进行一系列的像素值处理,以实现图像增强、去噪、平滑等效果。常见的滤波操作包括均值滤波、高斯滤波、中值滤波等。
在设计并行图像处理程序时,可以选择其中一种滤波操作进行示例。这里以均值滤波为例进行说明。均值滤波是典型的线性滤波算法,是指用当前像素点周围nxn个像素值的均值来代替当前像素值。使用该方法遍历处理图像内的每一个像素点,可完成整幅图像的均值滤波。
我们对第5行第5列的像素点进行均值滤波时,首先需要考虑需要对周围多少个像素点去取平均值。通常情况下,我们会以该当前像素为中心,对行数和列数相等的一块区域内的所有像素点的像素取平均值。
例如,我们可以以当前像素点的像素周围3x3区域内所有像素点的像素取平均值,也可以对周围5x5区域内所有像素点的像素值取平均值。
针对边缘的像素点,可以只取图像内存在的周围领域点的像素值均值
计算方法如下:像素点新值=[(23+158+140)+(238+0+67)+(199+197+25)]/9=116。 针对第5行第5列的像素点,其运算过程相当于一个额内部值是1/25的5*5矩阵进行相乘运算,从而得到均值滤波的结果为126。如图3(针对第 5 行第 5 列像素点均值滤波的运算示意图)所示。
根据上述运算,针对每一个像素点,都是与一个内部值均为1/25的5*5矩阵相乘,得到均值滤波的计算结果。示意图如图4(针对每一个像素点均值滤波的运算示意图)所示。
给定一个输入图像,将其划分为多个块,并使用多个进程对每个块进行滤波操作。
要求:
1、使用分段并行结构和指令section来并行执行不同的计算步骤。
2、使用单线程指令single或master确保某些代码段只在单个线程中执行。
3、使用线程同步和阻塞机制来确保所有线程在进入下一步处理之前完成当前步骤的计算。
4、使用任务池并行化来处理滤波操作,并根据图像块的大小和数量选择静态任务或动态任务。
#include <iostream>
#include <vector>
#include <omp.h>
// 定义图像块结构体
struct ImageBlock {
int start_x;
int start_y;
int size;
};
// 模拟图像滤波操作
void filter_block(const ImageBlock& block, const std::vector<std::vector<int>>& input_image, std::vector<std::vector<int>>& output_image) {
int sum = 0;
int count = 0;
// 计算均值
for (int y = block.start_y; y < block.start_y + block.size; ++y) {
for (int x = block.start_x; x < block.start_x + block.size; ++x) {
if (x >= 0 && x < input_image[0].size() && y >= 0 && y < input_image.size()) {
sum += input_image[y][x];
count++;
}
}
}
int average = sum / count;
// 将均值赋给输出图像块
for (int y = block.start_y; y < block.start_y + block.size; ++y) {
for (int x = block.start_x; x < block.start_x + block.size; ++x) {
if (x >= 0 && x < output_image[0].size() && y >= 0 && y < output_image.size()) {
output_image[y][x] = average;
}
}
}
}
int main() {
const int IMAGE_WIDTH = 1024;
const int IMAGE_HEIGHT = 768;
const int BLOCK_SIZE = 64;
std::vector<std::vector<int>> input_image(IMAGE_HEIGHT, std::vector<int>(IMAGE_WIDTH));
std::vector<std::vector<int>> output_image(IMAGE_HEIGHT, std::vector<int>(IMAGE_WIDTH));
// 初始化输入图像
for (int y = 0; y < IMAGE_HEIGHT; ++y) {
for (int x = 0; x < IMAGE_WIDTH; ++x) {
input_image[y][x] = y * IMAGE_WIDTH + x; // 假设输入图像为从左上角开始递增的像素值
}
}
// 设置线程数
double start_time = omp_get_wtime();
// 使用OpenMP并行处理图像块
#pragma omp parallel
{
#pragma omp single
{
std::cout << "Filtering image..." << std::endl;
}
#pragma omp for schedule(static)
for (int y = 0; y < IMAGE_HEIGHT; y += BLOCK_SIZE) {
for (int x = 0; x < IMAGE_WIDTH; x += BLOCK_SIZE) {
ImageBlock block = {x, y, BLOCK_SIZE};
filter_block(block, input_image, output_image);
}
}
}
double end_time = omp_get_wtime();
printf("Elapsed time: %.4f seconds\n", end_time - start_time);
// 输出结果
/*
std::cout << "Filtered image:" << std::endl;
for (int y = 0; y < IMAGE_HEIGHT; ++y) {
for (int x = 0; x < IMAGE_WIDTH; ++x) {
std::cout << output_image[y][x] << " ";
}
std::cout << std::endl;
}
*/
return 0;
}
运行结果如下:
monkeycode@ln0:~/training_system/chenzhaoxiang/OpenMP$ yhrun -p thcp1 -n 1 -c 1 image_processing
Filtering image...
Elapsed time: 0.0165 seconds
monkeycode@ln0:~/training_system/chenzhaoxiang/OpenMP$ yhrun -p thcp1 -n 1 -c 4 image_processing
Filtering image...
Elapsed time: 0.0095 seconds
monkeycode@ln0:~/training_system/chenzhaoxiang/OpenMP$ yhrun -p thcp1 -n 1 -c 16 image_processing
Filtering image...
Elapsed time: 0.0104 seconds
monkeycode@ln0:~/training_system/chenzhaoxiang/OpenMP$ yhrun -p thcp1 -n 1 -c 64 image_processing
Filtering image...
Elapsed time: 0.0142 seconds