UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
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  } else if (loopIncrement == -1) {
134  if (m_frameCount < m_firstFrame) {
135  m_frameCount += 2;
136  loopIncrement = 1;
137  return false;
138  }
139  }
140  } else if (m_frameCount > m_lastFrame || m_frameCount < m_firstFrame)
141  return true;
142  return false;
143  }
144 
145  // get image by its number in the sequence
146  void getFrame(ImageType &image, int index);
147 
148  // get image by its number in the sequence
149  ImageType &getFrame(int index);
150 
151  // total number of frames in the sequence
153 
154  // attributes getters/setters
155  double getFrameRate() const { return m_frameRate; }
156  long getImageNumber() const { return m_frameCount; }
157 
158  // timestamps vector getter
159  std::vector<uint64_t> getSequenceTimestamps() const { return m_timestamps; }
160 
161  // get the xml parser : usefull to acess all the image settings contained in it
163 
164  void open(ImageType &image, uint64_t &timestamp);
165  void open(ImageType &image);
166 
167  void setFirstFrameIndex(long firstIndex);
168  void setLastFrameIndex(long lastIndex);
169  void setLoopCycling(bool activateLoopCycling);
170  void setSequenceFileName(const std::string &sequenceFileName);
171 };
172 
173 /****************************************************************************
174 * Template implementations.
175 ****************************************************************************/
176 
180 template <class ImageType>
182  : m_frame(), m_frameRate(0.0), m_firstFrame(0), m_firstFrameIsSet(false), m_lastFrame(0), m_lastFrameIsSet(false),
183  m_frameCount(0), m_sequenceFileName(""), m_genericImageFileName(""), m_fileNameIsSet(false), is_open(false),
184  m_enableLoopCycling(false), loopIncrement(1)
185 {
186 }
187 
191 template <class ImageType> usSequenceReader<ImageType>::~usSequenceReader() {}
192 
197 template <class ImageType> void usSequenceReader<ImageType>::setSequenceFileName(const std::string &sequenceFileName)
198 {
199  m_sequenceFileName = sequenceFileName;
200  m_fileNameIsSet = true;
201 }
202 
207 template <class ImageType> void usSequenceReader<ImageType>::setFirstFrameIndex(long firstIndex)
208 {
209  m_firstFrame = firstIndex;
210  m_firstFrameIsSet = true;
211 }
212 
217 template <class ImageType> void usSequenceReader<ImageType>::setLastFrameIndex(long lastIndex)
218 {
219  m_lastFrame = lastIndex;
220  m_lastFrameIsSet = true;
221 }
222 
227 template <class ImageType> void usSequenceReader<ImageType>::open(ImageType &image)
228 {
229  (void)image;
230  throw(vpException(vpException::notImplementedError));
231 }
232 
238 template <class ImageType> void usSequenceReader<ImageType>::open(ImageType &image, uint64_t &timestamp)
239 {
240  (void)image;
241  (void)timestamp;
242  throw(vpException(vpException::notImplementedError));
243 }
244 
246 {
247  if (!m_fileNameIsSet) {
248  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
249  }
250 
251  m_xmlParser.parse(m_sequenceFileName);
252  if (m_xmlParser.getImageType() != us::PRESCAN_2D)
253  throw(vpException(vpException::badValue), "trying to open a non-usImagePreScan2D image !");
254 
255  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
256  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
257  m_frameRate = m_xmlParser.getSequenceFrameRate();
258  m_genericImageFileName = m_xmlParser.getImageFileName();
259 
260  // saving the settings for all the pre-scan sequence
261  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
262  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
263  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
264  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
265  m_frame.setAxialResolution(m_xmlParser.getAxialResolution());
266  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
267  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
268 
269  // Reading image
270  char buffer[FILENAME_MAX];
271  sprintf(buffer, m_genericImageFileName.c_str(), m_firstFrame);
272  std::string imageFileName;
273  // check timestamp
274  std::vector<std::string> splitName =
275  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
276 
277  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
278  if (!parentName.empty()) {
279  parentName = parentName + vpIoTools::path("/");
280  }
281  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
282  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
283  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
284  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
285  }
286  if (splitName.size() == 2) { // no timestamp : image0002.png for example
287  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
288  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
289  std::vector<std::string> dirFiles;
290 
291  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
292  dirFiles = vpIoTools::getDirFiles(parentName);
293 
294  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
295  2)) { // case of xml file in same directory
296  for (unsigned int i = 0; i < dirFiles.size(); i++) {
297  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
298  dirFiles.erase(dirFiles.begin() + i);
299  }
300  }
301  if (dirFiles.size() !=
302  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
303  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
304  "only the entire image sequence (no additionnal files allowed)"));
305 
306  // getting the all the timestamps of the sequence
307  unsigned int i = 0;
308  while (i < dirFiles.size()) {
309  uint64_t timestamp_temp;
310  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
311  m_timestamps.push_back(timestamp_temp);
312  i++;
313  }
314  imageFileName = parentName + dirFiles.front();
315  } else { // path not correct
316  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
317  }
318  }
319 
320  vpImageIo::read(image, imageFileName);
321 
322  m_frame.setDepth((image.getHeight() - 1) * m_frame.getAxialResolution());
323 
324  // workaround to prevent the resize by setImagePreScanSettings (having a scanline number at 0 if not precised in the
325  // xml)
326  int scanlineNumber = image.getWidth();
327  image.setImagePreScanSettings(m_frame);
328  image.setScanLineNumber(scanlineNumber);
329 
330  m_frameCount = m_firstFrame + 1;
331  is_open = true;
332 }
333 
334 template <>
336  uint64_t &timestamp)
337 {
338  if (!m_fileNameIsSet) {
339  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
340  }
341 
342  m_xmlParser.parse(m_sequenceFileName);
343  if (m_xmlParser.getImageType() != us::PRESCAN_2D)
344  throw(vpException(vpException::badValue), "trying to open a non-usImagePreScan2D image !");
345 
346  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
347  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
348  m_frameRate = m_xmlParser.getSequenceFrameRate();
349  m_genericImageFileName = m_xmlParser.getImageFileName();
350 
351  // saving the settings for all the pre-scan sequence
352  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
353  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
354  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
355  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
356  m_frame.setAxialResolution(m_xmlParser.getAxialResolution());
357  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
358  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
359 
360  // Reading image
361  char buffer[FILENAME_MAX];
362  sprintf(buffer, m_genericImageFileName.c_str(), m_firstFrame);
363  std::string imageFileName;
364  // check timestamp
365  std::vector<std::string> splitName =
366  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
367 
368  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
369  if (!parentName.empty()) {
370  parentName = parentName + vpIoTools::path("/");
371  }
372  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
373  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
374  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
375  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
376  }
377  if (splitName.size() == 2) { // no timestamp : image0002.png for example
378  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
379  timestamp = 0;
380  m_timestamps.clear();
381  m_timestamps.push_back(timestamp);
382  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
383  std::vector<std::string> dirFiles;
384 
385  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
386  dirFiles = vpIoTools::getDirFiles(parentName);
387 
388  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
389  2)) { // case of xml file in same directory
390  for (unsigned int i = 0; i < dirFiles.size(); i++) {
391  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
392  dirFiles.erase(dirFiles.begin() + i);
393  }
394  }
395  if (dirFiles.size() !=
396  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
397  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
398  "only the entire image sequence (no additionnal files allowed)"));
399 
400  // getting the all the timestamps of the sequence
401  unsigned int i = 0;
402  while (i < dirFiles.size()) {
403  uint64_t timestamp_temp;
404  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
405  m_timestamps.push_back(timestamp_temp);
406  i++;
407  }
408  std::istringstream(vpIoTools::splitChain(dirFiles.at(0), std::string(".")).at(1)) >> timestamp;
409 
410  imageFileName = parentName + dirFiles.front();
411  } else { // path not correct
412  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
413  }
414  }
415 
416  vpImageIo::read(image, imageFileName);
417 
418  m_frame.setDepth((image.getHeight() - 1) * m_frame.getAxialResolution());
419 
420  // workaround to prevent the resize by setImagePreScanSettings (having a scanline number at 0 if not precised in the
421  // xml)
422  int scanlineNumber = image.getWidth();
423  image.setImagePreScanSettings(m_frame);
424  image.setScanLineNumber(scanlineNumber);
425 
426  m_frameCount = m_firstFrame + 1;
427  is_open = true;
428 }
429 
430 template <>
432 {
433  if (!m_fileNameIsSet) {
434  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
435  }
436 
437  m_xmlParser.parse(m_sequenceFileName);
438  if (m_xmlParser.getImageType() != us::POSTSCAN_2D)
439  throw(vpException(vpException::badValue), "trying to open a non-usImagePostScan2D image !");
440 
441  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
442  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
443  m_frameRate = m_xmlParser.getSequenceFrameRate();
444  m_genericImageFileName = m_xmlParser.getImageFileName();
445 
446  // saving the settings for all the post scan sequence
447  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
448  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
449  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
450  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
451  m_frame.setWidthResolution(m_xmlParser.getWidthResolution());
452  m_frame.setHeightResolution(m_xmlParser.getHeightResolution());
453  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
454  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
455 
456  // Reading image
457  char buffer[FILENAME_MAX];
458  sprintf(buffer, m_genericImageFileName.c_str(), m_firstFrame);
459  std::string imageFileName;
460  // check timestamp
461  std::vector<std::string> splitName =
462  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
463 
464  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
465  if (!parentName.empty()) {
466  parentName = parentName + vpIoTools::path("/");
467  }
468  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
469  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
470  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
471  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
472  }
473  if (splitName.size() == 2) { // no timestamp : image0002.png for example
474  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
475  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
476  std::vector<std::string> dirFiles;
477 
478  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
479  dirFiles = vpIoTools::getDirFiles(parentName);
480 
481  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
482  2)) { // case of xml file in same directory
483  for (unsigned int i = 0; i < dirFiles.size(); i++) {
484  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
485  dirFiles.erase(dirFiles.begin() + i);
486  }
487  }
488 
489  if (dirFiles.size() !=
490  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
491  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
492  "only the entire image sequence (no additionnal files allowed)"));
493 
494  // getting the all the timestamps of the sequence
495  unsigned int i = 0;
496  while (i < dirFiles.size()) {
497  uint64_t timestamp_temp;
498  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
499  m_timestamps.push_back(timestamp_temp);
500  i++;
501  }
502 
503  imageFileName = parentName + dirFiles.front();
504  } else { // path not correct
505  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
506  }
507  }
508 
509  vpImageIo::read(image, imageFileName);
510  m_frame.setDepth(image.getHeight() - 1 * m_frame.getHeightResolution());
511 
512  image.setTransducerRadius(m_frame.getTransducerRadius());
513  image.setScanLinePitch(m_frame.getScanLinePitch());
514  image.setScanLineNumber(m_frame.getScanLineNumber());
515  image.setTransducerConvexity(m_frame.isTransducerConvex());
516  image.setWidthResolution(m_frame.getWidthResolution());
517  image.setHeightResolution(m_frame.getHeightResolution());
518  image.setSamplingFrequency(m_frame.getSamplingFrequency());
519  image.setTransmitFrequency(m_frame.getTransmitFrequency());
520  image.setDepth(m_frame.getDepth());
521 
522  m_frameCount = m_firstFrame + 1;
523  is_open = true;
524 }
525 
526 template <>
528  uint64_t &timestamp)
529 {
530  if (!m_fileNameIsSet) {
531  throw(vpException(vpException::badValue, "Sequence settings file name not set"));
532  }
533 
534  m_xmlParser.parse(m_sequenceFileName);
535  if (m_xmlParser.getImageType() != us::POSTSCAN_2D)
536  throw(vpException(vpException::badValue), "trying to open a non-usImagePostScan2D image !");
537 
538  setFirstFrameIndex(m_xmlParser.getSequenceStartNumber());
539  setLastFrameIndex(m_xmlParser.getSequenceStopNumber());
540  m_frameRate = m_xmlParser.getSequenceFrameRate();
541  m_genericImageFileName = m_xmlParser.getImageFileName();
542 
543  // saving the settings for all the post scan sequence
544  m_frame.setTransducerRadius(m_xmlParser.getTransducerSettings().getTransducerRadius());
545  m_frame.setScanLinePitch(m_xmlParser.getTransducerSettings().getScanLinePitch());
546  m_frame.setScanLineNumber(m_xmlParser.getTransducerSettings().getScanLineNumber());
547  m_frame.setTransducerConvexity(m_xmlParser.getTransducerSettings().isTransducerConvex());
548  m_frame.setWidthResolution(m_xmlParser.getWidthResolution());
549  m_frame.setHeightResolution(m_xmlParser.getHeightResolution());
550  m_frame.setSamplingFrequency(m_xmlParser.getTransducerSettings().getSamplingFrequency());
551  m_frame.setTransmitFrequency(m_xmlParser.getTransducerSettings().getTransmitFrequency());
552 
553  // Reading image
554  char buffer[FILENAME_MAX];
555  sprintf(buffer, m_genericImageFileName.c_str(), m_firstFrame);
556  std::string imageFileName;
557  // check timestamp
558  std::vector<std::string> splitName =
559  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
560 
561  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
562  if (!parentName.empty()) {
563  parentName = parentName + vpIoTools::path("/");
564  }
565  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
566  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
567  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
568  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
569  }
570  if (splitName.size() == 2) { // no timestamp : image0002.png for example
571  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
572  timestamp = 0;
573  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
574  std::istringstream(splitName.at(1)) >> timestamp;
575  std::vector<std::string> dirFiles;
576 
577  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
578  dirFiles = vpIoTools::getDirFiles(parentName);
579 
580  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
581  2)) { // case of xml file in same directory
582  for (unsigned int i = 0; i < dirFiles.size(); i++) {
583  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
584  dirFiles.erase(dirFiles.begin() + i);
585  }
586  }
587 
588  std::istringstream(vpIoTools::splitChain(dirFiles.at(0), std::string(".")).at(1)) >> timestamp;
589 
590  if (dirFiles.size() !=
591  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
592  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
593  "only the entire image sequence (no additionnal files allowed)"));
594 
595  // getting the all the timestamps of the sequence
596  unsigned int i = 0;
597  while (i < dirFiles.size()) {
598  uint64_t timestamp_temp;
599  std::istringstream(vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1)) >> timestamp_temp;
600  m_timestamps.push_back(timestamp_temp);
601  i++;
602  }
603 
604  imageFileName = parentName + dirFiles.front();
605  } else { // path not correct
606  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
607  }
608  }
609  vpImageIo::read(image, imageFileName);
610  m_frame.setDepth(image.getHeight() - 1 * m_frame.getHeightResolution());
611 
612  image.setTransducerRadius(m_frame.getTransducerRadius());
613  image.setScanLinePitch(m_frame.getScanLinePitch());
614  image.setScanLineNumber(m_frame.getScanLineNumber());
615  image.setTransducerConvexity(m_frame.isTransducerConvex());
616  image.setWidthResolution(m_frame.getWidthResolution());
617  image.setHeightResolution(m_frame.getHeightResolution());
618  image.setSamplingFrequency(m_frame.getSamplingFrequency());
619  image.setTransmitFrequency(m_frame.getTransmitFrequency());
620  image.setDepth(m_frame.getDepth());
621 
622  m_frameCount = m_firstFrame + 1;
623  is_open = true;
624 }
625 
630 template <class ImageType> void usSequenceReader<ImageType>::acquire(ImageType &image)
631 {
632  if (!is_open) {
633  this->open(image);
634  return;
635  }
636 
637  // Reading image
638  char buffer[FILENAME_MAX];
639  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
640  std::string imageFileName;
641  // check timestamp
642  std::vector<std::string> splitName =
643  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
644 
645  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
646  if (!parentName.empty()) {
647  parentName = parentName + vpIoTools::path("/");
648  }
649  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
650  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
651  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
652  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
653  }
654  if (splitName.size() == 2) { // no timestamp : image0002.png for example
655  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
656  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
657  std::vector<std::string> dirFiles;
658 
659  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
660  dirFiles = vpIoTools::getDirFiles(parentName);
661 
662  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
663  2)) { // case of xml file in same directory
664  for (unsigned int i = 0; i < dirFiles.size(); i++) {
665  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
666  dirFiles.erase(dirFiles.begin() + i);
667  }
668  }
669 
670  if (dirFiles.size() !=
671  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
672  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
673  "only the entire image sequence (no additionnal files allowed)"));
674 
675  imageFileName = parentName + dirFiles.at(m_frameCount);
676  } else { // path not correct
677  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
678  }
679  }
680  vpImageIo::read(image, imageFileName);
681  image.setTransducerSettings(m_frame);
682  image.setScanLineNumber(image.getWidth());
683  image.setDepth(m_frame.getDepth());
684 
685  m_frameCount += loopIncrement;
686 }
687 
693 template <class ImageType> void usSequenceReader<ImageType>::acquire(ImageType &image, uint64_t &timestamp)
694 {
695  if (!is_open) {
696  this->open(image, timestamp);
697  return;
698  }
699  // Reading image
700  char buffer[FILENAME_MAX];
701  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
702  std::string imageFileName;
703  // check timestamp
704  std::vector<std::string> splitName =
705  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
706 
707  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
708  if (!parentName.empty()) {
709  parentName = parentName + vpIoTools::path("/");
710  }
711  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
712  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
713  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
714  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
715  }
716  if (splitName.size() == 2) { // no timestamp : image0002.png for example
717  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
718  timestamp = 0;
719  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
720 
721  std::vector<std::string> dirFiles;
722 
723  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
724  dirFiles = vpIoTools::getDirFiles(parentName);
725 
726  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
727  2)) { // case of xml file in same directory
728  for (unsigned int i = 0; i < dirFiles.size(); i++) {
729  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
730  dirFiles.erase(dirFiles.begin() + i);
731  }
732  }
733 
734  std::istringstream(vpIoTools::splitChain(dirFiles.at(m_frameCount), std::string(".")).at(1)) >> timestamp;
735 
736  if (dirFiles.size() !=
737  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
738  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
739  "only the entire image sequence (no additionnal files allowed)"));
740 
741  imageFileName = parentName + dirFiles.at(m_frameCount);
742  } else { // path not correct
743  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
744  }
745  }
746 
747  vpImageIo::read(image, imageFileName);
748  image.setTransducerSettings(m_frame);
749  image.setScanLineNumber(image.getWidth());
750  image.setDepth(m_frame.getDepth());
751 
752  m_frameCount += loopIncrement;
753 }
754 
759 template <>
761 {
762  if (!is_open) {
763  this->open(image);
764  return;
765  }
766  // Reading image
767  char buffer[FILENAME_MAX];
768  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
769  std::string imageFileName;
770  // check timestamp
771  std::vector<std::string> splitName =
772  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
773 
774  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
775  if (!parentName.empty()) {
776  parentName = parentName + vpIoTools::path("/");
777  }
778  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
779  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
780  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
781  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
782  }
783  if (splitName.size() == 2) { // no timestamp : image0002.png for example
784  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
785  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
786  std::vector<std::string> dirFiles;
787 
788  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
789  dirFiles = vpIoTools::getDirFiles(parentName);
790 
791  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
792  2)) { // case of xml file in same directory
793  for (unsigned int i = 0; i < dirFiles.size(); i++) {
794  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
795  dirFiles.erase(dirFiles.begin() + i);
796  }
797  }
798 
799  if (dirFiles.size() !=
800  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
801  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
802  "only the entire image sequence (no additionnal files allowed)"));
803 
804  imageFileName = parentName + dirFiles.at(m_frameCount);
805  } else { // path not correct
806  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
807  }
808  }
809 
810  vpImageIo::read(image, imageFileName);
811  image.setTransducerSettings(m_frame);
812  image.setScanLineNumber(image.getWidth());
813  image.setDepth(m_frame.getDepth());
814  image.setAxialResolution(m_frame.getAxialResolution());
815  image.setSamplingFrequency(m_frame.getSamplingFrequency());
816  image.setTransmitFrequency(m_frame.getTransmitFrequency());
817 
818  m_frameCount += loopIncrement;
819 }
820 
826 template <>
828  uint64_t &timestamp)
829 {
830  if (!is_open) {
831  this->open(image, timestamp);
832  return;
833  }
834  // Reading image
835  char buffer[FILENAME_MAX];
836  sprintf(buffer, m_genericImageFileName.c_str(), m_frameCount);
837  std::string imageFileName;
838  // check timestamp
839  std::vector<std::string> splitName =
840  vpIoTools::splitChain(vpIoTools::splitChain(m_genericImageFileName, std::string("/")).back(), std::string("."));
841 
842  std::string parentName = vpIoTools::getParent(m_sequenceFileName);
843  if (!parentName.empty()) {
844  parentName = parentName + vpIoTools::path("/");
845  }
846  std::vector<std::string> splitNameDirs = vpIoTools::splitChain(m_genericImageFileName, std::string("/"));
847  if (splitNameDirs.size() > 1) { // images are in a subdirectory of the one conatining the xml file
848  for (unsigned int i = 0; i < splitNameDirs.size() - 1; i++)
849  parentName += (splitNameDirs.at(i) + vpIoTools::path("/"));
850  }
851  if (splitName.size() == 2) { // no timestamp : image0002.png for example
852  imageFileName = parentName + vpIoTools::splitChain(std::string(buffer), std::string("/")).back();
853  timestamp = 0;
854  } else if (splitName.size() == 3) { // timestamp included : image0002.156464063.png for example
855  std::vector<std::string> dirFiles;
856 
857  if (vpIoTools::checkDirectory(vpIoTools::getParent(m_sequenceFileName))) { // correct path
858  dirFiles = vpIoTools::getDirFiles(parentName);
859 
860  std::sort(dirFiles.begin(), dirFiles.end());
861  if (dirFiles.size() == (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() +
862  2)) { // case of xml file in same directory
863  for (unsigned int i = 0; i < dirFiles.size(); i++) {
864  if (vpIoTools::splitChain(dirFiles.at(i), std::string(".")).at(1) == std::string("xml"))
865  dirFiles.erase(dirFiles.begin() + i);
866  }
867  }
868  std::istringstream(vpIoTools::splitChain(dirFiles.at(m_frameCount), std::string(".")).at(1)) >> timestamp;
869 
870  if (dirFiles.size() !=
871  (unsigned int)(m_xmlParser.getSequenceStopNumber() - m_xmlParser.getSequenceStartNumber() + 1))
872  throw(vpException(vpException::fatalError, "For imgage sequnces with timeStamps, the directory must contain "
873  "only the entire image sequence (no additionnal files allowed)"));
874 
875  imageFileName = parentName + dirFiles.at(m_frameCount);
876  } else { // path not correct
877  throw(vpException(vpException::fatalError), "Sequence filename incorrect !");
878  }
879  }
880 
881  vpImageIo::read(image, imageFileName);
882  image.setTransducerSettings(m_frame);
883  image.setScanLineNumber(image.getWidth());
884  image.setDepth(m_frame.getDepth());
885  image.setAxialResolution(m_frame.getAxialResolution());
886  image.setSamplingFrequency(m_frame.getSamplingFrequency());
887  image.setTransmitFrequency(m_frame.getTransmitFrequency());
888 
889  m_frameCount += loopIncrement;
890 }
891 
897 template <class ImageType> void usSequenceReader<ImageType>::getFrame(ImageType &image, int index)
898 {
899  if (!is_open) {
900  open(image);
901  return;
902  }
903  if (index < m_firstFrame || index > m_lastFrame) {
904  throw(vpException(vpException::badValue, "position out of range"));
905  }
906 
907  // Reading image
908  char buffer[FILENAME_MAX];
909  sprintf(buffer, m_genericImageFileName.c_str(), index);
910  std::string imageFileName = buffer;
911 
912  vpImageIo::read(image, imageFileName);
913  image.setImageSettins(m_frame);
914 }
915 
921 template <class ImageType> ImageType &usSequenceReader<ImageType>::getFrame(int index)
922 {
923  ImageType image;
924  getFrame(image, index);
925  return image;
926 }
927 
932 template <class ImageType> void usSequenceReader<ImageType>::setLoopCycling(bool activateLoopCycling)
933 {
934  m_enableLoopCycling = activateLoopCycling;
935 }
936 
941 template <class ImageType> long usSequenceReader<ImageType>::getFrameCount()
942 {
943  if (is_open)
944  return m_lastFrame - m_firstFrame + 1;
945  throw(vpException(vpException::fatalError, "Cannot compute the frame number of the sequence before opening it !"));
946 }
947 
953 {
954  if (is_open)
955  return m_xmlParser;
956  throw(vpException(vpException::fatalError, "Sequence not opened, xml parser is empty !"));
957 }
958 
959 #endif
960 #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