UsTK : Ultrasound ToolKit  version 2.0.1 under development (2024-12-03)
usSequenceReader.h
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ustk with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Authors:
29  * Marc Pouliquen
30  *
31  *****************************************************************************/
32 
40 #ifndef __usSequenceReader_h_
41 #define __usSequenceReader_h_
42 
43 #include <algorithm>
44 #include <cstring>
45 #include <iostream>
46 #include <vector>
47  //#include <unistd.h>
48 
49 #include <visp3/core/vpConfig.h>
50 
51 #ifdef VISP_HAVE_XML2
52 
53 #include <visp3/core/vpException.h>
54 #include <visp3/core/vpImage.h>
55 #include <visp3/io/vpImageIo.h>
56 
57 #include <visp3/ustk_core/usImageIo.h>
58 #include <visp3/ustk_core/usImageSettingsXmlParser.h>
59 
67 template <class ImageType> class usSequenceReader
68 {
69 private:
71  ImageType m_frame;
72 
74  double m_frameRate;
75 
77  long m_firstFrame;
78  bool m_firstFrameIsSet;
79 
81  long m_lastFrame;
82  bool m_lastFrameIsSet;
83 
86  long m_frameCount;
87 
90  std::string m_sequenceFileName;
91  std::string m_genericImageFileName;
92  bool m_fileNameIsSet;
93 
95  bool is_open;
96 
98  bool m_enableLoopCycling;
99  int loopIncrement; // -1 or +1 depending on witch side we acquire
100 
102  usImageSettingsXmlParser m_xmlParser;
103 
105  std::vector<uint64_t> m_timestamps;
106 
107 public:
109 
110  virtual ~usSequenceReader();
111 
112  // get images in grabber style
113  void acquire(ImageType &image);
114  void acquire(ImageType &image, uint64_t &timestamp);
115 
119  inline bool end()
120  {
121  if (!is_open) {
122  open(m_frame);
123  m_frameCount--;
124  }
125  //
126  if (m_enableLoopCycling) {
127  if (loopIncrement == 1) {
128  if (m_frameCount > m_lastFrame) {
129  m_frameCount -= 2;
130  loopIncrement = -1;
131  return false;
132  }
133  }
134  else if (loopIncrement == -1) {
135  if (m_frameCount < m_firstFrame) {
136  m_frameCount += 2;
137  loopIncrement = 1;
138  return false;
139  }
140  }
141  }
142  else if (m_frameCount > m_lastFrame || m_frameCount < m_firstFrame)
143  return true;
144  return false;
145  }
146 
147 // get image by its number in the sequence
148  void getFrame(ImageType &image, int index);
149 
150  // get image by its number in the sequence
151  ImageType &getFrame(int index);
152 
153  // total number of frames in the sequence
155 
156  // attributes getters/setters
157  double getFrameRate() const { return m_frameRate; }
158  long getImageNumber() const { return m_frameCount; }
159 
160  // timestamps vector getter
161  std::vector<uint64_t> getSequenceTimestamps() const { return m_timestamps; }
162 
163  // get the xml parser : usefull to acess all the image settings contained in it
165 
166  void open(ImageType &image, uint64_t &timestamp);
167  void open(ImageType &image);
168 
169  void setFirstFrameIndex(long firstIndex);
170  void setLastFrameIndex(long lastIndex);
171  void setLoopCycling(bool activateLoopCycling);
172  void setSequenceFileName(const std::string &sequenceFileName);
173 };
174 
175 /****************************************************************************
176 * Template implementations.
177 ****************************************************************************/
178 
182 template <class ImageType>
184  : m_frame(), m_frameRate(0.0), m_firstFrame(0), m_firstFrameIsSet(false), m_lastFrame(0), m_lastFrameIsSet(false),
185  m_frameCount(0), m_sequenceFileName(""), m_genericImageFileName(""), m_fileNameIsSet(false), is_open(false),
186  m_enableLoopCycling(false), loopIncrement(1)
187 { }
188 
192 template <class ImageType> usSequenceReader<ImageType>::~usSequenceReader() { }
193 
198 template <class ImageType> void usSequenceReader<ImageType>::setSequenceFileName(const std::string &sequenceFileName)
199 {
200  m_sequenceFileName = sequenceFileName;
201  m_fileNameIsSet = true;
202 }
203 
208 template <class ImageType> void usSequenceReader<ImageType>::setFirstFrameIndex(long firstIndex)
209 {
210  m_firstFrame = firstIndex;
211  m_firstFrameIsSet = true;
212 }
213 
218 template <class ImageType> void usSequenceReader<ImageType>::setLastFrameIndex(long lastIndex)
219 {
220  m_lastFrame = lastIndex;
221  m_lastFrameIsSet = true;
222 }
223 
228 template <class ImageType> void usSequenceReader<ImageType>::open(ImageType &image)
229 {
230  (void)image;
231  throw(vpException(vpException::notImplementedError));
232 }
233 
239 template <class ImageType> void usSequenceReader<ImageType>::open(ImageType &image, uint64_t &timestamp)
240 {
241  (void)image;
242  (void)timestamp;
243  throw(vpException(vpException::notImplementedError));
244 }
245 
247 {
248  if (!m_fileNameIsSet) {
249  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
250  }
251 
252  m_xmlParser.parse(m_sequenceFileName);
253  if (m_xmlParser.getImageType() != us::PRESCAN_2D)
254  throw(vpException(vpException::badValue), "trying to open a non-usImagePreScan2D image !");
255 
256  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
257  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
258  m_frameRate = m_xmlParser.getSequenceFrameRate();
259  m_genericImageFileName = m_xmlParser.getImageFileName();
260 
261  // saving the settings for all the pre-scan sequence
262  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
263  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
264  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
265  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
266  m_frame.setAxialResolution(m_xmlParser.getAxialResolution());
267  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
268  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
269 
270  // Reading image
271  char buffer[FILENAME_MAX];
272  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_firstFrame);
273  std::string imageFileName;
274  // check timestamp
275  std::vector<std::string> splitName =
276  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
277 
278  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
279  if (!parentName.empty()) {
280  parentName = parentName + vpIoTools::path("/");
281  }
282  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
283  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
284  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
285  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
286  }
287  if (splitName.size() == 2) { // no timestamp : image0002.png for example
288  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
289  }
290  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
291  std::vector<std::string> dirFiles;
292 
293  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
294  dirFiles = vpIoTools::getDirFiles(parentName);
295 
296  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
297  2)) { // case of xml file in same directory
298  for (unsigned int i = 0; i < dirFiles.size(); i++) {
299  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
300  dirFiles.erase(dirFiles.begin() + i);
301  }
302  }
303  if (dirFiles.size() !=
304  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
305  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
306  "only the entire image sequence (no additionnal files allowed)"));
307 
308  // getting the all the timestamps of the sequence
309  unsigned int i = 0;
310  while (i < dirFiles.size()) {
311  uint64_t timestamp_temp;
312  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
313  m_timestamps.push_back(timestamp_temp);
314  i++;
315  }
316  imageFileName = parentName + dirFiles.front();
317  }
318  else { // path not correct
319  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
320  }
321  }
322 
323  vpImageIo::read(image, imageFileName);
324 
325  m_frame.setDepth((image.getHeight() - 1) * m_frame.getAxialResolution());
326 
327  // workaround to prevent the resize by setImagePreScanSettings (having a scanline number at 0 if not precised in the
328  // xml)
329  int scanlineNumber = image.getWidth();
330  image.setImagePreScanSettings(m_frame);
331  image.setScanLineNumber(scanlineNumber);
332 
333  m_frameCount = m_firstFrame + 1;
334  is_open = true;
335 }
336 
337 template <>
339  uint64_t &timestamp)
340 {
341  if (!m_fileNameIsSet) {
342  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
343  }
344 
345  m_xmlParser.parse(m_sequenceFileName);
346  if (m_xmlParser.getImageType() != us::PRESCAN_2D)
347  throw(vpException(vpException::badValue), "trying to open a non-usImagePreScan2D image !");
348 
349  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
350  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
351  m_frameRate = m_xmlParser.getSequenceFrameRate();
352  m_genericImageFileName = m_xmlParser.getImageFileName();
353 
354  // saving the settings for all the pre-scan sequence
355  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
356  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
357  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
358  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
359  m_frame.setAxialResolution(m_xmlParser.getAxialResolution());
360  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
361  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
362 
363  // Reading image
364  char buffer[FILENAME_MAX];
365  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_firstFrame);
366  std::string imageFileName;
367  // check timestamp
368  std::vector<std::string> splitName =
369  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
370 
371  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
372  if (!parentName.empty()) {
373  parentName = parentName + vpIoTools::path("/");
374  }
375  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
376  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
377  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
378  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
379  }
380  if (splitName.size() == 2) { // no timestamp : image0002.png for example
381  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
382  timestamp = 0;
383  m_timestamps.clear();
384  m_timestamps.push_back(timestamp);
385  }
386  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
387  std::vector<std::string> dirFiles;
388 
389  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
390  dirFiles = vpIoTools::getDirFiles(parentName);
391 
392  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
393  2)) { // case of xml file in same directory
394  for (unsigned int i = 0; i < dirFiles.size(); i++) {
395  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
396  dirFiles.erase(dirFiles.begin() + i);
397  }
398  }
399  if (dirFiles.size() !=
400  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
401  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
402  "only the entire image sequence (no additionnal files allowed)"));
403 
404  // getting the all the timestamps of the sequence
405  unsigned int i = 0;
406  while (i < dirFiles.size()) {
407  uint64_t timestamp_temp;
408  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
409  m_timestamps.push_back(timestamp_temp);
410  i++;
411  }
412  std::istringstream(vpIoTools::splitChain(dirFiles.at(0), std::string(".")).at(1)) >> timestamp;
413 
414  imageFileName = parentName + dirFiles.front();
415  }
416  else { // path not correct
417  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
418  }
419  }
420 
421  vpImageIo::read(image, imageFileName);
422 
423  m_frame.setDepth((image.getHeight() - 1) * m_frame.getAxialResolution());
424 
425  // workaround to prevent the resize by setImagePreScanSettings (having a scanline number at 0 if not precised in the
426  // xml)
427  int scanlineNumber = image.getWidth();
428  image.setImagePreScanSettings(m_frame);
429  image.setScanLineNumber(scanlineNumber);
430 
431  m_frameCount = m_firstFrame + 1;
432  is_open = true;
433 }
434 
435 template <>
437 {
438  if (!m_fileNameIsSet) {
439  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
440  }
441 
442  m_xmlParser.parse(m_sequenceFileName);
443  if (m_xmlParser.getImageType() != us::POSTSCAN_2D)
444  throw(vpException(vpException::badValue), "trying to open a non-usImagePostScan2D image !");
445 
446  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
447  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
448  m_frameRate = m_xmlParser.getSequenceFrameRate();
449  m_genericImageFileName = m_xmlParser.getImageFileName();
450 
451  // saving the settings for all the post scan sequence
452  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
453  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
454  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
455  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
456  m_frame.setWidthResolution(m_xmlParser.getWidthResolution());
457  m_frame.setHeightResolution(m_xmlParser.getHeightResolution());
458  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
459  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
460 
461  // Reading image
462  char buffer[FILENAME_MAX];
463  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_firstFrame);
464  std::string imageFileName;
465  // check timestamp
466  std::vector<std::string> splitName =
467  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
468 
469  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
470  if (!parentName.empty()) {
471  parentName = parentName + vpIoTools::path("/");
472  }
473  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
474  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
475  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
476  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
477  }
478  if (splitName.size() == 2) { // no timestamp : image0002.png for example
479  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
480  }
481  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
482  std::vector<std::string> dirFiles;
483 
484  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
485  dirFiles = vpIoTools::getDirFiles(parentName);
486 
487  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
488  2)) { // case of xml file in same directory
489  for (unsigned int i = 0; i < dirFiles.size(); i++) {
490  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
491  dirFiles.erase(dirFiles.begin() + i);
492  }
493  }
494 
495  if (dirFiles.size() !=
496  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
497  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
498  "only the entire image sequence (no additionnal files allowed)"));
499 
500  // getting the all the timestamps of the sequence
501  unsigned int i = 0;
502  while (i < dirFiles.size()) {
503  uint64_t timestamp_temp;
504  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
505  m_timestamps.push_back(timestamp_temp);
506  i++;
507  }
508 
509  imageFileName = parentName + dirFiles.front();
510  }
511  else { // path not correct
512  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
513  }
514  }
515 
516  vpImageIo::read(image, imageFileName);
517  m_frame.setDepth(image.getHeight() - 1 * m_frame.getHeightResolution());
518 
519  image.setTransducerRadius(m_frame.getTransducerRadius());
520  image.setScanLinePitch(m_frame.getScanLinePitch());
521  image.setScanLineNumber(m_frame.getScanLineNumber());
522  image.setTransducerConvexity(m_frame.isTransducerConvex());
523  image.setWidthResolution(m_frame.getWidthResolution());
524  image.setHeightResolution(m_frame.getHeightResolution());
525  image.setSamplingFrequency(m_frame.getSamplingFrequency());
526  image.setTransmitFrequency(m_frame.getTransmitFrequency());
527  image.setDepth(m_frame.getDepth());
528 
529  m_frameCount = m_firstFrame + 1;
530  is_open = true;
531 }
532 
533 template <>
535  uint64_t &timestamp)
536 {
537  if (!m_fileNameIsSet) {
538  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
539  }
540 
541  m_xmlParser.parse(m_sequenceFileName);
542  if (m_xmlParser.getImageType() != us::POSTSCAN_2D)
543  throw(vpException(vpException::badValue), "trying to open a non-usImagePostScan2D image !");
544 
545  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
546  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
547  m_frameRate = m_xmlParser.getSequenceFrameRate();
548  m_genericImageFileName = m_xmlParser.getImageFileName();
549 
550  // saving the settings for all the post scan sequence
551  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
552  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
553  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
554  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
555  m_frame.setWidthResolution(m_xmlParser.getWidthResolution());
556  m_frame.setHeightResolution(m_xmlParser.getHeightResolution());
557  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
558  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
559 
560  // Reading image
561  char buffer[FILENAME_MAX];
562  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_firstFrame);
563  std::string imageFileName;
564  // check timestamp
565  std::vector<std::string> splitName =
566  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
567 
568  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
569  if (!parentName.empty()) {
570  parentName = parentName + vpIoTools::path("/");
571  }
572  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
573  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
574  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
575  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
576  }
577  if (splitName.size() == 2) { // no timestamp : image0002.png for example
578  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
579  timestamp = 0;
580  }
581  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
582  std::istringstream(splitName.at(1)) >> timestamp;
583  std::vector<std::string> dirFiles;
584 
585  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
586  dirFiles = vpIoTools::getDirFiles(parentName);
587 
588  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
589  2)) { // case of xml file in same directory
590  for (unsigned int i = 0; i < dirFiles.size(); i++) {
591  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
592  dirFiles.erase(dirFiles.begin() + i);
593  }
594  }
595 
596  std::istringstream(vpIoTools::splitChain(dirFiles.at(0), std::string(".")).at(1)) >> timestamp;
597 
598  if (dirFiles.size() !=
599  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
600  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
601  "only the entire image sequence (no additionnal files allowed)"));
602 
603  // getting the all the timestamps of the sequence
604  unsigned int i = 0;
605  while (i < dirFiles.size()) {
606  uint64_t timestamp_temp;
607  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
608  m_timestamps.push_back(timestamp_temp);
609  i++;
610  }
611 
612  imageFileName = parentName + dirFiles.front();
613  }
614  else { // path not correct
615  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
616  }
617  }
618  vpImageIo::read(image, imageFileName);
619  m_frame.setDepth(image.getHeight() - 1 * m_frame.getHeightResolution());
620 
621  image.setTransducerRadius(m_frame.getTransducerRadius());
622  image.setScanLinePitch(m_frame.getScanLinePitch());
623  image.setScanLineNumber(m_frame.getScanLineNumber());
624  image.setTransducerConvexity(m_frame.isTransducerConvex());
625  image.setWidthResolution(m_frame.getWidthResolution());
626  image.setHeightResolution(m_frame.getHeightResolution());
627  image.setSamplingFrequency(m_frame.getSamplingFrequency());
628  image.setTransmitFrequency(m_frame.getTransmitFrequency());
629  image.setDepth(m_frame.getDepth());
630 
631  m_frameCount = m_firstFrame + 1;
632  is_open = true;
633 }
634 
639 template <class ImageType> void usSequenceReader<ImageType>::acquire(ImageType &image)
640 {
641  if (!is_open) {
642  this->open(image);
643  return;
644  }
645 
646 // Reading image
647  char buffer[FILENAME_MAX];
648  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
649  std::string imageFileName;
650  // check timestamp
651  std::vector<std::string> splitName =
652  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
653 
654  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
655  if (!parentName.empty()) {
656  parentName = parentName + vpIoTools::path("/");
657  }
658  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
659  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one containing the xml file
660  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
661  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
662  }
663  if (splitName.size() == 2) { // no timestamp : image0002.png for example
664  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
665  }
666  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
667  std::vector<std::string> dirFiles;
668 
669  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
670  dirFiles = vpIoTools::getDirFiles(parentName);
671 
672  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
673  2)) { // case of xml file in same directory
674  for (unsigned int i = 0; i < dirFiles.size(); i++) {
675  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
676  dirFiles.erase(dirFiles.begin() + i);
677  }
678  }
679 
680  if (dirFiles.size() !=
681  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
682  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
683  "only the entire image sequence (no additionnal files allowed)"));
684 
685  imageFileName = parentName + dirFiles.at(m_frameCount);
686  }
687  else { // path not correct
688  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
689  }
690  }
691  vpImageIo::read(image, imageFileName);
692  image.setTransducerSettings(m_frame);
693  image.setScanLineNumber(image.getWidth());
694  image.setDepth(m_frame.getDepth());
695 
696  m_frameCount += loopIncrement;
697 }
698 
704 template <class ImageType> void usSequenceReader<ImageType>::acquire(ImageType &image, uint64_t &timestamp)
705 {
706  if (!is_open) {
707  this->open(image, timestamp);
708  return;
709  }
710 // Reading image
711  char buffer[FILENAME_MAX];
712  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
713  std::string imageFileName;
714  // check timestamp
715  std::vector<std::string> splitName =
716  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
717 
718  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
719  if (!parentName.empty()) {
720  parentName = parentName + vpIoTools::path("/");
721  }
722  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
723  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
724  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
725  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
726  }
727  if (splitName.size() == 2) { // no timestamp : image0002.png for example
728  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
729  timestamp = 0;
730  }
731  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
732 
733  std::vector<std::string> dirFiles;
734 
735  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
736  dirFiles = vpIoTools::getDirFiles(parentName);
737 
738  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
739  2)) { // case of xml file in same directory
740  for (unsigned int i = 0; i < dirFiles.size(); i++) {
741  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
742  dirFiles.erase(dirFiles.begin() + i);
743  }
744  }
745 
746  std::istringstream(vpIoTools::splitChain(dirFiles.at(m_frameCount), std::string(".")).at(1)) >> timestamp;
747 
748  if (dirFiles.size() !=
749  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
750  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
751  "only the entire image sequence (no additionnal files allowed)"));
752 
753  imageFileName = parentName + dirFiles.at(m_frameCount);
754  }
755  else { // path not correct
756  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
757  }
758  }
759 
760  vpImageIo::read(image, imageFileName);
761  image.setTransducerSettings(m_frame);
762  image.setScanLineNumber(image.getWidth());
763  image.setDepth(m_frame.getDepth());
764 
765  m_frameCount += loopIncrement;
766 }
767 
772 template <>
774 {
775  if (!is_open) {
776  this->open(image);
777  return;
778  }
779 // Reading image
780  char buffer[FILENAME_MAX];
781  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
782  std::string imageFileName;
783  // check timestamp
784  std::vector<std::string> splitName =
785  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
786 
787  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
788  if (!parentName.empty()) {
789  parentName = parentName + vpIoTools::path("/");
790  }
791  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
792  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
793  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
794  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
795  }
796  if (splitName.size() == 2) { // no timestamp : image0002.png for example
797  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
798  }
799  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
800  std::vector<std::string> dirFiles;
801 
802  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
803  dirFiles = vpIoTools::getDirFiles(parentName);
804 
805  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
806  2)) { // case of xml file in same directory
807  for (unsigned int i = 0; i < dirFiles.size(); i++) {
808  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
809  dirFiles.erase(dirFiles.begin() + i);
810  }
811  }
812 
813  if (dirFiles.size() !=
814  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
815  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
816  "only the entire image sequence (no additionnal files allowed)"));
817 
818  imageFileName = parentName + dirFiles.at(m_frameCount);
819  }
820  else { // path not correct
821  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
822  }
823  }
824 
825  vpImageIo::read(image, imageFileName);
826  image.setTransducerSettings(m_frame);
827  image.setScanLineNumber(image.getWidth());
828  image.setDepth(m_frame.getDepth());
829  image.setAxialResolution(m_frame.getAxialResolution());
830  image.setSamplingFrequency(m_frame.getSamplingFrequency());
831  image.setTransmitFrequency(m_frame.getTransmitFrequency());
832 
833  m_frameCount += loopIncrement;
834 }
835 
841 template <>
843  uint64_t &timestamp)
844 {
845  if (!is_open) {
846  this->open(image, timestamp);
847  return;
848  }
849 // Reading image
850  char buffer[FILENAME_MAX];
851  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), m_frameCount);
852  std::string imageFileName;
853  // check timestamp
854  std::vector<std::string> splitName =
855  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
856 
857  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
858  if (!parentName.empty()) {
859  parentName = parentName + vpIoTools::path("/");
860  }
861  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
862  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
863  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
864  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
865  }
866  if (splitName.size() == 2) { // no timestamp : image0002.png for example
867  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
868  timestamp = 0;
869  }
870  else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
871  std::vector<std::string> dirFiles;
872 
873  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
874  dirFiles = vpIoTools::getDirFiles(parentName);
875 
876  std::sort(dirFiles.begin(), dirFiles.end());
877  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
878  2)) { // case of xml file in same directory
879  for (unsigned int i = 0; i < dirFiles.size(); i++) {
880  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
881  dirFiles.erase(dirFiles.begin() + i);
882  }
883  }
884  std::istringstream(vpIoTools::splitChain(dirFiles.at(m_frameCount), std::string(".")).at(1)) >> timestamp;
885 
886  if (dirFiles.size() !=
887  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
888  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
889  "only the entire image sequence (no additionnal files allowed)"));
890 
891  imageFileName = parentName + dirFiles.at(m_frameCount);
892  }
893  else { // path not correct
894  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
895  }
896  }
897 
898  vpImageIo::read(image, imageFileName);
899  image.setTransducerSettings(m_frame);
900  image.setScanLineNumber(image.getWidth());
901  image.setDepth(m_frame.getDepth());
902  image.setAxialResolution(m_frame.getAxialResolution());
903  image.setSamplingFrequency(m_frame.getSamplingFrequency());
904  image.setTransmitFrequency(m_frame.getTransmitFrequency());
905 
906  m_frameCount += loopIncrement;
907 }
908 
914 template <class ImageType> void usSequenceReader<ImageType>::getFrame(ImageType &image, int index)
915 {
916  if (!is_open) {
917  open(image);
918  return;
919  }
920  if (index < m_firstFrame || index > m_lastFrame) {
921  throw(vpException(vpException::badValue, "position out of range"));
922  }
923 
924 // Reading image
925  char buffer[FILENAME_MAX];
926  snprintf(buffer, FILENAME_MAX, m_genericImageFileName.c_str(), index);
927  std::string imageFileName = buffer;
928 
929  vpImageIo::read(image, imageFileName);
930  image.setImageSettins(m_frame);
931 }
932 
938 template <class ImageType> ImageType &usSequenceReader<ImageType>::getFrame(int index)
939 {
940  ImageType image;
941  getFrame(image, index);
942  return image;
943 }
944 
949 template <class ImageType> void usSequenceReader<ImageType>::setLoopCycling(bool activateLoopCycling)
950 {
951  m_enableLoopCycling = activateLoopCycling;
952 }
953 
958 template <class ImageType> long usSequenceReader<ImageType>::getFrameCount()
959 {
960  if (is_open)
961  return m_lastFrame - m_firstFrame + 1;
962  throw(vpException(vpException::fatalError, "Cannot compute the frame number of the sequence before opening it !"));
963 }
964 
970 {
971  if (is_open)
972  return m_xmlParser;
973  throw(vpException(vpException::fatalError, "Sequence not opened, xml parser is empty !"));
974 }
975 
976 #endif
977 #endif // __usSequenceReader_h_
void setHeightResolution(double heightResolution)
double getHeightResolution() const
void setWidthResolution(double widthResolution)
void setScanLineNumber(unsigned int scanLineNumber)
void setImagePreScanSettings(const usImagePreScanSettings &preScanSettings)
void setAxialResolution(const double axialResolution)
Input/output operations between ultrasound image settings and the assiciated xml files.
Reading of sequences of ultrasound images.
virtual ~usSequenceReader()
void open(ImageType &image, uint64_t &timestamp)
void acquire(ImageType &image)
void setSequenceFileName(const std::string &sequenceFileName)
usImageSettingsXmlParser getXmlParser()
void setLastFrameIndex(long lastIndex)
std::vector< uint64_t > getSequenceTimestamps() const
long getImageNumber() const
void open(ImageType &image)
void setLoopCycling(bool activateLoopCycling)
ImageType & getFrame(int index)
double getFrameRate() const
void acquire(ImageType &image, uint64_t &timestamp)
void setFirstFrameIndex(long firstIndex)
void getFrame(ImageType &image, int index)
void setTransducerConvexity(const bool isTransducerConvex)
void setDepth(double depth)
void setScanLinePitch(const double scanLinePitch)
void setTransmitFrequency(const int transmitFrequency)
void setSamplingFrequency(const int samplingFrequency)
void setTransducerRadius(const double transducerRadius)
void setTransducerSettings(const usTransducerSettings &other)
void setScanLineNumber(unsigned int scanLineNumber)
@ PRESCAN_2D
Definition: us.h:70
@ POSTSCAN_2D
Definition: us.h:72