SaigeVision C/C++  1.4.7
SaigeVision API document for C/C++
SRUtils.h
Go to the documentation of this file.
1 
4 #pragma once
5 
6 #include <fstream>
7 #include <string>
8 
9 #include "opencv2/opencv.hpp"
10 
11 #if (defined(_MSC_VER) && _MSC_VER < 1900)
12 // filesystem may not exist..
13 #elif (defined(_MSC_VER) && _MSC_VER <= 1916)
14 #include <filesystem>
15 namespace fs = std::experimental::filesystem;
16 #elif ((defined(_MSC_VER) && _MSC_VER > 1916) || __cplusplus >= 201703L)
17 #include <filesystem>
18 namespace fs = std::filesystem;
19 #endif
20 
22 typedef enum
23 {
24  ImageFilePathMultiByteChar, // multibyte char path of image file
25  ImageFilePathWideChar, // wide char path of image file
26  UCGrayImage, // 8bit 1-channel image
27  UCColorImage, // 8bit 3-channels image
28  UIColorImage, // 8bit 4-channels image
29  UCGrayImage16Bit, // 16bit 1-channel image
30  UCColorImage16Bit, // 16bit 3-channels image
31  UIColorImage16Bit, // 16bit 4-channels image
32  UC8bitImage, // 8bit 1~4 channels image (for multi page mode)
34 
36 void ConvertImageToDepthOfCV8U(cv::Mat& image)
37 {
38  int depth = image.depth();
39 
40  double max = 0.;
41  double min = 0.;
42  switch (depth) {
43  case CV_8U:
44  return;
45  case CV_16U:
46  max = 65535.; // 256^2 - 1
47  min = 0;
48  break;
49  case CV_32F:
50  case CV_64F:
51  case CV_16F:
52  max = 1.;
53  min = 0.;
54  break;
55  case CV_8S:
56  max = 127.;
57  min = -128.;
58  break;
59  case CV_16S:
60  max = 32767.; // (256^2)/2 - 1
61  min = -32768.; // (256^2)/2
62  break;
63  case CV_32S:
64  max = 2147483647.; // (256^4)/2 - 1
65  min = -2147483648.; // (256^4)/2
66  break;
67  default:
68  assert(false && "saige: unsupported image depth");
69  }
70  if(min != max) image.convertTo(image, CV_8U, 255.0 / (max - min), -255.0 * min / (max - min));
71 }
72 
74 bool OpenImageFile(const std::wstring imagePath, cv::Mat& image, bool asCV8U = false)
75 {
76  const wchar_t* imageFilePath = imagePath.c_str();
77 
78  size_t sizeOfChar = 0;
79 
80  size_t sizeOfWChar = wcslen(imageFilePath);
81  size_t bufferSize = sizeOfWChar * 2;
82 
83  std::vector<char> imageFilePathMB(bufferSize);
84 
85  sizeOfChar = wcstombs(
86  imageFilePathMB.data(),
87  imageFilePath,
88  bufferSize);
89 
90  std::string ext;
91  int isSuccess = 1;
92 
93  if (sizeOfChar != sizeOfWChar)
94  {
95 #if ((defined(_MSC_VER) && _MSC_VER >= 1900) || __cplusplus >= 201402L)
96  std::ifstream ifs(fs::path(imageFilePath), std::ios::in | std::ios::ate | std::ios::binary);
97  if (ifs.is_open())
98  {
99  size_t size = ifs.tellg();
100 
101  ifs.seekg(0, std::ios::beg);
102  std::vector<uchar> buffer(size);
103  ifs.read(reinterpret_cast<char*>(&buffer[0]), size);
104  ifs.close();
105 
106  image = cv::imdecode(buffer, cv::IMREAD_UNCHANGED);
107  }
108  else
109  {
110  return false;
111  }
112 #else
113  // use filename which can be converted to multi byte characters without any loss..
114  return false;
115 #endif
116  }
117  else
118  {
119  image = cv::imread(imageFilePathMB.data(), cv::IMREAD_UNCHANGED);
120  }
121 
122  if (image.empty() == true)
123  {
124  return false;
125  }
126 
127  if (asCV8U)
128  {
130  }
131 
132  return true;
133 }
134 
138 void* GetImageDataByInputImageType(const std::wstring imagePath, const eSRInputImageType inputType, int& height, int& width, int* channel = nullptr)
139 {
140  if (inputType == eSRInputImageType::ImageFilePathMultiByteChar || inputType == eSRInputImageType::ImageFilePathWideChar)
141  {
142  return nullptr;
143  }
144 
145  cv::Mat image;
146 
147  bool isOpened = OpenImageFile(imagePath, image);
148 
149  if ((image.empty() == true) || (isOpened == false))
150  {
151  std::wcout << "GetImageDataByInputImageType: wrong file path or damaged file.." << imagePath << std::endl;
152  return nullptr;
153  }
154 
155  width = image.size().width;
156  height = image.size().height;
157  int c = image.channels();
158 
159  unsigned char* ucData = nullptr;
160 
161  bool bIsColor = false;
162 
163  // copy image data to ucData
164  switch (inputType)
165  {
166  case eSRInputImageType::ImageFilePathMultiByteChar:
167  case eSRInputImageType::ImageFilePathWideChar:
168  break;
169  case eSRInputImageType::UCGrayImage:
170  ucData = new unsigned char[width * height * 1];
171  if (c == 3)
172  {
173  cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
174  }
175  else if (c == 4)
176  {
177  cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY);
178  }
179  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * 1);
180  break;
181  case eSRInputImageType::UCColorImage:
182  ucData = new unsigned char[width * height * 3];
183  if (c == 4)
184  {
185  cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
186  }
187  bIsColor = (c == 1) ? 0 : 1;
188 
189  if (bIsColor)
190  {
191  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * 3);
192  }
193  else
194  {
195  for (int i = 0; i < width * height; i++)
196  {
197  ucData[3 * i + 0] = image.data[c * i + 0 * bIsColor];
198  ucData[3 * i + 1] = image.data[c * i + 1 * bIsColor];
199  ucData[3 * i + 2] = image.data[c * i + 2 * bIsColor];
200  }
201  }
202  break;
203  case eSRInputImageType::UIColorImage:
204  bIsColor = (c == 1) ? 0 : 1;
205  ucData = new unsigned char[width * height * 4];
206  for (int i = 0; i < width * height; i++)
207  {
208  ucData[4 * i + 0] = image.data[c * i + 0 * bIsColor];
209  ucData[4 * i + 1] = image.data[c * i + 1 * bIsColor];
210  ucData[4 * i + 2] = image.data[c * i + 2 * bIsColor];
211  if (c == 4)
212  {
213  ucData[4 * i + 3] = image.data[c * i + 3 * bIsColor];
214  }
215  else
216  {
217  ucData[4 * i + 3] = 255;
218  }
219  }
220  break;
221  case eSRInputImageType::UCGrayImage16Bit:
222  ucData = new unsigned char[width * height * 1 * 2]; // channels = 1, element size = 2
223  if (c == 3)
224  {
225  cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
226  }
227  else if (c == 4)
228  {
229  cv::cvtColor(image, image, cv::COLOR_BGRA2GRAY);
230  }
231  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * 1 * 2);
232  break;
233  case eSRInputImageType::UCColorImage16Bit:
234  ucData = new unsigned char[width * height * 3 * 2]; // channels = 3, element size = 2
235  if (c == 1)
236  {
237  cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
238  }
239  else if (c == 4)
240  {
241  cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
242  }
243  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * 3 * 2);
244  break;
245  case eSRInputImageType::UIColorImage16Bit:
246  ucData = new unsigned char[width * height * 4 * 2]; // channels = 4, element size = 2
247  if (c == 1)
248  {
249  cv::cvtColor(image, image, cv::COLOR_GRAY2BGRA);
250  }
251  else if (c == 3)
252  {
253  cv::cvtColor(image, image, cv::COLOR_BGR2BGRA);
254  }
255  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * 4 * 2);
256  break;
257  case eSRInputImageType::UC8bitImage:
258  ucData = new unsigned char[width * height * image.channels()];
259  memcpy(ucData, image.data, sizeof(unsigned char) * width * height * image.channels());
260  break;
261  default:
262  break;
263  }
264 
265  if (channel != nullptr) {
266  *channel = image.channels();
267  }
268 
269  return (void*)ucData;
270 }
271 
273 void DisplayFailedImageOnCVWindow(std::wstring& imagePath, std::string failPhrase, std::string windowName, int displayTime, const float resizeFactor)
274 {
275  cv::Mat failImage = cv::Mat();
276 
277  bool isOpened = OpenImageFile(imagePath, failImage);
278 
279  if ((failImage.empty() == true) || (isOpened == false))
280  {
281  return;
282  }
283 
284  if (failImage.channels() == 1)
285  {
286  cv::cvtColor(failImage, failImage, cv::COLOR_GRAY2BGR);
287  }
288  else if (failImage.channels() == 4)
289  {
290  cv::cvtColor(failImage, failImage, cv::COLOR_BGRA2BGR);
291  }
292 
293  cv::putText(failImage, failPhrase,
294  cv::Point(0, 0), // Coordinates
295  cv::FONT_HERSHEY_COMPLEX_SMALL, // Font
296  2.0, // Scale. 2.0 = 2x bigger
297  cv::Scalar(0, 0, 255), // BGR Color
298  8 // Line Thickness (Optional)
299  );
300 
301  cv::putText(failImage, failPhrase,
302  cv::Point(int(failImage.size().width * 0.25), int(failImage.size().height * 0.25)), // Coordinates
303  cv::FONT_HERSHEY_COMPLEX_SMALL, // Font
304  2.0, // Scale. 2.0 = 2x bigger
305  cv::Scalar(0, 0, 255), // BGR Color
306  8 // Line Thickness (Optional)
307  );
308 
309  cv::putText(failImage, failPhrase,
310  cv::Point(int(failImage.size().width * 0.5), int(failImage.size().height * 0.5)), // Coordinates
311  cv::FONT_HERSHEY_COMPLEX_SMALL, // Font
312  2.0, // Scale. 2.0 = 2x bigger
313  cv::Scalar(0, 0, 255), // BGR Color
314  8 // Line Thickness (Optional)
315  );
316 
317  cv::putText(failImage, failPhrase,
318  cv::Point(int(failImage.size().width * 0.75), int(failImage.size().height * 0.75)), // Coordinates
319  cv::FONT_HERSHEY_COMPLEX_SMALL, // Font
320  2.0, // Scale. 2.0 = 2x bigger
321  cv::Scalar(0, 0, 255), // BGR Color
322  8 // Line Thickness (Optional)
323  );
324 
325  cv::namedWindow(windowName, cv::WINDOW_NORMAL);
326  cv::resizeWindow(windowName, failImage.size().width * resizeFactor, failImage.size().height * resizeFactor);
327  cv::imshow(windowName, failImage);
328  cv::waitKey(displayTime);
329 
330  return;
331 }
332 
334 void convertSRSegmentedObjectToOpencvFormat(const SR_SegmentedObject& object, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchies)
335 {
336  contours.clear();
337  contours.resize(object.nContours);
338 
339  hierarchies.clear();
340  hierarchies.resize(object.nContours);
341 
342  int pointsIdx = 0;
343  for (size_t i_c = 0; i_c < contours.size(); i_c++)
344  {
345  for (size_t i_p = 0; i_p < object.nPointsOnContour[i_c]; i_p++)
346  {
347  cv::Point point = cv::Point(object.pointsOnContour[pointsIdx], object.pointsOnContour[pointsIdx + 1]);
348  contours[i_c].push_back(point);
349 
350  pointsIdx += 2;
351  }
352 
353  hierarchies[i_c][0] = object.hierarchies[4 * i_c + 0];
354  hierarchies[i_c][1] = object.hierarchies[4 * i_c + 1];
355  hierarchies[i_c][2] = object.hierarchies[4 * i_c + 2];
356  hierarchies[i_c][3] = object.hierarchies[4 * i_c + 3];
357  }
358 }
ConvertImageToDepthOfCV8U
void ConvertImageToDepthOfCV8U(cv::Mat &image)
Convert image to CV_8U depth type.
Definition: SRUtils.h:36
SR_SegmentedObject
Struct describing features of a segmentation object.
Definition: CommonHeaderDLL.h:108
GetImageDataByInputImageType
void * GetImageDataByInputImageType(const std::wstring imagePath, const eSRInputImageType inputType, int &height, int &width, int *channel=nullptr)
Get image data from a file path and image size by an allocated pointer for example projects.
Definition: SRUtils.h:138
eSRInputImageType
eSRInputImageType
Data Type of input Image for example projects.
Definition: SRUtils.h:23
convertSRSegmentedObjectToOpencvFormat
void convertSRSegmentedObjectToOpencvFormat(const SR_SegmentedObject &object, std::vector< std::vector< cv::Point >> &contours, std::vector< cv::Vec4i > &hierarchies)
convert SR_SegmentedObject to opencv contours and hierarchies for example projects.
Definition: SRUtils.h:334
DisplayFailedImageOnCVWindow
void DisplayFailedImageOnCVWindow(std::wstring &imagePath, std::string failPhrase, std::string windowName, int displayTime, const float resizeFactor)
Display failed image on opencv window for example projects.
Definition: SRUtils.h:273
OpenImageFile
bool OpenImageFile(const std::wstring imagePath, cv::Mat &image, bool asCV8U=false)
Open image file for example projects.
Definition: SRUtils.h:74