Optimized Belief Propagation (CPU and GPU)
BpImage.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 
27 #include "BpImage.h"
28 
29 template<class T>
30 requires std::is_arithmetic_v<T>
31 void BpImage<T>::LoadImageAsGrayScale(const std::string& file_path_image)
32 {
33  //check if PGM or PPM image (types currently supported)
34  std::istringstream iss(file_path_image);
35  std::string token;
36  while (std::getline(iss, token, '.')) {
37  //continue to get last token with the file extension
38  }
39 
40  //last token after "." is file extension
41  //use extension to check if image is pgm or ppm
42  BpImage<unsigned char> init_image;
43  if (token == beliefprop::kPGMExt) {
44  init_image = ImageRead(file_path_image, beliefprop::ImageType::kPgmImage);
45  } else if (token == beliefprop::kPPMExt) {
46  init_image = ImageRead(
47  file_path_image,
50  } else {
51  //end function if not of type pgm or ppm with result
52  //being BpImage with default constructor
53  return;
54  }
55 
56  //set width and height using data from file image and initialize
57  //pixels array of size width_ * height_ with unique pointer
58  width_height_ = {init_image.Width(), init_image.Height()};
59  pixels_ = std::make_unique<T[]>(TotalPixels());
60 
61  //convert each pixel in dataRead to data type T and place in imageData array
62  //in same location
63  std::ranges::transform(
64  init_image.PointerToPixelsStart(),
65  init_image.PointerToPixelsStart() + TotalPixels(),
66  pixels_.get(),
67  [](const unsigned char i) -> T {return (T)i;});
68 }
69 
70 template<class T>
71 requires std::is_arithmetic_v<T>
72 void BpImage<T>::pnm_read(std::ifstream &file, std::string& buf) const
73 {
74  std::string doc;
75  char c;
76 
77  file >> c;
78  while (c == '#') {
79  std::getline(file, doc);
80  file >> c;
81  }
82  file.putback(c);
83 
84  file >> buf;
85  file.ignore();
86 }
87 
88 template<class T>
89 requires std::is_arithmetic_v<T>
91  const std::string& file_name,
92  beliefprop::ImageType image_type,
93  bool weighted_rgb_conversion) const
94 {
95  std::string buf;
96 
97  /* read header */
98  std::ifstream file(file_name, std::ios::in | std::ios::binary);
99  pnm_read(file, buf);
100  if (buf != "P5")
101  std::cout << "ERROR READING FILE P5: " << file_name << std::endl;
102 
103  unsigned int cols, rows;
104  pnm_read(file, buf);
105  cols = std::stoul(buf);
106  pnm_read(file, buf);
107  rows = std::stoul(buf);
108 
109  pnm_read(file, buf);
110  if (std::stoul(buf) > UCHAR_MAX)
111  std::cout << "ERROR READING FILE UCHAR MAX: " << file_name << std::endl;
112 
113  BpImage<unsigned char> out_image(std::array<unsigned int, 2>{cols, rows});
114 
115  if (image_type == beliefprop::ImageType::kPgmImage) {
116  /* read data */
117  file.read((char*) (out_image.PointerToPixelsStart()),
118  (cols * rows * sizeof(char)));
119  }
120  else if (image_type == beliefprop::ImageType::kPpmImage) {
121  std::unique_ptr<char[]> rgb_image_ptr =
122  std::make_unique<char[]>(3 * cols * rows);
123 
124  /* read data */
125  file.read(rgb_image_ptr.get(), 3 * cols * rows * sizeof(char));
126  file.close();
127 
128  //convert the RGB image to grayscale either
129  //with each channel weighted the same or weighted
130  //if weighted_rgb_conversion set to true
131  for (unsigned int i = 0; i < (rows * cols); i++) {
132  float r_channel_weight = 1.0f / 3.0f;
133  float b_channel_weight = 1.0f / 3.0f;
134  float g_channel_weight = 1.0f / 3.0f;
135  if (weighted_rgb_conversion) {
136  r_channel_weight = 0.299f;
137  b_channel_weight = 0.587f;
138  g_channel_weight = 0.114f;
139  }
140  out_image.PointerToPixelsStart()[i] =
141  (unsigned char)std::floor(
142  r_channel_weight * ((float) rgb_image_ptr[i * 3]) +
143  g_channel_weight * ((float) rgb_image_ptr[i * 3 + 1]) +
144  b_channel_weight * ((float) rgb_image_ptr[i * 3 + 2]) +
145  0.5f);
146  }
147  }
148 
149  file.close();
150  return out_image;
151 }
152 
153 //each type that may be used instantiated here
154 template class BpImage<unsigned int>;
155 template class BpImage<float>;
156 template class BpImage<unsigned char>;
157 template class BpImage<char>;
158 
Declares class to define images that are used in bp processing.
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
void LoadImageAsGrayScale(const std::string &file_path_image)
Definition: BpImage.cpp:31
void pnm_read(std::ifstream &file, std::string &buf) const
Definition: BpImage.cpp:72
T * PointerToPixelsStart() const
Definition: BpImage.h:85
BpImage< unsigned char > ImageRead(const std::string &file_name, beliefprop::ImageType image_type, bool weighted_rgb_conversion=true) const
Definition: BpImage.cpp:90
constexpr std::string_view kPGMExt
Definition: BpImage.h:45
constexpr bool kUseWeightedRGBToGrayscaleConversion
Definition: BpImage.h:44
constexpr std::string_view kPPMExt
Definition: BpImage.h:46