This project is a work in progress to gather ND array related features
of EleFits' Raster
-- an extensible ND data storage class with pixel-wise operations --
and PhiFun's operations -- e.g. Fourier transforms, linear filtering, and interpolation.
The target is a header-only library focused on ease of use, extensibility, and which interfaces seamlessly with the standard C++ library. At some point, the ND array implementation of EleFits should be droped in favor of Linx.
The image processing feature set is expected to grow steadily on demand. Currently supported operations are:
+
, *
, exp()
, apply()
...) on Raster
s and on Raster
regions;GaussianNoise
, PoissonNoise
, ImpulseNoise
...);DftPlan
class;SimpleFilter
, FilterSeq
and FilterAgg
classes;Nearest
, Linear
, Constant
...);The Linx library is licensed under Apache-2.0. Some executables including some unit tests are licensed under GPL-3.0-or-later.
The simplest way to use Linx, which is a header-only library, is to copy the deepest Linx
folder into your include directory:
git clone https://github.com/kabasset/Linx.git
cp -r Linx/Linx/Linx /usr/include/
The following libraries offer features similar to Linx. Most of the libraries which support ND arrays are focused on linear algebra, while most image processing libraries limit the number of axes. ITK (and SimpleITK) is the notable exception. Linx aims at being simpler, less verbose and more extensible, although with a more limited feature set.
Here is a quick comparison of ITK, CImg, Linx and NumPy/SciKit for the following use case: read an image, dilate it with an L2-ball structuring element, and write the output.
ITK:
using T = unsigned char;
static constexpr unsigned int N = 2;
using Image = itk::Image<T, N>;
auto raw = itk::ReadImage<ImageType>(input);
using StructuringElement = itk::FlatStructuringElement<N>;
StructuringElement::RadiusType strelRadius;
strelRadius.Fill(radius);
StructuringElementType ball = StructuringElement::Ball(strelRadius);
using GrayscaleDilateImageFilter = itk::GrayscaleDilateImageFilter<Image, Image, StructuringElement>;
GrayscaleDilateImageFilter::Pointer dilateFilter = GrayscaleDilateImageFilter::New();
dilateFilter->SetInput(input);
dilateFilter->SetKernel(ball);
itk::WriteImage(dilateFilter->GetOutput(), output);
CImg (limited to N <= 3):
using T = unsigned char;
auto raw = cimg::CImg<T>().load(input);
cimg::CImg<bool> ball(2 * radius + 1, 2 * radius + 1, 1, 1, false);
bool color[1] = {true};
ball.draw_circle(radius, radius, radius, color);
auto dilated = raw.get_dilate(ball, 0, true);
dilated.write(output);
Linx:
using T = unsigned char;
static constexpr Linx::Index N = 2;
auto raw = Linx::read<T, N>(input);
auto ball = Linx::Mask<N>::ball<2>(radius);
auto dilated = dilation<T>(ball) * extrapolation(raw);
Linx::write(dilated, output);
NumPy/SciKit:
raw = np.load(input)
ball = skimage.morphology.disk(radius)
dilated = skimage.morphology.dilation(raw, ball)
np.save(output, dilated)