25 #define DEFAULT_FPS 30
36 #include <opencv2/core/core.hpp>
37 #include <opencv2/highgui/highgui.hpp>
38 #include <opencv2/imgproc/imgproc.hpp>
44 #include <SimoxUtility/algorithm/string/string_tools.h>
49 this->playingBack =
false;
50 this->currentFrame = 0;
57 this->playingBack =
false;
58 this->currentFrame = 0;
60 this->startPlayback(filePath);
73 return this->playingBack;
80 ARMARX_WARNING <<
"FPS cannot be reconstructed from a bare image sequence. Using a pre-set default of " <<
DEFAULT_FPS <<
" FPS instead";
89 return this->frameCount;
96 return this->frameHeight;
103 return this->frameWidth;
110 this->currentFrame = frame;
117 return this->currentFrame;
124 return this->currentFrame < this->frameCount;
131 this->initBasePathPrefixSuffix(filePath);
132 this->initFramePaths();
133 this->initFrameDimensions();
135 this->frameCount =
static_cast<unsigned int>(this->framePaths.size());
137 this->playingBack =
true;
145 if (this->currentFrame >= this->frameCount)
152 if (!this->getNextFrame(frame))
158 cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
159 std::memcpy(buffer, frame.data, this->frameHeight * this->frameWidth *
static_cast<unsigned int>(frame.channels()));
169 return this->getNextFrame(buffer.pixels);
176 buffer = cv::imread(this->framePaths[this->currentFrame++].
string());
179 if (buffer.data ==
nullptr)
185 if (
static_cast<unsigned int>(buffer.size().height) != this->frameHeight
186 or
static_cast<unsigned int>(buffer.size().width) != this->frameWidth)
198 this->playingBack =
false;
203 visionx::imrec::strats::ImageSequencePlaybackStrategy::initBasePathPrefixSuffix(
const std::filesystem::path& filePath)
206 auto findCommonPrefix = [](
const std::string & s1,
const std::string & s2) -> std::string
208 std::string commonPrefix =
"";
210 for (
unsigned int i = 0; i < s1.length() and i < s2.length(); ++i)
214 commonPrefix += s1[i];
224 auto findCommonSuffix = [](
const std::string & s1,
const std::string & s2) -> std::string
226 std::string commonSuffix =
"";
228 for (
unsigned int i = 1; i <= s1.length() and i <= s2.length(); ++i)
230 if (s1[s1.length() - i] == s2[s2.length() - i])
232 commonSuffix = s1[s1.length() - i] + commonSuffix;
244 std::filesystem::path basePath;
245 std::string requiredPrefix =
"";
246 std::string requiredSuffix =
"";
249 if (std::filesystem::is_directory(filePath))
252 basePath = std::filesystem::canonical(filePath);
255 std::string prefixCandidate =
"";
256 std::string suffixCandidate =
"";
257 bool candidatesInitialised =
false;
260 for (
auto de = std::filesystem::directory_iterator(basePath); de != std::filesystem::directory_iterator{}; ++de)
262 const std::string currentFile = de->path().filename().string();
266 if (!candidatesInitialised)
268 prefixCandidate = currentFile;
269 suffixCandidate = currentFile;
270 candidatesInitialised =
true;
274 prefixCandidate = findCommonPrefix(prefixCandidate, currentFile);
275 suffixCandidate = findCommonSuffix(suffixCandidate, currentFile);
280 requiredPrefix = prefixCandidate;
281 requiredSuffix = suffixCandidate;
287 basePath = std::filesystem::canonical(filePath.parent_path());
290 std::string
filename = filePath.filename().string();
291 const unsigned int wildcardCount =
static_cast<unsigned int>(std::count(
filename.begin(),
filename.end(),
'*'));
297 if (wildcardCount == 1)
306 std::string prefixCandidate =
filename;
307 std::string suffixCandidate =
filename;
310 for (
auto de = std::filesystem::directory_iterator(basePath); de != std::filesystem::directory_iterator{}; ++de)
312 const std::string currentFile = de->path().filename().string();
313 prefixCandidate = findCommonPrefix(prefixCandidate, currentFile);
314 suffixCandidate = findCommonSuffix(suffixCandidate, currentFile);
318 requiredPrefix = prefixCandidate;
319 requiredSuffix = suffixCandidate;
323 this->basePath = basePath;
324 this->requiredPrefix = requiredPrefix;
325 this->requiredSuffix = requiredSuffix;
330 visionx::imrec::strats::ImageSequencePlaybackStrategy::initFramePaths()
333 unsigned long prefixLength = requiredPrefix.length();
334 unsigned long suffixLength = requiredSuffix.length();
335 auto naturalSortComparator = [prefixLength, suffixLength](
const std::filesystem::path &
a,
const std::filesystem::path & b) ->
bool
337 std::string as =
a.filename().string();
338 std::string bs = b.filename().string();
339 unsigned long normalisation = 2;
340 as = as.substr(prefixLength, as.length() - (suffixLength + normalisation));
341 bs = bs.substr(prefixLength, bs.length() - (suffixLength + normalisation));
344 if (as.length() == bs.length())
350 while (as.length() > 0 and bs.length() > 0)
352 unsigned int asi = 0;
353 unsigned int bsi = 0;
354 std::stringstream(as) >> asi;
355 std::stringstream(bs) >> bsi;
358 if (as[0] == bs[0] and asi == bsi)
360 unsigned int decimals = 1;
367 as = as.substr(decimals, as.length());
368 bs = bs.substr(decimals, bs.length());
371 else if ((asi > 0 or (asi == 0 and as[0] ==
'0')) and (bsi > 0 or (bsi == 0 and bs[0] ==
'0')))
378 return as[0] < bs[0];
382 return as.length() < bs.length();
386 for (
auto de = std::filesystem::directory_iterator(basePath); de != std::filesystem::directory_iterator{}; ++de)
388 const std::string currentFile = de->path().filename().string();
393 this->framePaths.push_back(de->path());
398 std::sort(this->framePaths.begin(), this->framePaths.end(), naturalSortComparator);
403 visionx::imrec::strats::ImageSequencePlaybackStrategy::initFrameDimensions()
405 const std::filesystem::path probe = this->framePaths.at(0);
406 cv::Mat frameImage = cv::imread(probe.string());
410 this->frameHeight =
static_cast<unsigned int>(frameImage.size().height);
411 this->frameWidth =
static_cast<unsigned int>(frameImage.size().width);