Skip to content

Commit

Permalink
Added possibility of converting from dB to grayscale in EnvelopeAndLo…
Browse files Browse the repository at this point in the history
…gCompressor and in UFFStreamer when not scan converting
  • Loading branch information
smistad committed Aug 8, 2023
1 parent 7405099 commit b0abd44
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 13 deletions.
17 changes: 17 additions & 0 deletions source/FAST/Algorithms/Ultrasound/EnvelopeAndLogCompressor.cl
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,20 @@ __kernel void normalizeEnvelope(

write_imagef(output, pos, read_imagef(input, sampler, pos).x - maxdB);
}

__kernel void normalizeEnvelopeToGrayscale(
__read_only image2d_t input,
__write_only image2d_t output,
__private float maxdB,
__private float gain,
__private float dynamicRange
) {
const int2 pos = {get_global_id(0), get_global_id(1)};

float dBPixel = read_imagef(input, sampler, pos).x - maxdB;
float img_sc_reject = dBPixel + gain;
img_sc_reject = (img_sc_reject < -dynamicRange) ? -dynamicRange : img_sc_reject; //Reject everything below dynamic range
img_sc_reject = (img_sc_reject > 0) ? 0 : img_sc_reject; // Everything above 0 dB should be saturated
uchar img_gray_scale = round(255*(img_sc_reject+dynamicRange)/dynamicRange);
write_imageui(output, pos, img_gray_scale);
}
45 changes: 38 additions & 7 deletions source/FAST/Algorithms/Ultrasound/EnvelopeAndLogCompressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

namespace fast {

EnvelopeAndLogCompressor::EnvelopeAndLogCompressor() {
EnvelopeAndLogCompressor::EnvelopeAndLogCompressor(bool convertToGrayscale, float gain, float dynamicRange) {
createInputPort(0, "");
createOutputPort(0, "");
createOpenCLProgram(Config::getKernelSourcePath() + "Algorithms/Ultrasound/EnvelopeAndLogCompressor.cl");
setConvertToGrayscale(convertToGrayscale);
setGain(gain);
setDynamicRange(dynamicRange);
}

void EnvelopeAndLogCompressor::execute() {
Expand Down Expand Up @@ -39,13 +42,26 @@ void EnvelopeAndLogCompressor::execute() {

{
auto outputAccess = output->getOpenCLImageAccess(ACCESS_READ, device);
auto normalizedOutput = Image::createFromImage(output);
auto normalizedOutputAccess = normalizedOutput->getOpenCLImageAccess(ACCESS_READ_WRITE, device);

cl::Kernel kernel(getOpenCLProgram(device), "normalizeEnvelope");
kernel.setArg(0, *outputAccess->get2DImage());
kernel.setArg(1, *normalizedOutputAccess->get2DImage());
kernel.setArg(2, m_maxValue);
cl::Kernel kernel;
Image::pointer normalizedOutput;
if(m_convertToGrayscale) {
normalizedOutput = Image::create(output->getSize(), TYPE_UINT8, 1);
auto normalizedOutputAccess = normalizedOutput->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
kernel = cl::Kernel(getOpenCLProgram(device), "normalizeEnvelopeToGrayscale");
kernel.setArg(0, *outputAccess->get2DImage());
kernel.setArg(1, *normalizedOutputAccess->get2DImage());
kernel.setArg(2, m_maxValue);
kernel.setArg(3, m_gain);
kernel.setArg(4, m_dynamicRange);
} else {
normalizedOutput = Image::createFromImage(output);
auto normalizedOutputAccess = normalizedOutput->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
kernel = cl::Kernel(getOpenCLProgram(device), "normalizeEnvelope");
kernel.setArg(0, *outputAccess->get2DImage());
kernel.setArg(1, *normalizedOutputAccess->get2DImage());
kernel.setArg(2, m_maxValue);
}

device->getCommandQueue().enqueueNDRangeKernel(
kernel,
Expand All @@ -58,4 +74,19 @@ void EnvelopeAndLogCompressor::execute() {

}

void EnvelopeAndLogCompressor::setConvertToGrayscale(bool convert) {
m_convertToGrayscale = convert;
setModified(true);
}

void EnvelopeAndLogCompressor::setGain(float gain) {
m_gain = gain;
setModified(true);
}

void EnvelopeAndLogCompressor::setDynamicRange(float dynamicRange) {
m_dynamicRange = dynamicRange;
setModified(true);
}

}
15 changes: 13 additions & 2 deletions source/FAST/Algorithms/Ultrasound/EnvelopeAndLogCompressor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,29 @@ namespace fast {
* - 0: Image 2 channels float (IQ data)
*
* Outputs:
* - 0: Image 1 channel float (beamspace data in dB)
* - 0: Image 1 channel float (beamspace data in dB) if convertToGrayscale == false,
* or Image 1 channel uint8 (beamspace data in grayscale) if convertToGrayscale == true
*
* @ingroup ultrasound
*/
class FAST_EXPORT EnvelopeAndLogCompressor : public ProcessObject {
FAST_PROCESS_OBJECT(EnvelopeAndLogCompressor)
public:
FAST_CONSTRUCTOR(EnvelopeAndLogCompressor)
FAST_CONSTRUCTOR(EnvelopeAndLogCompressor,
bool, convertToGrayscale, = false,
float, gain, = 0,
float, dynamicRange, = 60
)
void setConvertToGrayscale(bool convert);
void setGain(float gain);
void setDynamicRange(float dynamicRange);
private:
void execute() override;

float m_maxValue;
bool m_maxInitialize = false;
bool m_convertToGrayscale = false;
float m_gain = 0;
float m_dynamicRange = 60;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace fast {
* @brief Automatic cropping of an ultrasound scanner image
*
* When streaming or storing images/video on ultrasound scanner, the menu and a lot of information around the actual
* ultrasound image is included.
* ultrasound image is often included.
* This algorithm tries to extract the ultrasound image from the entire scanner GUI image using two thresholds.
* It does this by counting the number of non-zero pixels in every row and column of the image.
* Works best on linear array images.
Expand Down
6 changes: 4 additions & 2 deletions source/FAST/Streamers/UFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ UFFStreamer::UFFStreamer() {
createBooleanAttribute("loop", "Loop", "Loop recordin", false);
}

UFFStreamer::UFFStreamer(std::string filename, bool loop, uint framerate, float gain, float dynamicRange, int width, int height, bool scanConvert) {
m_envelopeAndLogCompressor = EnvelopeAndLogCompressor::create();
UFFStreamer::UFFStreamer(std::string filename, bool loop, uint framerate, float gain, float dynamicRange, int width, int height, bool scanConvert, bool convertToGrayscale) {
m_envelopeAndLogCompressor = EnvelopeAndLogCompressor::create(convertToGrayscale, gain, dynamicRange);
m_scanConverter = ScanConverter::create(width, height)
->connect(m_envelopeAndLogCompressor);
createOutputPort(0, "Image");
Expand Down Expand Up @@ -535,11 +535,13 @@ int UFFStreamer::getNrOfFrames() {
}

void UFFStreamer::setGain(float gain) {
m_envelopeAndLogCompressor->setGain(gain);
m_scanConverter->setGain(gain);
setModified(true);
}

void UFFStreamer::setDynamicRange(float dynamicRange) {
m_envelopeAndLogCompressor->setDynamicRange(dynamicRange);
m_scanConverter->setDynamicRange(dynamicRange);
setModified(true);
}
Expand Down
5 changes: 4 additions & 1 deletion source/FAST/Streamers/UFFStreamer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class FAST_EXPORT UFFStreamer : public RandomAccessStreamer {
* @param scanConversionWidth Width of scan converted image
* @param scanConversionHeight Height of scan converted image
* @param doScanConversion Whether to perform scan conversion or not
* @param toGrayscale Whether to convert from dB to grayscale using the gain and dynamicRange if scan conversion is OFF.
* When scan conversion is ON, the image is always converted to grayscale.
* @return instance
*/
FAST_CONSTRUCTOR(UFFStreamer,
Expand All @@ -53,7 +55,8 @@ class FAST_EXPORT UFFStreamer : public RandomAccessStreamer {
float, dynamicRange, = 60,
int, scanConversionWidth, = 1024,
int, scanConversionHeight, = 1024,
bool, doScanConversion, = true
bool, doScanConversion, = true,
bool, convertToGrayscale, = true
);
void setFilename(std::string filename);
void setGain(float gain);
Expand Down

0 comments on commit b0abd44

Please sign in to comment.