ROIFilter: Add filter to only preserve ROI regions
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 .)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user