UsTK : Ultrasound ToolKit  version 2.0.1 under development (2025-03-14)
tutorial-sonosite-grabber.cpp
1 #include <iostream>
4 
5 #include <visp3/core/vpImageConvert.h>
6 #include <visp3/core/vpMutex.h>
7 #include <visp3/core/vpThread.h>
8 #include <visp3/core/vpTime.h>
9 #include <visp3/gui/vpDisplayX.h>
10 #include <visp3/sensor/vpV4l2Grabber.h>
11 
12 #include <visp3/ustk_core/usImagePostScan2D.h>
13 
14 #if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD)
15 
16 // Shared vars
17 typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
18 t_CaptureState s_capture_state = capture_waiting;
19 vpImage<unsigned char> s_frame;
20 vpMutex s_mutex_capture;
22 
24 vpThread::Return captureFunction(vpThread::Args args)
25 {
26  vpV4l2Grabber cap = *((vpV4l2Grabber *)args);
27  vpImage<unsigned char> frame_;
28  bool stop_capture_ = false;
29 
30  cap.open(frame_);
31 
32  vpRect roi(vpImagePoint(48, 90), vpImagePoint(416, 550)); // roi to remove sonosite banners
33 
34  while (!stop_capture_) {
35  // Capture in progress
36  cap.acquire(frame_, roi); // get a new frame from camera
37 
38  // Update shared data
39  {
40  vpMutex::vpScopedLock lock(s_mutex_capture);
41  if (s_capture_state == capture_stopped)
42  stop_capture_ = true;
43  else
44  s_capture_state = capture_started;
45  s_frame = frame_;
46  }
47  }
48 
49  {
50  vpMutex::vpScopedLock lock(s_mutex_capture);
51  s_capture_state = capture_stopped;
52  }
53  std::cout << "End of capture thread" << std::endl;
54  return 0;
55 }
57 
59 vpThread::Return displayFunction(vpThread::Args args)
60 {
61  (void)args; // Avoid warning: unused parameter args
62  vpImage<unsigned char> I_;
64 
65  t_CaptureState capture_state_;
66  bool display_initialized_ = false;
67 #if defined(VISP_HAVE_X11)
68  vpDisplayX *d_ = NULL;
69 #endif
70 
71  do {
72  s_mutex_capture.lock();
73  capture_state_ = s_capture_state;
74  s_mutex_capture.unlock();
75 
76  // Check if a frame is available
77  if (capture_state_ == capture_started) {
78  // Create a copy of the captured frame
79  {
80  vpMutex::vpScopedLock lock(s_mutex_capture);
81  I_ = s_frame;
82  }
83 
84  // Convert image into post-scan image
85  postScan_.setData(I_);
86  postScan_.setProbeName("Sonosite C60");
87  postScan_.setTransducerRadius(0.060);
88  postScan_.setTransducerConvexity(true);
89  postScan_.setScanLineNumber(128);
90  postScan_.setScanLinePitch(vpMath::rad(57 / 127)); // field of view is 57 deg
91 
92  // Check if we need to initialize the display with the first frame
93  if (!display_initialized_) {
94 // Initialize the display
95 #if defined(VISP_HAVE_X11)
96  d_ = new vpDisplayX(postScan_);
97  display_initialized_ = true;
98 #endif
99  }
100 
101  // Display the image
102  vpDisplay::display(postScan_);
103 
104  // Trigger end of acquisition with a mouse click
105  vpDisplay::displayText(postScan_, 10, 10, "Click to exit...", vpColor::red);
106  if (vpDisplay::getClick(postScan_, false)) {
107  vpMutex::vpScopedLock lock(s_mutex_capture);
108  s_capture_state = capture_stopped;
109  }
110 
111  // Update the display
112  vpDisplay::flush(postScan_);
113  } else {
114  vpTime::wait(2); // Sleep 2ms
115  }
116  } while (capture_state_ != capture_stopped);
117 
118 #if defined(VISP_HAVE_X11)
119  delete d_;
120 #endif
121 
122  std::cout << "End of display thread" << std::endl;
123  return 0;
124 }
126 
128 int main(int argc, const char *argv[])
129 {
130  unsigned int opt_input = 1; // Default value is 1 to mach the material in the lab
131 
132  // Command line options
133  for (int i = 0; i < argc; i++) {
134  if (std::string(argv[i]) == "--input")
135  opt_input = (unsigned int)atoi(argv[i + 1]);
136  else if (std::string(argv[i]) == "--help") {
137  std::cout << "Usage: " << argv[0] << " [--input <number>] [--help]" << std::endl;
138  return 0;
139  }
140  }
141 
142  // Instantiate the grabber
143  vpV4l2Grabber g;
144 
145  g.setInput(opt_input);
146  g.setScale(1);
147 
148  // Start the threads
149  vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&g);
150  vpThread thread_display((vpThread::Fn)displayFunction);
151 
152  // Wait until thread ends up
153  thread_capture.join();
154  thread_display.join();
155 
156  return 0;
157 }
159 
160 #else
161 int main()
162 {
163 #ifndef VISP_HAVE_V4L2
164  std::cout << "You should enable V4L2 to make this example working..." << std::endl;
165 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
166  std::cout << "You should enable pthread usage and rebuild ViSP..." << std::endl;
167 #else
168  std::cout << "Multi-threading seems not supported on this platform" << std::endl;
169 #endif
170 }
171 
172 #endif
void setData(const vpImage< Type > &image)
void setTransducerConvexity(const bool isTransducerConvex)
void setScanLinePitch(const double scanLinePitch)
void setProbeName(std::string probeName)
void setTransducerRadius(const double transducerRadius)
void setScanLineNumber(unsigned int scanLineNumber)