UsTK : Ultrasound ToolKit  version 2.0.1 under development (2024-11-21)
Tutorial: UsTK grabber tutorial for ultrasonix station

Introduction

This tutorial expains how to grab ultrasound images using a TCP connection between the ultrasound station and a client, and to remote-control the station to change acquisition parameters.

In the lagadic team, we are using a ultrasonix station on which we developped a tcp server application to remotely control the acquisitions. Please contact us if you want to acess the server software (you will need an acess to the ultrasonix research SDK to make it work). Additionnal informations about the station we use :

  • Station type : Sonix touch
  • Sdk version : Sonix RP 5.6.0

Note that the source code used in this tutorial can be downloaded using the following command :

$ svn export https://github.com/lagadic/ustk.git/trunk/tutorial/ustk/ultrasonix

Simple grabbing

The easiest way to grab images using the ustk grabber is to let the acquisition parameters to default. Here is the code to simply grab pre-scan images :

#include <iostream>
#include <visp3/ustk_core/usConfig.h>
#if (defined(USTK_HAVE_QT5) || defined(USTK_HAVE_VTK_QT)) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI))
#include <QApplication>
#include <QStringList>
#include <QtCore/QThread>
#include <visp3/ustk_grabber/usNetworkGrabberPreScan2D.h>
#include <visp3/gui/vpDisplayGDI.h>
#include <visp3/gui/vpDisplayX.h>
int main(int argc, char **argv)
{
// QT application
QApplication app(argc, argv);
qtGrabber->connectToServer();
// record option
if (qApp->arguments().contains(QString("--record"))) {
qtGrabber->activateRecording(
qApp->arguments().at(qApp->arguments().indexOf(QString("--record")) + 1).toStdString());
}
// setting acquisition parameters
if (qApp->arguments().contains(QString("--probeID"))) {
header.probeId = qApp->arguments().at(qApp->arguments().indexOf(QString("--probeID")) + 1).toInt();
} else
header.probeId = 15; // 4DC7 id = 15 by default
if (qApp->arguments().contains(QString("--slotID"))) {
header.slotId = qApp->arguments().at(qApp->arguments().indexOf(QString("--slotID")) + 1).toInt();
} else
header.slotId = 0; // top slot id = 0 by default
if (qApp->arguments().contains(QString("--imagingMode"))) {
header.imagingMode = qApp->arguments().at(qApp->arguments().indexOf(QString("--imagingMode")) + 1).toInt();
} else
header.imagingMode = 0; // B-mode = 0 by default
// prepare image;
// Prepare display
#if defined(VISP_HAVE_X11)
vpDisplayX *display = NULL;
#elif defined(VISP_HAVE_GDI)
vpDisplayGDI *display = NULL;
#endif
bool displayInit = false;
bool captureRunning = true;
// sending acquisition parameters
qtGrabber->initAcquisition(header);
qtGrabber->setMotorPosition(37);
// Send the command to run the acquisition
qtGrabber->runAcquisition();
// our grabbing loop
do {
grabbedFrame = qtGrabber->acquire();
std::cout << "MAIN THREAD received frame No : " << grabbedFrame->getFrameCount() << std::endl;
// init display
if (!displayInit && grabbedFrame->getHeight() != 0 && grabbedFrame->getWidth() != 0) {
#if defined(VISP_HAVE_X11)
display = new vpDisplayX(*grabbedFrame);
#elif defined(VISP_HAVE_GDI)
display = new vpDisplayGDI(*grabbedFrame);
#endif
qtGrabber->useVpDisplay(display);
displayInit = true;
}
// processing display
if (displayInit) {
if (vpDisplay::getClick(*grabbedFrame, false))
captureRunning = false;
vpDisplay::display(*grabbedFrame);
vpDisplay::displayText(*grabbedFrame, 20, 20, std::string("Click to exit..."), vpColor::red);
vpDisplay::flush(*grabbedFrame);
}
} while (captureRunning);
qtGrabber->stopAcquisition();
if (displayInit) {
delete display;
}
return 0;
}
#else
int main()
{
std::cout << "You should intall Qt5 (with wigdets and network modules), and display X to run this tutorial"
<< std::endl;
return 0;
}
#endif
Class to store additionnal informations arriving on the network with ultrasound images grabbed,...
quint32 getFrameCount() const
Specific class to grab pre-scan frames from the ultrasound station on the network.
void activateRecording(std::string path)
usFrameGrabbedInfo< usImagePreScan2D< unsigned char > > * acquire()
void useVpDisplay(vpDisplay *display)
bool initAcquisition(const usNetworkGrabber::usInitHeaderSent &header)
void setMotorPosition(int motorPosition)
VISP_EXPORT void display(const usOrientedPlane3D &plane, const vpImage< ImageDataType > &I, const vpHomogeneousMatrix &imageMworld, double Xscale=3000, double Yscale=3000, const vpColor &color=vpColor::green)
Display usOrientedPlane3D.

Some details about this code :

  • You will need Qt to use the grabber (it is based on QTcpSocket)
  • You will need X11 to display the images
  • This code sets some parameters :
    • Probe id : the id of the ultrasound probe you mant to use. Here we selected the 4DC7(15).
    • Slot id : there is 3 slots on the station to connect probes. The top one has the id 0, the middle one 2, and the bottom ont 1.
    • Imaging mode : we selected B-mode (pre-scan) images using the id 0.

Note that the acquire() method can be blocking, to prevent grabbing 2 times the same frame (if you call it faster than the frames are arriving). But if you call it slower, you will loose frames.

Grabbing with selection of acquisition parameters

If you want to remotely change the acquisition parameters, here is a code showing how to proceed :

#include <iostream>
#include <visp3/ustk_core/usConfig.h>
#if (defined(USTK_HAVE_QT5) || defined(USTK_HAVE_VTK_QT)) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI))
#include <QApplication>
#include <QStringList>
#include <QtCore/QThread>
#include <visp3/ustk_grabber/usNetworkGrabberPostScan2D.h>
#include <visp3/gui/vpDisplayGDI.h>
#include <visp3/gui/vpDisplayX.h>
int main(int argc, char **argv)
{
// QT application
QApplication app(argc, argv);
qtGrabber->connectToServer();
// record option
if (qApp->arguments().contains(QString("--record"))) {
qtGrabber->activateRecording(
qApp->arguments().at(qApp->arguments().indexOf(QString("--record")) + 1).toStdString());
}
// setting acquisition parameters
if (qApp->arguments().contains(QString("--probeID"))) {
header.probeId = qApp->arguments().at(qApp->arguments().indexOf(QString("--probeID")) + 1).toInt();
} else
header.probeId = 15; // 4DC7 id = 15 by default
if (qApp->arguments().contains(QString("--slotID"))) {
header.slotId = qApp->arguments().at(qApp->arguments().indexOf(QString("--slotID")) + 1).toInt();
} else
header.slotId = 0; // top slot id = 0 by default
if (qApp->arguments().contains(QString("--imagingMode"))) {
header.imagingMode = qApp->arguments().at(qApp->arguments().indexOf(QString("--imagingMode")) + 1).toInt();
} else
header.imagingMode = 0; // B-mode = 0 by default
// Prepare display
#if defined(VISP_HAVE_X11)
vpDisplayX *display = NULL;
#elif defined(VISP_HAVE_GDI)
vpDisplayGDI *display = NULL;
#endif
bool displayInit = false;
bool captureRunning = true;
// sending acquisition parameters
qtGrabber->initAcquisition(header);
// grab a 640*480 post-scan image
qtGrabber->setPostScanMode(true);
qtGrabber->setPostScanHeigh(480);
qtGrabber->setPostScanWidth(640);
// set the ultrsound depth to 140 mm
qtGrabber->setImageDepth(140);
// set the 4DC7 motor on the middle frame
qtGrabber->setMotorPosition(37);
std::cout << "send update" << std::endl;
std::cout << "end update" << std::endl;
qtGrabber->runAcquisition();
std::cout << "waiting ultrasound initialisation..." << std::endl;
// our local grabbing loop
do {
grabbedFrame = qtGrabber->acquire();
std::cout << "MAIN THREAD received frame No : " << grabbedFrame->getFrameCount() << std::endl;
std::cout << *grabbedFrame << std::endl;
// init display
if (!displayInit && grabbedFrame->getHeight() != 0 && grabbedFrame->getWidth() != 0) {
#if defined(VISP_HAVE_X11)
display = new vpDisplayX(*grabbedFrame);
#elif defined(VISP_HAVE_GDI)
display = new vpDisplayGDI(*grabbedFrame);
#endif
qtGrabber->useVpDisplay(display);
displayInit = true;
}
// processing display
if (displayInit) {
if (vpDisplay::getClick(*grabbedFrame, false))
captureRunning = false;
vpDisplay::display(*grabbedFrame);
vpDisplay::displayText(*grabbedFrame, 20, 20, std::string("Click to exit..."), vpColor::red);
vpDisplay::flush(*grabbedFrame);
}
} while (captureRunning);
qtGrabber->stopAcquisition();
if (displayInit) {
delete display;
}
return 0;
}
#else
int main()
{
std::cout << "You should intall Qt5 (with wigdets and network modules), and display X to run this tutorial"
<< std::endl;
return 0;
}
#endif
Specific class to grab post-scan frames from the ultrasound station on the network.
usFrameGrabbedInfo< usImagePostScan2D< unsigned char > > * acquire()
void setPostScanWidth(int postScanWidth)
void setPostScanHeigh(int postScanHeigh)
void setPostScanMode(bool postScanMode)
void setImageDepth(int imageDepth)

Some details about this code :

Next tutorial

You are now ready to see the next Tutorial: UsTK grabber tutorial for ultrasonix station with computation of confidence map of the image.