diff --git a/Modules/PhotoacousticsAlgorithms/source/utils/mitkBeamformingUtils.cpp b/Modules/PhotoacousticsAlgorithms/source/utils/mitkBeamformingUtils.cpp index f6b1851975..7ffc75415f 100644 --- a/Modules/PhotoacousticsAlgorithms/source/utils/mitkBeamformingUtils.cpp +++ b/Modules/PhotoacousticsAlgorithms/source/utils/mitkBeamformingUtils.cpp @@ -1,450 +1,439 @@ /*=================================================================== mitkPhotoacousticBeamformingFilter The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkProperties.h" #include "mitkImageReadAccessor.h" #include #include #include #include #include #include "mitkImageCast.h" #include "mitkBeamformingUtils.h" mitk::BeamformingUtils::BeamformingUtils() { } mitk::BeamformingUtils::~BeamformingUtils() { } float* mitk::BeamformingUtils::VonHannFunction(int samples) { float* ApodWindow = new float[samples]; for (int n = 0; n < samples; ++n) { ApodWindow[n] = (1 - cos(2 * itk::Math::pi * n / (samples - 1))) / 2; } return ApodWindow; } float* mitk::BeamformingUtils::HammFunction(int samples) { float* ApodWindow = new float[samples]; for (int n = 0; n < samples; ++n) { ApodWindow[n] = 0.54 - 0.46*cos(2 * itk::Math::pi*n / (samples - 1)); } return ApodWindow; } float* mitk::BeamformingUtils::BoxFunction(int samples) { float* ApodWindow = new float[samples]; for (int n = 0; n < samples; ++n) { ApodWindow[n] = 1; } return ApodWindow; } unsigned short* mitk::BeamformingUtils::MinMaxLines(const mitk::BeamformingSettings::Pointer config) { int outputL = (int)config->GetReconstructionLines(); int outputS = (int)config->GetSamplesPerLine(); unsigned short* dDest = new unsigned short[outputL * outputS * 2]; int inputL = (int)config->GetInputDim()[0]; float horizontalExtent = config->GetHorizontalExtent(); float verticalExtent = config->GetReconstructionDepth(); float partMult = (tan(config->GetAngle() / 360 * 2 * itk::Math::pi) * ((config->GetSpeedOfSound() * config->GetTimeSpacing())) / (config->GetPitchInMeters() * config->GetTransducerElements())) * inputL; float totalSamples_i = (float)(config->GetReconstructionDepth()) / (float)(config->GetSpeedOfSound() * config->GetTimeSpacing()); totalSamples_i = totalSamples_i <= config->GetInputDim()[1] ? totalSamples_i : config->GetInputDim()[1]; if ((int)config->GetGeometry() == 0) // if this is raw data from a linear probe geometry { for (int x = 0; x < outputL; ++x) { for (int y = 0; y < outputS; ++y) { float l_i = (float)x / outputL * inputL; float s_i = (float)y / (float)outputS * totalSamples_i; float part = partMult * s_i; if (part < 1) part = 1; unsigned short maxLine = std::min((l_i + part) + 1, (float)inputL); unsigned short minLine = std::max((l_i - part), 0.0f); dDest[y * 2 * outputL + 2 * x] = (unsigned short)minLine; //minLine dDest[y * 2 * outputL + 2 * x + 1] = (unsigned short)maxLine; //maxLine } } } else // if this is *not* raw data from a linear probe geometry (currently meaning its a concave geometry) { float probeRadius = config->GetProbeRadius(); float* elementHeights = config->GetElementHeights(); float* elementPositions = config->GetElementPositions(); - float cos_deg = std::cos(config->GetAngle() / 2.f / 360 * 2 * itk::Math::pi); - - float cos = 0; - float a = 0; - float d = 0; - + float sin_deg = std::sin(config->GetAngle() / 360 * 2 * itk::Math::pi); + + //float cos = 0; + //float a = 0; + //float d = 0; + //MITK_INFO << "probeRadius" < cos_deg) + float x_sensor_pos = elementPositions[l_s]; + float y_sensor_pos = elementHeights[l_s]; + + float distance_sensor_target = sqrt((x_cm - x_sensor_pos)*(x_cm - x_sensor_pos) + + (y_cm - y_sensor_pos)*(y_cm - y_sensor_pos)); + + float center_to_sensor_a = y_sensor_pos - y_center_pos; + float center_to_sensor_b = x_center_pos - x_sensor_pos; + float center_to_sensor_c = -(center_to_sensor_a * x_center_pos + center_to_sensor_b * y_center_pos); + float distance_to_sensor_direction = std::fabs((center_to_sensor_a * x_cm + + center_to_sensor_b * y_cm + + center_to_sensor_c)) / + (sqrt(center_to_sensor_a*center_to_sensor_a + center_to_sensor_b*center_to_sensor_b)); + + //a = sqrt((probeRadius - sample_position)*(probeRadius - sample_position) + // + (line_position - horizontalExtent / 2)*(line_position - horizontalExtent / 2)); + //d = sqrt((sample_position - elementHeights[l_s])*(sample_position - elementHeights[l_s]) + // + (line_position - elementPositions[l_s])*(line_position - elementPositions[l_s])); + //cos = std::abs((d*d + probeRadius*probeRadius - a*a) / (2 * probeRadius * d)); + //MITK_INFO << "distance_to_sensor_direction" < cos_deg) - { - minLine = l_s - 8; - if (minLine < 0) - minLine = 0; - break; + MITK_INFO << "x_sensor_pos" << x_sensor_pos; + MITK_INFO << "y_sensor_pos" << y_sensor_pos; + MITK_INFO << "distance_sensor_target" << distance_sensor_target; + MITK_INFO << "distance_to_sensor_direction" << distance_to_sensor_direction; + foo=1; } - } - for (int l_s = minLine; l_s < inputL; l_s += 1) - { - a = sqrt((probeRadius - s_p)*(probeRadius - s_p) + (l_p - horizontalExtent / 2)*(l_p - horizontalExtent / 2)); - d = sqrt((s_p - elementHeights[l_s])*(s_p - elementHeights[l_s]) + (l_p - elementPositions[l_s])*(l_p - elementPositions[l_s])); - cos = (d*d + probeRadius * probeRadius - a * a) / (2 * probeRadius*d); - - if (cos > cos_deg) + if (distance_to_sensor_direction < sin_deg*distance_sensor_target) { minLine = l_s; break; } } - for (int l_s = inputL; l_s >= 0; l_s -= 32) + for (int l_s = maxLine; l_s >= minLine; l_s -= 1) { - a = sqrt((probeRadius - s_p)*(probeRadius - s_p) + (l_p - horizontalExtent / 2)*(l_p - horizontalExtent / 2)); - d = sqrt((s_p - elementHeights[l_s])*(s_p - elementHeights[l_s]) + (l_p - elementPositions[l_s])*(l_p - elementPositions[l_s])); - cos = (d*d + probeRadius * probeRadius - a * a) / (2 * probeRadius*d); - cos = 0; + float x_sensor_pos = elementPositions[l_s]; + float y_sensor_pos = elementHeights[l_s]; - if (cos > cos_deg) - { - maxLine = l_s + 32; - if (maxLine > inputL) - minLine = inputL; - break; - } - } - for (int l_s = maxLine; l_s >= 0; l_s -= 8) - { - a = sqrt((probeRadius - s_p)*(probeRadius - s_p) + (l_p - horizontalExtent / 2)*(l_p - horizontalExtent / 2)); - d = sqrt((s_p - elementHeights[l_s])*(s_p - elementHeights[l_s]) + (l_p - elementPositions[l_s])*(l_p - elementPositions[l_s])); - cos = (d*d + probeRadius * probeRadius - a * a) / (2 * probeRadius*d); - cos = 0; + float distance_sensor_target = sqrt((x_cm - x_sensor_pos)*(x_cm - x_sensor_pos) + + (y_cm - y_sensor_pos)*(y_cm - y_sensor_pos)); - if (cos > cos_deg) - { - maxLine = l_s + 8; - if (maxLine > inputL) - minLine = inputL; - break; - } - } - for (int l_s = maxLine; l_s >= 0; l_s -= 1) - { - a = sqrt((probeRadius - s_p)*(probeRadius - s_p) + (l_p - horizontalExtent / 2)*(l_p - horizontalExtent / 2)); - d = sqrt((s_p - elementHeights[l_s])*(s_p - elementHeights[l_s]) + (l_p - elementPositions[l_s])*(l_p - elementPositions[l_s])); - cos = (d*d + probeRadius * probeRadius - a * a) / (2 * probeRadius*d); - cos = 0; + float center_pos_x = horizontalExtent / 2.0; + float center_pos_y = probeRadius; + float center_to_sensor_a = y_sensor_pos - center_pos_y; + float center_to_sensor_b = center_pos_x - x_sensor_pos; + float center_to_sensor_c = -(center_to_sensor_a * center_pos_x + center_to_sensor_b * center_pos_y); + float distance_to_sensor_direction = std::fabs((center_to_sensor_a * x_cm + center_to_sensor_b * y_cm + center_to_sensor_c)) / + (sqrt(center_to_sensor_a*center_to_sensor_a + center_to_sensor_b*center_to_sensor_b)); + + + //a = sqrt((probeRadius - sample_position)*(probeRadius - sample_position) + (line_position - horizontalExtent / 2)*(line_position - horizontalExtent / 2)); + //d = sqrt((sample_position - elementHeights[l_s])*(sample_position - elementHeights[l_s]) + (line_position - elementPositions[l_s])*(line_position - elementPositions[l_s])); + //cos = (d*d + probeRadius * probeRadius - a * a) / (2 * probeRadius*d); + //cos = 0; - if (cos > cos_deg) + if (distance_to_sensor_direction < sin_deg*distance_sensor_target) { maxLine = l_s; break; } } dDest[y * 2 * outputL + 2 * x] = (unsigned short)minLine; //minLine dDest[y * 2 * outputL + 2 * x + 1] = (unsigned short)maxLine; //maxLine } } } return dDest; } void mitk::BeamformingUtils::DASSphericalLine( float* input, float* output, float inputDim[2], float outputDim[2], const short& line, const mitk::BeamformingSettings::Pointer config) { const float* apodisation = config->GetApodizationFunction(); const short apodArraySize = config->GetApodizationArraySize(); const float* elementHeights = config->GetElementHeights(); const float* elementPositions = config->GetElementPositions(); float& inputS = inputDim[1]; float& inputL = inputDim[0]; float& outputS = outputDim[1]; float& outputL = outputDim[0]; short AddSample = 0; short maxLine = 0; short minLine = 0; float l_p = 0; float s_i = 0; float apod_mult = 1; short usedLines = (maxLine - minLine); float totalSamples_i = (float)(config->GetReconstructionDepth()) / (float)(config->GetSpeedOfSound() * config->GetTimeSpacing()); totalSamples_i = totalSamples_i <= inputS ? totalSamples_i : inputS; l_p = (float)line / outputL * config->GetHorizontalExtent(); for (short sample = 0; sample < outputS; ++sample) { s_i = (float)sample / outputS * totalSamples_i; minLine = config->GetMinMaxLines()[2*sample*(short)outputL + 2*line]; maxLine = config->GetMinMaxLines()[2*sample*(short)outputL + 2*line + 1]; usedLines = (maxLine - minLine); apod_mult = (float)apodArraySize / (float)usedLines; for (short l_s = minLine; l_s < maxLine; ++l_s) { AddSample = (int)sqrt( pow(s_i-elementHeights[l_s]/(config->GetSpeedOfSound()*config->GetTimeSpacing()), 2) + pow((1 / (config->GetTimeSpacing()*config->GetSpeedOfSound())) * (l_p - elementPositions[l_s]), 2) ) + (1 - config->GetIsPhotoacousticImage())*s_i; if (AddSample < inputS && AddSample >= 0) output[sample*(short)outputL + line] += input[l_s + AddSample*(short)inputL] * apodisation[(short)((l_s - minLine)*apod_mult)]; else --usedLines; } output[sample*(short)outputL + line] = output[sample*(short)outputL + line] / usedLines; } } void mitk::BeamformingUtils::DMASSphericalLine( float* input, float* output, float inputDim[2], float outputDim[2], const short& line, const mitk::BeamformingSettings::Pointer config) { const float* apodisation = config->GetApodizationFunction(); const short apodArraySize = config->GetApodizationArraySize(); const float* elementHeights = config->GetElementHeights(); const float* elementPositions = config->GetElementPositions(); float& inputS = inputDim[1]; float& inputL = inputDim[0]; float& outputS = outputDim[1]; float& outputL = outputDim[0]; short maxLine = 0; short minLine = 0; float l_p = 0; float s_i = 0; float apod_mult = 1; float mult = 0; short usedLines = (maxLine - minLine); float totalSamples_i = (float)(config->GetReconstructionDepth()) / (float)(config->GetSpeedOfSound() * config->GetTimeSpacing()); totalSamples_i = totalSamples_i <= inputS ? totalSamples_i : inputS; l_p = (float)line / outputL * config->GetHorizontalExtent(); for (short sample = 0; sample < outputS; ++sample) { s_i = (float)sample / outputS * totalSamples_i; minLine = config->GetMinMaxLines()[2 * sample*(short)outputL + 2 * line]; maxLine = config->GetMinMaxLines()[2 * sample*(short)outputL + 2 * line + 1]; usedLines = (maxLine - minLine); apod_mult = (float)apodArraySize / (float)usedLines; //calculate the AddSamples beforehand to save some time short* AddSample = new short[maxLine - minLine]; for (short l_s = 0; l_s < maxLine - minLine; ++l_s) { AddSample[l_s] = (int)sqrt( pow(s_i - elementHeights[l_s + minLine] / (config->GetSpeedOfSound()*config->GetTimeSpacing()), 2) + pow((1 / (config->GetTimeSpacing()*config->GetSpeedOfSound())) * (l_p - elementPositions[l_s + minLine]), 2) ) + (1 - config->GetIsPhotoacousticImage())*s_i; } float s_1 = 0; float s_2 = 0; for (short l_s1 = minLine; l_s1 < maxLine - 1; ++l_s1) { if (AddSample[l_s1 - minLine] < inputS && AddSample[l_s1 - minLine] >= 0) { for (short l_s2 = l_s1 + 1; l_s2 < maxLine; ++l_s2) { if (AddSample[l_s2 - minLine] < inputS && AddSample[l_s2 - minLine] >= 0) { s_2 = input[l_s2 + AddSample[l_s2 - minLine] * (short)inputL]; s_1 = input[l_s1 + AddSample[l_s1 - minLine] * (short)inputL]; mult = s_2 * apodisation[(int)((l_s2 - minLine)*apod_mult)] * s_1 * apodisation[(int)((l_s1 - minLine)*apod_mult)]; output[sample*(short)outputL + line] += sqrt(fabs(mult)) * ((mult > 0) - (mult < 0)); } } } else --usedLines; } output[sample*(short)outputL + line] = output[sample*(short)outputL + line] / (float)(pow(usedLines, 2) - (usedLines - 1)); delete[] AddSample; } } void mitk::BeamformingUtils::sDMASSphericalLine( float* input, float* output, float inputDim[2], float outputDim[2], const short& line, const mitk::BeamformingSettings::Pointer config) { const float* apodisation = config->GetApodizationFunction(); const short apodArraySize = config->GetApodizationArraySize(); const float* elementHeights = config->GetElementHeights(); const float* elementPositions = config->GetElementPositions(); float& inputS = inputDim[1]; float& inputL = inputDim[0]; float& outputS = outputDim[1]; float& outputL = outputDim[0]; short maxLine = 0; short minLine = 0; float l_p = 0; float s_i = 0; float apod_mult = 1; float mult = 0; short usedLines = (maxLine - minLine); float totalSamples_i = (float)(config->GetReconstructionDepth()) / (float)(config->GetSpeedOfSound() * config->GetTimeSpacing()); totalSamples_i = totalSamples_i <= inputS ? totalSamples_i : inputS; l_p = (float)line / outputL * config->GetHorizontalExtent(); for (short sample = 0; sample < outputS; ++sample) { s_i = (float)sample / outputS * totalSamples_i; minLine = config->GetMinMaxLines()[2 * sample*(short)outputL + 2 * line]; maxLine = config->GetMinMaxLines()[2 * sample*(short)outputL + 2 * line + 1]; usedLines = (maxLine - minLine); apod_mult = (float)apodArraySize / (float)usedLines; //calculate the AddSamples beforehand to save some time short* AddSample = new short[maxLine - minLine]; for (short l_s = 0; l_s < maxLine - minLine; ++l_s) { AddSample[l_s] = (int)sqrt( pow(s_i - elementHeights[l_s + minLine] / (config->GetSpeedOfSound()*config->GetTimeSpacing()), 2) + pow((1 / (config->GetTimeSpacing()*config->GetSpeedOfSound())) * (l_p - elementPositions[l_s + minLine]), 2) ) + (1 - config->GetIsPhotoacousticImage())*s_i; } float s_1 = 0; float s_2 = 0; float sign = 0; for (short l_s1 = minLine; l_s1 < maxLine - 1; ++l_s1) { if (AddSample[l_s1 - minLine] < inputS && AddSample[l_s1 - minLine] >= 0) { s_1 = input[l_s1 + AddSample[l_s1 - minLine] * (short)inputL]; sign += s_1; for (short l_s2 = l_s1 + 1; l_s2 < maxLine; ++l_s2) { if (AddSample[l_s2 - minLine] < inputS && AddSample[l_s2 - minLine] >= 0) { s_2 = input[l_s2 + AddSample[l_s2 - minLine] * (short)inputL]; mult = s_2 * apodisation[(int)((l_s2 - minLine)*apod_mult)] * s_1 * apodisation[(int)((l_s1 - minLine)*apod_mult)]; output[sample*(short)outputL + line] += sqrt(fabs(mult)) * ((mult > 0) - (mult < 0)); } } } else --usedLines; } output[sample*(short)outputL + line] = output[sample*(short)outputL + line] / (float)(pow(usedLines, 2) - (usedLines - 1)) * ((sign > 0) - (sign < 0)); delete[] AddSample; } } diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.imageprocessing/src/internal/PAImageProcessingControls.ui b/Plugins/org.mitk.gui.qt.photoacoustics.imageprocessing/src/internal/PAImageProcessingControls.ui index 28a016d489..6ec9decbac 100644 --- a/Plugins/org.mitk.gui.qt.photoacoustics.imageprocessing/src/internal/PAImageProcessingControls.ui +++ b/Plugins/org.mitk.gui.qt.photoacoustics.imageprocessing/src/internal/PAImageProcessingControls.ui @@ -1,1317 +1,1317 @@ PAImageProcessingControls 0 0 601 890 0 0 QmitkTemplate 0 0 - 0 + 1 0 0 - 583 - 732 + 98 + 28 Bandpass 10 0 301 529 QLayout::SetDefaultConstraint 0 0 0 3 0.010000000000000 200.000000000000000 0.100000000000000 8.000000000000000 [MHz] f High Pass [MHz] f Low Pass 0 0 3 200.000000000000000 0.100000000000000 0.100000000000000 1 200.000000000000000 3000.000000000000000 5.000000000000000 1500.000000000000000 [m/s] Speed of Sound 1.000000000000000 0.100000000000000 0.500000000000000 <html><head/><body><p><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;">At </span><span style=" font-family:'sans-serif'; font-size:14px; font-style:italic; color:#222222; background-color:#ffffff;">α</span><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;"> = 0 it's rectangular, at </span><span style=" font-family:'sans-serif'; font-size:14px; font-style:italic; color:#222222; background-color:#ffffff;">α</span><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;"> = 1 it's a Hann window. Both flanks can be set independently.</span></p></body></html> Tukey Window α High Pass 2 1.000000000000000 0.100000000000000 0.500000000000000 <html><head/><body><p><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;">At </span><span style=" font-family:'sans-serif'; font-size:14px; font-style:italic; color:#222222; background-color:#ffffff;">α</span><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;"> = 0 it's rectangular, at </span><span style=" font-family:'sans-serif'; font-size:14px; font-style:italic; color:#222222; background-color:#ffffff;">α</span><span style=" font-family:'sans-serif'; font-size:14px; color:#222222; background-color:#ffffff;"> = 1 it's a Hann window. Both flanks can be set independently.</span></p></body></html> Tukey Window α Low Pass 0 25 16777215 25 <html><head/><body><p><span style=" font-size:10pt; font-weight:600; color:#ff0000;">Select input data in datamanager!</span></p></body></html> Apply Bandpass <html><head/><body><p>If not checked, treat input as raw US/PA data with Y-axis as a time coordinate in microseconds</p></body></html> Assume Spatial Coordinates Qt::Vertical 20 40 0 0 583 732 Beamforming 10 0 - 301 + 306 661 5 0 0 PA Image US Image <html><head/><body><p>which type of image do you plan to reconstruct?</p></body></html> Raw Data Type 0 0 DAS DMAS sDMAS 0 0 Von Hann Hamming Box [mm] Transducer Pitch Apodization Function Beamforming Algorithm 0 0 3 0.010000000000000 9.000000000000000 0.050000000000000 0.340000000000000 Probe Geomentry 0 0 - 1 + 5 1.000000000000000 180.000000000000000 45.000000000000000 <html><head/><body><p>... of the transducer elements.</p></body></html> [°] Sensitive Angle [mm] Reconstruction Depth 4 300.000000000000000 0.100000000000000 60.000000000000000 Linear Linear Concave 2 - 0.010000000000000 + 0.000000000000000 - 399.990000000000009 + 999.990000000000009 40.000000000000000 [mm] Concave Probe Radius <html><head/><body><p>Some setups' hardware produces signal delays that need to be cropped out of the image before performing beamforming. To do this, select this box.</p></body></html> Consider Hardware Delay [µs] false 0.100000000000000 1.000000000000000 <html><head/><body><p>... from y-spacing in the selected raw data. If this is switched of &quot;Manual Scan Depth&quot; is used.</p></body></html> Automatic Get Depth true [mm] Manual Scan Depth <html><head/><body><p>Using GPU is recommended - It is so much faster.</p></body></html> Compute On GPU true 0 0 64 2048 128 512 0 0 2 2048 64 256 Reconstructed Lines 75 true Advanced Options 0 0 4 300.000000000000000 0.100000000000000 60.000000000000000 0 0 1 200.000000000000000 3000.000000000000000 5.000000000000000 1500.000000000000000 <html><head/><body><p>... Good default - change only if you know what you are doing.</p></body></html> Samples [m/s] Speed of Sound 0 0 256 16384 256 2048 <html><head/><body><p>Set automatically from selected raw data x-Geometry.</p></body></html> Transducer Elements 75 true 0 25 16777215 25 <html><head/><body><p><span style=" font-size:10pt; font-weight:600; color:#ff0000;">Select input data in datamanager!</span></p></body></html> true 0 0 100 0 Qt::Vertical 20 40 Apply Beamforming 0 0 - 583 - 732 + 98 + 28 Cropping 10 0 330 301 999999999 Left Bottom minimal beamformed slice First Slice 999999999 Right Select Slices Apply Crop Filer 0 25 16777215 25 <html><head/><body><p><span style=" font-size:10pt; font-weight:600; color:#ff0000;">Select input data in datamanager!</span></p></body></html> Top false 99999 Cut N Pixels from ... 999999999 1 0 999999999 0 false 99999 10 Maximal beamformed slice Last Slice Qt::Vertical 20 40 0 0 - 583 - 732 + 98 + 28 B-mode Generation 10 0 301 261 0 25 16777215 25 <html><head/><body><p><span style=" font-size:10pt; font-weight:600; color:#ff0000;">Select input data in datamanager!</span></p></body></html> Envelope Detection Envelope Detection Absolute Filter <html><head/><body><p>The image will still be oversampled after B-Mode generation. This default performs a sensible downsampling.</p></body></html> Resample Image after B-mode true 0 0 13 0 11 3 0.010000000000000 1.000000000000000 0.010000000000000 0.050000000000000 [mm] Resampled y-Spacing <html><head/><body><p>Adds a log() filter after the B-mode filter. Often used in US B-mode images.</p></body></html> Logarithmic Compression Use GPU 0 0 Do image processing Apply B-mode Filter Qt::Vertical 20 40 0 0 - 583 - 732 + 98 + 28 Legacy Batch Processing 10 0 309 231 300 100 <html><head/><body><p><span style=" font-weight:600;">Note:</span> This batch processing tool is depricated <br/>and is no longer tested. It is recommended to <br/>use the PA command line tool to process large <br/>amounts of files with consistent settings.</p></body></html> Bandpass true Crop true Save false Save false Save false Beamform true B-Mode true Save true Start Batch Processing Qt::Vertical 20 40