Optimized Belief Propagation (CPU and GPU)
SmoothImageCPU.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2024 Scott Grauer-Gray
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
28 #include "SmoothImageCPU.h"
29 
30 //function to use the CPU-image filter to apply a guassian filter to the a single images
31 //input images have each pixel stored as an unsigned in (value between 0 and 255 assuming 8-bit grayscale image used)
32 //output filtered images have each pixel stored as a float after the image has been smoothed with a Gaussian filter of sigma
33 void SmoothImageCPU::operator()(const BpImage<unsigned int>& in_image, float sigma, float* smoothed_image) const
34 {
35  //if sigma < kMinSigmaValSmooth, then don't smooth image...just convert the input image
36  //of unsigned ints to an output image of float values
37  if (sigma < kMinSigmaValSmooth) {
38  //call kernel to convert input unsigned int pixels to output float pixels on the device
39  ConvertUnsignedIntImageToFloatCPU(in_image.PointerToPixelsStart(), smoothed_image,
40  in_image.Width(), in_image.Height(), this->parallel_params_);
41  }
42  //otherwise apply a Guassian filter to the images
43  else
44  {
45  //retrieve output filter (float array in unique_ptr) and size
46  const auto filter = this->MakeFilter(sigma);
47 
48  //space for intermediate image (when the image has been filtered horizontally but not vertically)
49  std::unique_ptr<float[]> intermediateImage = std::make_unique<float[]>(in_image.Width() * in_image.Height());
50 
51  //first filter the image horizontally, then vertically; the result is applying a 2D gaussian filter with the given sigma value to the image
52  FilterImageAcrossCPU<unsigned int>(in_image.PointerToPixelsStart(), intermediateImage.get(), in_image.Width(),
53  in_image.Height(), filter.data(), filter.size(), this->parallel_params_);
54 
55  //now use the vertical filter to complete the smoothing of image 1 on the device
56  FilterImageVerticalCPU<float>(intermediateImage.get(), smoothed_image,
57  in_image.Width(), in_image.Height(), filter.data(), filter.size(), this->parallel_params_);
58  }
59 }
60 
61 //convert the unsigned int pixels to float pixels in an image when
62 //smoothing is not desired but the pixels need to be converted to floats
63 //the input image is stored as unsigned ints in the texture uint_image_pixels
64 //output filtered image stored in float_image_pixels
65 void SmoothImageCPU::ConvertUnsignedIntImageToFloatCPU(
66  const unsigned int* uint_image_pixels, float* float_image_pixels,
67  unsigned int width_images, unsigned int height_images,
68  const ParallelParams& opt_cpu_params) const
69 {
70 #if defined(SET_THREAD_COUNT_INDIVIDUAL_KERNELS_CPU)
71  int num_threads_kernel{
72  (int)opt_cpu_params.OptParamsForKernel({static_cast<unsigned int>(beliefprop::BpKernel::kBlurImages), 0})[0]};
73  #pragma omp parallel for num_threads(num_threads_kernel)
74 #else
75  #pragma omp parallel for
76 #endif
77 #ifdef _WIN32
78  for (int val = 0; val < width_images * height_images; val++) {
79 #else
80  for (unsigned int val = 0; val < width_images * height_images; val++) {
81 #endif //_WIN32
82  const unsigned int y_val = val / width_images;
83  const unsigned int x_val = val % width_images;
84  float_image_pixels[y_val * width_images + x_val] = 1.0f * uint_image_pixels[y_val * width_images + x_val];
85  }
86 }
87 
88 
89 //apply a horizontal filter on each pixel of the image in parallel
90 template<BpImData_t U>
91 void SmoothImageCPU::FilterImageAcrossCPU(
92  const U* image_to_filter, float* filtered_image,
93  unsigned int width_images, unsigned int height_images,
94  const float* image_filter, unsigned int size_filter,
95  const ParallelParams& opt_cpu_params) const
96 {
97 #if defined(SET_THREAD_COUNT_INDIVIDUAL_KERNELS_CPU)
98  int num_threads_kernel{
99  (int)opt_cpu_params.OptParamsForKernel(
100  {static_cast<unsigned int>(beliefprop::BpKernel::kBlurImages), 0})[0]};
101  #pragma omp parallel for num_threads(num_threads_kernel)
102 #else
103  #pragma omp parallel for
104 #endif
105 #ifdef _WIN32
106  for (int val = 0; val < width_images * height_images; val++) {
107 #else
108  for (unsigned int val = 0; val < width_images * height_images; val++) {
109 #endif //_WIN32
110  const unsigned int y_val = val / width_images;
111  const unsigned int x_val = val % width_images;
112  beliefprop::FilterImageAcrossProcessPixel<U>(
113  x_val, y_val, image_to_filter, filtered_image,
114  width_images, height_images, image_filter, size_filter);
115  }
116 }
117 
118 //apply a vertical filter on each pixel of the image in parallel
119 template<BpImData_t U>
120 void SmoothImageCPU::FilterImageVerticalCPU(
121  const U* image_to_filter, float* filtered_image,
122  unsigned int width_images, unsigned int height_images,
123  const float* image_filter, unsigned int size_filter,
124  const ParallelParams& opt_cpu_params) const
125 {
126 #if defined(SET_THREAD_COUNT_INDIVIDUAL_KERNELS_CPU)
127  int num_threads_kernel{
128  (int)opt_cpu_params.OptParamsForKernel({static_cast<unsigned int>(beliefprop::BpKernel::kBlurImages), 0})[0]};
129  #pragma omp parallel for num_threads(num_threads_kernel)
130 #else
131  #pragma omp parallel for
132 #endif
133 #ifdef _WIN32
134  for (int val = 0; val < width_images * height_images; val++) {
135 #else
136  for (unsigned int val = 0; val < width_images * height_images; val++) {
137 #endif //_WIN32
138  const unsigned int y_val = val / width_images;
139  const unsigned int x_val = val % width_images;
140  beliefprop::FilterImageVerticalProcessPixel<U>(
141  x_val, y_val, image_to_filter, filtered_image,
142  width_images, height_images, image_filter, size_filter);
143  }
144 }
145 
146 //explicit instantiations of template member functions
147 //which take float or unsigned int as templated type
148 //TODO: seems to compile without explicit instantiations,
149 //so not clear if needed or not
150 //explicit instantiations for FilterImageAcrossCPU member
151 //function
152 template void SmoothImageCPU::FilterImageAcrossCPU<float>(
153  const float* image_to_filter, float* filtered_image,
154  unsigned int width_images, unsigned int height_images,
155  const float* image_filter, unsigned int size_filter,
156  const ParallelParams& opt_cpu_params) const;
157 template void SmoothImageCPU::FilterImageAcrossCPU<unsigned int>(
158  const unsigned int* image_to_filter, float* filtered_image,
159  unsigned int width_images, unsigned int height_images,
160  const float* image_filter, unsigned int size_filter,
161  const ParallelParams& opt_cpu_params) const;
162 
163 //explicit instantiations for FilterImageVerticalCPU member
164 //function
165 template void SmoothImageCPU::FilterImageVerticalCPU<float>(
166  const float* image_to_filter, float* filtered_image,
167  unsigned int width_images, unsigned int height_images,
168  const float* image_filter, unsigned int size_filter,
169  const ParallelParams& opt_cpu_params) const;
170 template void SmoothImageCPU::FilterImageVerticalCPU<unsigned int>(
171  const unsigned int* image_to_filter, float* filtered_image,
172  unsigned int width_images, unsigned int height_images,
173  const float* image_filter, unsigned int size_filter,
174  const ParallelParams& opt_cpu_params) const;
Functions for smoothing input images that are used in both optimized CPU and CUDA implementations.
constexpr float kMinSigmaValSmooth
Definition: SmoothImage.h:39
Declares child class of SmoothImage for smoothing images in the optimized CPU implementation.
Class to define images that are used in bp processing.
Definition: BpImage.h:56
unsigned int Height() const
Definition: BpImage.h:106
unsigned int Width() const
Definition: BpImage.h:105
T * PointerToPixelsStart() const
Definition: BpImage.h:85
Abstract class for holding and processing parallelization parameters. Child class(es) specific to im...
virtual std::array< unsigned int, 2 > OptParamsForKernel(const std::array< unsigned int, 2 > &kernel_location) const =0
Get optimized parallel parameters for parallel processing kernel for kernel that is indexed as an arr...
void operator()(const BpImage< unsigned int > &in_image, const float sigma, float *smoothed_image) const override
Function to use the image filter to apply a guassian filter to the a single image....
std::vector< float > MakeFilter(float sigma) const
Create a Gaussian filter from a sigma value.
Definition: SmoothImage.cpp:30