SaigeVision C/C++ 1.5.0
SaigeVision API document for C/C++
 
Loading...
Searching...
No Matches
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>
15namespace fs = std::experimental::filesystem;
16#elif ((defined(_MSC_VER) && _MSC_VER > 1916) || __cplusplus >= 201703L)
17#include <filesystem>
18namespace fs = std::filesystem;
19#endif
20
22typedef 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
36static 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
74static 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 {
129 ConvertImageToDepthOfCV8U(image);
130 }
131
132 return true;
133}
134
138static 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
273static 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
334static 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}
eSRInputImageType
Data Type of input Image for example projects.
Definition: SRUtils.h:23
Struct describing features of a segmentation object.
Definition: CommonHeaderDLL.h:122