Parallel and Distributed Computing
Parallel Image Processing Using OpenMP (C++)
Course Project Report - Parallel and Distributed Computing
Team Members
Muhammad Talha Nizamani
Muhammad Anas
Roll No
CS221003
CS221004
Department: Computer Science
University: DHA Suffa University
Date: 21 January 2026
Page 1
Parallel and Distributed Computing
Abstract
This project demonstrates shared-memory parallel programming with OpenMP by accelerating common
image processing filters on a multi-core CPU. A baseline serial implementation is compared against
OpenMP-parallel versions for grayscale conversion, box blur, and Sobel edge detection. The program
loads a JPG or PNG image, generates filtered outputs, and benchmarks execution time across multiple
thread counts. The results show measurable speedup for compute-heavy filters, while memory-bound
filters achieve more limited scaling.
Keywords: OpenMP, shared memory, parallel for, image processing, Sobel, box blur, benchmarking
1. Introduction
Modern CPUs contain multiple cores capable of executing threads concurrently. OpenMP is a widely
used API for shared-memory parallelism that enables developers to parallelize loops and tasks with
minimal code changes. Image processing workloads are a natural fit for OpenMP because many
operations perform the same computation independently across pixels or small neighborhoods.
2. Objectives
Implement three image processing filters in C++: grayscale, box blur, and Sobel edge detection.
Develop both serial and OpenMP-parallel versions of each filter.
Benchmark runtime for different thread counts and compute speedup.
Demonstrate correctness by saving output images for visual verification.
3. System and Tools
Software stack used for this project:
Language: C++17
Parallel API: OpenMP (OpenMP 5.2 features are sufficient for this project)
Build system: CMake
Compiler: MinGW g++ on Windows 11 (or any OpenMP-capable compiler)
Image I/O: stb_image.h and stb_image_write.h single-header libraries
OpenMP specifications and reference materials are published by the OpenMP Architecture Review
Board (ARB). The stb libraries are maintained in the public repository by Sean Barrett (nothings).
4. Design Overview
The program follows a simple pipeline: (1) load image as RGB byte array, (2) run one or more filters, (3)
write outputs as PNG, (4) benchmark serial and parallel runtimes.
Page 2
Parallel and Distributed Computing
4.1 Data representation
Images are stored as an RGB buffer of unsigned bytes with size width * height * 3. Pixel (x, y) starts at
index (y * width + x) * 3.
4.2 Filters implemented
Grayscale
Each pixel is converted to a single intensity value using a weighted RGB approximation, then written
back to R, G, and B channels. This is a per-pixel operation with no neighborhood dependency.
Box blur
For each pixel (excluding borders), the blur output is the average of a square neighborhood of size (2r +
1) x (2r + 1), where r is the blur radius. The implementation reads from the input buffer and writes to a
separate output buffer to avoid data hazards.
Sobel edge detection
The Sobel operator estimates the image intensity gradient using two 3x3 kernels (Gx and Gy). The
magnitude is approximated with abs(Gx) + abs(Gy) and clamped to [0, 255]. The output is written as a
grayscale RGB image where stronger edges appear brighter.
5. Parallelization with OpenMP
All three filters are parallelized by distributing image rows across threads using OpenMP parallel for. This
is safe because each output pixel is written exactly once, and each thread writes to distinct indices.
5.1 OpenMP directives used
parallel for: parallelizes the outer loop over rows.
schedule(static): assigns contiguous row blocks to threads, suitable for uniform work per pixel.
omp_set_num_threads(t): sets thread count for benchmarking runs.
omp_get_wtime(): measures wall-clock time for performance analysis.
5.2 Avoiding race conditions
Neighborhood-based filters (box blur and Sobel) must not overwrite input pixels that are still needed for
other computations. To prevent race conditions and incorrect results, the program reads from an
immutable input buffer and writes the computed pixels into a separate output buffer. After a pass
completes, buffers can be swapped if multiple stages are chained.
Page 3
Parallel and Distributed Computing
6. Complexity Analysis
Let N = width * height be the number of pixels.
Filter Time complexity Notes
Grayscale O(N) One pass over pixels
Box blur O(N * k^2) k = 2r + 1 neighborhood size
Sobel O(N) Constant-size 3x3 neighborhood
per pixel
In practice, grayscale may be limited by memory bandwidth, while box blur and Sobel can benefit more
from parallel execution due to higher arithmetic intensity.
7. Build and Run Instructions (Windows 11, MinGW, CMake)
From the project root in PowerShell:
rmdir /s /q build 2>$null
mkdir build
cd build
cmake -G "MinGW Makefiles" ..
cmake --build . -j
.\img_omp.exe ..\input\[Link] ..\output 1,2,4,8 3
Program arguments:
input_image: path to JPG or PNG input image
output_dir: folder where output PNGs are saved
threads_list: comma-separated thread counts for benchmarking, for example 1,2,4,8
blur_radius: integer radius for box blur, typical values are 2 to 5
Page 4
Parallel and Distributed Computing
8. Experimental Results
This section should include results from the target machine. The table below provides sample results to
illustrate the expected reporting format. Replace these sample values with your measured timings.
Filter Threads Time (s) Speedup vs serial Efficiency
Grayscale Serial 0.120 1.00 1.00
Grayscale 1 0.121 0.99 0.99
Grayscale 2 0.070 1.71 0.86
Grayscale 4 0.040 3.00 0.75
Grayscale 8 0.032 3.75 0.47
Box blur (r=3) Serial 1.800 1.00 1.00
Box blur (r=3) 1 1.820 0.99 0.99
Box blur (r=3) 2 1.020 1.76 0.88
Box blur (r=3) 4 0.580 3.10 0.77
Box blur (r=3) 8 0.420 4.29 0.54
Sobel Serial 0.950 1.00 1.00
Sobel 1 0.960 0.99 0.99
Sobel 2 0.550 1.73 0.86
Sobel 4 0.310 3.06 0.77
Sobel 8 0.240 3.96 0.50
Speedup is computed as T_serial / T_parallel. Efficiency is Speedup / Threads. Scaling typically improves
up to the number of physical cores, then flattens due to overheads and memory bandwidth limits.
9. Discussion
Grayscale is often memory-bound. Each thread reads and writes large contiguous buffers, so
speedup is limited by memory bandwidth.
Box blur has higher arithmetic intensity because each output pixel sums many neighbors. This
typically produces stronger speedup.
Sobel uses a small fixed neighborhood and tends to scale well until memory bandwidth becomes the
limiting factor.
Speedup flattens when thread count exceeds available physical cores or when OpenMP overhead
becomes significant for smaller images.
10. Limitations and Future Work
The current box blur is a straightforward implementation; separable blur or integral image
optimization would reduce complexity.
Border handling is kept simple; more advanced padding strategies can improve visual quality.
Additional filters can be added (Gaussian blur, sharpen, median filter) to demonstrate more
workloads.
A plotting script can be added to automatically generate speedup graphs from benchmark output.
Page 5
Parallel and Distributed Computing
11. Conclusion
This project demonstrates how OpenMP can parallelize image processing workloads on shared-memory
systems. Using a small number of OpenMP directives, the program accelerates per-pixel and
neighborhood-based filters and provides a benchmarking harness to measure performance across
thread counts. The approach highlights core parallel programming concepts such as work-sharing loops,
avoiding race conditions, and evaluating scalability.
References
1. OpenMP Architecture Review Board. OpenMP API Specifications. [Link].
2. OpenMP Architecture Review Board. OpenMP 5.2 Specification (PDF), November 2021.
3. Barrett, S. (nothings). stb single-file public domain libraries for C/C++. GitHub repository.
4. Sobel, I., and Feldman, G. Isotropic 3x3 Image Gradient Operator (talk at Stanford AI Laboratory,
1968).
Page 6
Parallel and Distributed Computing
Appendix A: Reproducible Commands
Download stb headers (PowerShell):
mkdir third_party -Force | Out-Null
[Link] -L "[Link] -o
"third_party\stb_image.h"
[Link] -L "[Link]
-o "third_party\stb_image_write.h"
Build and run:
rmdir /s /q build 2>$null
mkdir build
cd build
cmake -G "MinGW Makefiles" ..
cmake --build . -j
.\img_omp.exe ..\input\[Link] ..\output 1,2,4,8 3
Page 7