This constructor initializes the array with a constant value:
        Image(const int width, const int height, const ElementT initVal):
            width(width),
            height(height),
            image_data(width * height)
        {
            this->image_data = recursive_transform<1>(this->image_data, [initVal](ElementT element) { return initVal; });
            return;
        }
 Use the std::vector constructor for this:
        Image(const int width, const int height, const ElementT initVal):
            width(width),
            height(height),
            image_data(width * height, initVal) {}
 If you further add a default value to the last parameter (const ElementT initVal = {}) then you don't need the previous constructor (Image(const size_t width, const size_t height)).
        Image(const std::vector<ElementT>& input, size_t newWidth, size_t newHeight)
        {
            this->width = newWidth;
            this->height = newHeight;
            this->image_data = recursive_transform<1>(input, [](ElementT element) { return element; });   //  Deep copy
        }
 This constructor  be easily implemented in terms of std::copy. You do need to add a test here to verify that the input array has the right number of elements considering newWidth and newHeight.
 The implementation of at doesn't check bounds. I would suggest adding assert statements for bounds, to catch bugs in debug mode. A release build would then not test bounds.
 Functions here are declared out of order: functions use other functions that are declared later in the file. Somehow this works for you, I think because templates are instantiated when used. It would be better practice to declare normalDistribution1D before gaussianFigure2D, and gaussianFigure2D2 before gaussianFigure2D. Note that class methods can be declared in any order -- the compiler will first collect all member names (collect the full definition of the class) before attempting to compile each of the function bodies. The same is not true for free functions such as the ones we're talking about here.
 Again you have way too many headers included here. The
 This is very complex code in, which seems out of place with the relatively straight-forward C++ code elsewhere. With the changes suggested above, you don't need this file is not used in your program, as far as I can tellat all.