UsTK : Ultrasound ToolKit  version 2.0.1 under development (2025-03-14)
tutorial-sonosite-confidence-map.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_confidence_map/usScanlineConfidence2D.h>
13 #include <visp3/ustk_core/usImagePostScan2D.h>
14 #include <visp3/ustk_core/usImagePreScan2D.h>
15 #include <visp3/ustk_core/usPostScanToPreScan2DConverter.h>
16 #include <visp3/ustk_core/usPreScanToPostScan2DConverter.h>
17 
18 #if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD)
19 
20 // Shared vars
21 typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
22 t_CaptureState s_capture_state = capture_waiting;
23 vpImage<unsigned char> s_frame;
24 vpMutex s_mutex_capture;
26 
28 vpThread::Return captureFunction(vpThread::Args args)
29 {
30  vpV4l2Grabber cap = *((vpV4l2Grabber *)args);
31  vpImage<unsigned char> frame_;
32  bool stop_capture_ = false;
33 
34  cap.open(frame_);
35 
36  vpRect roi(vpImagePoint(55, 70), vpImagePoint(410, 555)); // roi to remove sonosite banners
37 
38  while (!stop_capture_) {
39  // Capture in progress
40  cap.acquire(frame_, roi); // get a new frame from camera
41 
42  // Update shared data
43  {
44  vpMutex::vpScopedLock lock(s_mutex_capture);
45  if (s_capture_state == capture_stopped)
46  stop_capture_ = true;
47  else
48  s_capture_state = capture_started;
49  s_frame = frame_;
50  }
51  }
52 
53  {
54  vpMutex::vpScopedLock lock(s_mutex_capture);
55  s_capture_state = capture_stopped;
56  }
57  std::cout << "End of capture thread" << std::endl;
58  return 0;
59 }
61 
63 vpThread::Return displayFunction(vpThread::Args args)
64 {
65  (void)args; // Avoid warning: unused parameter args
66  vpImage<unsigned char> I_;
69  usImagePostScan2D<unsigned char> confidencePostScan_;
70  usImagePreScan2D<unsigned char> confidencePreScan_;
71  usScanlineConfidence2D confidenceMapProcessor_;
72 
73  t_CaptureState capture_state_;
74  bool display_initialized_ = false;
75 #if defined(VISP_HAVE_X11)
76  vpDisplayX *dpost_scan_ = NULL; // display post-scan image
77  vpDisplayX *dpre_scan_ = NULL; // display pre-scan image
78  vpDisplayX *dpost_scan_confidence_ = NULL; // display post-scan image
79  vpDisplayX *dpre_scan_confidence_ = NULL; // display pre-scan image
80 
81 #endif
82 
83  do {
84  s_mutex_capture.lock();
85  capture_state_ = s_capture_state;
86  s_mutex_capture.unlock();
87 
88  // Check if a frame is available
89  if (capture_state_ == capture_started) {
90  // Create a copy of the captured frame
91  {
92  vpMutex::vpScopedLock lock(s_mutex_capture);
93  I_ = s_frame;
94  }
95 
96  // Convert image into post-scan image
97  postScan_.setData(I_);
98  postScan_.setProbeName("Sonosite C60");
99  postScan_.setTransducerRadius(0.060);
100  postScan_.setTransducerConvexity(true);
101  postScan_.setScanLineNumber(128);
102  postScan_.setDepth(0.12);
103  postScan_.setFieldOfView(vpMath::rad(57.0)); // field of view of C60 is 57 deg
104  postScan_.setHeightResolution((postScan_.getTransducerRadius() + postScan_.getDepth() -
105  (postScan_.getTransducerRadius() * cos(postScan_.getFieldOfView() / 2.0))) /
106  postScan_.getHeight());
107 
108  postScan_.setWidthResolution(
109  (2.0 * (postScan_.getTransducerRadius() + postScan_.getDepth()) * sin(postScan_.getFieldOfView() / 2.0)) /
110  postScan_.getWidth());
111 
112  // Convert post-scan to pre-scan image
113  usPostScanToPreScan2DConverter backConverter_;
114  backConverter_.convert(postScan_, preScan_, 480);
115 
116  // Compute confidence map on pre-scan image
117  // initialisations
118  // settings for sonosite probe
120 
121  // computing pre-scan confidence map
122  confidencePreScan_.setImagePreScanSettings(preScan_);
123  confidenceMapProcessor_.run(confidencePreScan_, preScan_);
124 
125  // converting computed confidence map in post-scan
126  converter_.convert(confidencePreScan_, confidencePostScan_);
127 
128  // Check if we need to initialize the display with the first frame
129  if (!display_initialized_) {
130 // Initialize the display
131 #if defined(VISP_HAVE_X11)
132  unsigned int xpos = 10;
133  dpost_scan_ = new vpDisplayX(postScan_, xpos, 10, "post-scan");
134  xpos += 80 + postScan_.getWidth();
135  dpre_scan_ = new vpDisplayX(preScan_, xpos, 10, "pre-scan");
136  xpos += 40 + preScan_.getWidth();
137  dpre_scan_confidence_ = new vpDisplayX(confidencePreScan_, xpos, 10, "pre-scan confidence");
138  xpos += 40 + confidencePreScan_.getWidth();
139  dpost_scan_confidence_ = new vpDisplayX(confidencePostScan_, xpos, 10, "post-scan confidence");
140  display_initialized_ = true;
141 #endif
142  }
143 
144  // Display the image
145  vpDisplay::display(postScan_);
146  vpDisplay::display(preScan_);
147  vpDisplay::display(confidencePreScan_);
148  vpDisplay::display(confidencePostScan_);
149 
150  // Trigger end of acquisition with a mouse click
151  vpDisplay::displayText(postScan_, 10, 10, "Click to exit...", vpColor::red);
152  if (vpDisplay::getClick(postScan_, false)) {
153  vpMutex::vpScopedLock lock(s_mutex_capture);
154  s_capture_state = capture_stopped;
155  }
156  vpDisplay::displayText(preScan_, 10, 10, "Click to exit...", vpColor::red);
157  if (vpDisplay::getClick(preScan_, false)) {
158  vpMutex::vpScopedLock lock(s_mutex_capture);
159  s_capture_state = capture_stopped;
160  }
161  vpDisplay::displayText(confidencePreScan_, 10, 10, "Click to exit...", vpColor::red);
162  if (vpDisplay::getClick(confidencePreScan_, false)) {
163  vpMutex::vpScopedLock lock(s_mutex_capture);
164  s_capture_state = capture_stopped;
165  }
166  vpDisplay::displayText(confidencePostScan_, 10, 10, "Click to exit...", vpColor::red);
167  if (vpDisplay::getClick(confidencePostScan_, false)) {
168  vpMutex::vpScopedLock lock(s_mutex_capture);
169  s_capture_state = capture_stopped;
170  }
171 
172  // Update the display
173  vpDisplay::flush(postScan_);
174  vpDisplay::flush(preScan_);
175  vpDisplay::flush(confidencePostScan_);
176  vpDisplay::flush(confidencePreScan_);
177  } else {
178  vpTime::wait(2); // Sleep 2ms
179  }
180  } while (capture_state_ != capture_stopped);
181 
182 #if defined(VISP_HAVE_X11)
183  delete dpost_scan_;
184  delete dpre_scan_;
185  delete dpost_scan_confidence_;
186  delete dpre_scan_confidence_;
187 #endif
188 
189  std::cout << "End of display thread" << std::endl;
190  return 0;
191 }
193 
195 int main(int argc, const char *argv[])
196 {
197  unsigned int opt_input = 1; // Default value is 1 to mach the material in the lab
198 
199  // Command line options
200  for (int i = 0; i < argc; i++) {
201  if (std::string(argv[i]) == "--input")
202  opt_input = (unsigned int)atoi(argv[i + 1]);
203  else if (std::string(argv[i]) == "--help") {
204  std::cout << "Usage: " << argv[0] << " [--input <number>] [--help]" << std::endl;
205  return 0;
206  }
207  }
208 
209  // Instantiate the grabber
210  vpV4l2Grabber g;
211 
212  g.setInput(opt_input);
213  g.setScale(1);
214 
215  // Start the threads
216  vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&g);
217  vpThread thread_display((vpThread::Fn)displayFunction);
218 
219  // Wait until thread ends up
220  thread_capture.join();
221  thread_display.join();
222 
223  return 0;
224 }
226 
227 #else
228 int main()
229 {
230 #ifndef VISP_HAVE_V4L2
231  std::cout << "You should enable V4L2 to make this example working..." << std::endl;
232 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
233  std::cout << "You should enable pthread usage and rebuild ViSP..." << std::endl;
234 #else
235  std::cout << "Multi-threading seems not supported on this platform" << std::endl;
236 #endif
237 }
238 
239 #endif
void setHeightResolution(double heightResolution)
void setData(const vpImage< Type > &image)
void setWidthResolution(double widthResolution)
void setImagePreScanSettings(const usImagePreScanSettings &preScanSettings)
void convert(const usImagePostScan2D< unsigned char > &imageToConvert, usImagePreScan2D< unsigned char > &imageConverted, int preScanSamples)
void convert(const usImagePreScan2D< unsigned char > &preScanImage, usImagePostScan2D< unsigned char > &postScanImage, double xResolution=0., double yResolution=0.)
Process a pre-scan image to determine the confidence map.
void run(usImagePreScan2D< unsigned char > &preScanConfidence, const usImagePreScan2D< unsigned char > &preScanImage)
void setFieldOfView(double fieldOfView)
void setTransducerConvexity(const bool isTransducerConvex)
void setDepth(double depth)
void setProbeName(std::string probeName)
void setTransducerRadius(const double transducerRadius)
double getTransducerRadius() const
void setScanLineNumber(unsigned int scanLineNumber)