ROIFilter: Add filter to only preserve ROI regions

This commit is contained in:
2023-06-23 12:38:34 +02:00
parent dd20ac2acd
commit bbd0b6ef36
7 changed files with 220 additions and 2 deletions
+2 -1
View File
@@ -43,7 +43,8 @@ ADD_LIBRARY( CommonFunctions STATIC
grpcToJson.h jsonToGrpc.h to_fixed.h
DetectorGeometry.cpp DetectorGeometry.h
DetectorModuleGeometry.cpp DetectorModuleGeometry.h
DetectorSetup.h DetectorSetup.cpp ZeroCopyReturnValue.h Histogram.h DiffractionGeometry.h)
DetectorSetup.h DetectorSetup.cpp ZeroCopyReturnValue.h Histogram.h DiffractionGeometry.h
ROIFilter.h)
TARGET_LINK_LIBRARIES(CommonFunctions Compression FrameSerialize libzmq JFCalibration JFJochProtoBuf -lrt)
+7
View File
@@ -143,6 +143,13 @@ void FrameTransformation::ProcessModule(const int16_t *input, uint16_t module_nu
}
}
void FrameTransformation::ApplyROI(const ROIFilter &filter) {
if (pixel_depth == 2)
filter.Apply((int16_t *) precompression_buffer.data(), static_cast<int16_t>(INT16_MIN));
else
filter.Apply((int32_t *) precompression_buffer.data(), static_cast<int32_t>(INT32_MIN));
}
int16_t *FrameTransformation::GetPreview16BitImage() {
if (pixel_depth == 2)
return (int16_t *) precompression_buffer.data();
+2
View File
@@ -7,6 +7,7 @@
#include "DiffractionExperiment.h"
#include "../compression/JFJochCompressor.h"
#include "../jungfrau/JFConversion.h"
#include "ROIFilter.h"
class FrameTransformation {
const DiffractionExperiment& experiment;
@@ -31,6 +32,7 @@ public:
int data_stream);
void Pack(); // transfer summed image to converted coordinates, clear summation buffer
size_t SaveCompressedImage(void *output);
void ApplyROI(const ROIFilter &filter);
int16_t *GetPreview16BitImage();
};
+63
View File
@@ -0,0 +1,63 @@
// Copyright (2019-2023) Paul Scherrer Institute
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef JUNGFRAUJOCH_ROIFILTER_H
#define JUNGFRAUJOCH_ROIFILTER_H
#include <cstddef>
#include <cstdint>
#include <vector>
#include "JFJochException.h"
class ROIFilter {
size_t width, height;
std::vector<uint8_t> mask;
public:
ROIFilter(size_t in_width, size_t in_height, uint8_t fill_value = 0)
: width(in_width), height(in_height), mask (in_width * in_height, fill_value) {}
void SetRectangle(size_t x0, size_t y0, size_t in_width, size_t in_height, uint8_t fill_value = 1) {
if (y0 + in_height > height)
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size");
if (x0 + in_width > width)
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size");
for (size_t y = y0; y < y0 + in_height; y++) {
for (size_t x = x0; x < x0 + in_width; x++) {
mask[y * width + x] |= fill_value;
}
}
}
void ClearRectangle(size_t x0, size_t y0, size_t in_width, size_t in_height, uint8_t fill_value = 1) {
if (y0 + in_height > height)
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size");
if (x0 + in_width > width)
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size");
for (size_t y = y0; y < y0 + in_height; y++) {
for (size_t x = x0; x < x0 + in_width; x++) {
mask[y * width + x] &= ~fill_value;
}
}
}
template <class T>
void Apply(T* data, T fill_value) const {
for (size_t i = 0; i < mask.size(); i++) {
if (mask[i] == 0)
data[i] = fill_value;
}
}
template <class T>
void Apply(std::vector<T> &data, T fill_value) const {
if (data.size() != mask.size())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Mismatch in array size");
Apply(data.data(), fill_value);
}
};
#endif //JUNGFRAUJOCH_ROIFILTER_H
+1 -1
View File
@@ -25,7 +25,7 @@ ADD_EXECUTABLE(CatchTest
RadialIntegrationTest.cpp
StatusVectorTest.cpp ProcessRawPacketTest.cpp
CBORTest.cpp ../tests/stream2.h ../tests/stream2.c
JFConversionTest.cpp DetectorGeometryTest.cpp JFJochBrokerParserTest.cpp DetectorSetupTest.cpp DiffractionGeometryTest.cpp)
JFConversionTest.cpp DetectorGeometryTest.cpp JFJochBrokerParserTest.cpp DetectorSetupTest.cpp DiffractionGeometryTest.cpp ROIFilterTest.cpp)
target_link_libraries(CatchTest JFJochBroker JFJochReceiver JFJochWriter ImageAnalysis CommonFunctions HLSSimulation)
target_include_directories(CatchTest PRIVATE .)
+116
View File
@@ -168,6 +168,122 @@ TEST_CASE("FrameTransformation_Converted_bshuf_lz4" ,"") {
REQUIRE(input_1[(511+512)*1024 + 800] == output[CONVERTED_MODULE_SIZE * (nmodules - 2) + 1030 + 800 + 6]);
}
TEST_CASE("FrameTransformation_Converted_bshuf_lz4_roi" ,"") {
const uint16_t nmodules = 4;
const uint16_t ndatastreams = 2;
DiffractionExperiment experiment(DetectorGeometry(ndatastreams * nmodules, 2));
experiment.DataStreams(ndatastreams);
experiment.Mode(DetectorMode::Conversion).Compression(JFJochProtoBuf::BSHUF_LZ4);
FrameTransformation transformation(experiment);
ROIFilter filter(experiment.GetXPixelsNum(), experiment.GetYPixelsNum(), 0);
filter.SetRectangle(100, 20, 10, 10);
std::vector<int16_t> input_0(nmodules*RAW_MODULE_SIZE);
for (int i = 0; i < nmodules*RAW_MODULE_SIZE; i++)
input_0[i] = 50;
std::vector<int16_t> input_1(nmodules*RAW_MODULE_SIZE);
for (int i = 0; i < nmodules*RAW_MODULE_SIZE; i++)
input_1[i] = 50;
std::vector<char> output_compressed(experiment.GetMaxCompressedSize());
for (int i = 0; i < nmodules; i++) {
REQUIRE_NOTHROW(transformation.ProcessModule(input_0.data() + i * RAW_MODULE_SIZE, i, 0));
REQUIRE_NOTHROW(transformation.ProcessModule(input_1.data() + i * RAW_MODULE_SIZE, i, 1));
}
size_t compressed_size;
transformation.Pack();
transformation.ApplyROI(filter);
REQUIRE_NOTHROW(compressed_size = transformation.SaveCompressedImage(output_compressed.data()));
output_compressed.resize(compressed_size);
REQUIRE(bshuf_read_uint64_BE(output_compressed.data()) == experiment.GetPixelsNum() * experiment.GetPixelDepth());
REQUIRE(bshuf_read_uint32_BE(output_compressed.data()+8) == JFJochBitShuffleCompressor::DefaultBlockSize * experiment.GetPixelDepth());
std::vector<int16_t> output;
REQUIRE_NOTHROW(JFJochDecompress(output, experiment.GetCompressionAlgorithmEnum(), output_compressed,
experiment.GetPixelsNum()));
size_t diff = 0;
for (int y = 0; y < experiment.GetYPixelsNum(); y++) {
for (int x = 0; x < experiment.GetXPixelsNum(); x++) {
if ((y >= 20 ) && (y < 30) && (x >= 100) && (x < 110)) {
if (output[y * experiment.GetXPixelsNum() + x] != 50)
diff++;
} else {
if (output[y * experiment.GetXPixelsNum() + x] != INT16_MIN)
diff++;
}
}
}
REQUIRE(diff == 0);
}
TEST_CASE("FrameTransformation_Converted_bshuf_lz4_roi_summation" ,"") {
const uint16_t nmodules = 4;
const uint16_t ndatastreams = 2;
const uint16_t nframes = 4;
DiffractionExperiment experiment(DetectorGeometry(ndatastreams * nmodules, 2));
experiment.DataStreams(ndatastreams);
experiment.Mode(DetectorMode::Conversion).Compression(JFJochProtoBuf::BSHUF_LZ4).Summation(nframes);
FrameTransformation transformation(experiment);
ROIFilter filter(experiment.GetXPixelsNum(), experiment.GetYPixelsNum(), 0);
filter.SetRectangle(100, 20, 10, 10);
std::vector<int16_t> input_0(nmodules*RAW_MODULE_SIZE);
for (int i = 0; i < nmodules*RAW_MODULE_SIZE; i++)
input_0[i] = 50;
std::vector<int16_t> input_1(nmodules*RAW_MODULE_SIZE);
for (int i = 0; i < nmodules*RAW_MODULE_SIZE; i++)
input_1[i] = 50;
std::vector<char> output_compressed(experiment.GetMaxCompressedSize());
for (int f = 0; f < nframes; f++) {
for (int i = 0; i < nmodules; i++) {
REQUIRE_NOTHROW(transformation.ProcessModule(input_0.data() + i * RAW_MODULE_SIZE, i, 0));
REQUIRE_NOTHROW(transformation.ProcessModule(input_1.data() + i * RAW_MODULE_SIZE, i, 1));
}
}
size_t compressed_size;
transformation.Pack();
transformation.ApplyROI(filter);
REQUIRE_NOTHROW(compressed_size = transformation.SaveCompressedImage(output_compressed.data()));
output_compressed.resize(compressed_size);
REQUIRE(bshuf_read_uint64_BE(output_compressed.data()) == experiment.GetPixelsNum() * experiment.GetPixelDepth());
REQUIRE(bshuf_read_uint32_BE(output_compressed.data()+8) == JFJochBitShuffleCompressor::DefaultBlockSize * experiment.GetPixelDepth());
std::vector<int32_t> output;
REQUIRE_NOTHROW(JFJochDecompress(output, experiment.GetCompressionAlgorithmEnum(), output_compressed,
experiment.GetPixelsNum()));
size_t diff = 0;
for (int y = 0; y < experiment.GetYPixelsNum(); y++) {
for (int x = 0; x < experiment.GetXPixelsNum(); x++) {
if ((y >= 20 ) && (y < 30) && (x >= 100) && (x < 110)) {
if (output[y * experiment.GetXPixelsNum() + x] != nframes * 50)
diff++;
} else {
if (output[y * experiment.GetXPixelsNum() + x] != INT32_MIN)
diff++;
}
}
}
REQUIRE(diff == 0);
}
TEST_CASE("FrameTransformation_Converted_bshuf_zstd" ,"") {
const uint16_t nmodules = 4;
const uint16_t ndatastreams = 2;
+29
View File
@@ -0,0 +1,29 @@
// Copyright (2019-2022) Paul Scherrer Institute
// SPDX-License-Identifier: GPL-3.0-or-later
#include <catch2/catch.hpp>
#include "../common/ROIFilter.h"
TEST_CASE("ROIFilter") {
size_t width = 4;
size_t height = 5;
std::vector<uint32_t> v(width * height, 1);
ROIFilter filter(width, height);
filter.SetRectangle(1, 1, 2, 3);
filter.Apply(v, (uint32_t) 55);
REQUIRE(v[0] == 55);
REQUIRE(v[2] == 55);
REQUIRE(v[width * 1 + 0] == 55);
REQUIRE(v[width * 1 + 1] == 1);
REQUIRE(v[width * 1 + 2] == 1);
REQUIRE(v[width * 1 + 3] == 55);
REQUIRE(v[width * 3 + 2] == 1);
REQUIRE(v[width * 4 + 2] == 55);
}