1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
#ifndef IMAGE_H
#define IMAGE_H
#include <cstring>
#include <cmath>
#include <complex>
#include <memory>
#include <aocommon/uvector.h>
template<typename NumT>
class ImageT
{
public:
typedef NumT value_type;
typedef value_type num_t;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef std::unique_ptr<ImageT<NumT>> Ptr;
ImageT() : _data(nullptr), _width(0), _height(0) { }
ImageT(size_t width, size_t height);
ImageT(size_t width, size_t height, value_type initialValue);
~ImageT();
ImageT(const ImageT<NumT>&);
ImageT<NumT>& operator=(const ImageT<NumT>&);
ImageT<NumT>& operator=(value_type value);
ImageT(ImageT<NumT>&& source);
ImageT<NumT>& operator=(ImageT<NumT>&& source);
static Ptr Make(size_t width, size_t height) {
return Ptr(new ImageT<NumT>(width, height));
}
static Ptr Make(size_t width, size_t height, value_type initialValue) {
return Ptr(new ImageT<NumT>(width, height, initialValue));
}
value_type* data() { return _data; }
const value_type* data() const { return _data; }
size_t Width() const { return _width; }
size_t Height() const { return _height; }
size_t size() const { return _width * _height; }
bool empty() const { return _width == 0 || _height == 0; }
iterator begin() { return _data; }
const_iterator begin() const { return _data; }
iterator end() { return _data + _width*_height; }
const_iterator end() const { return _data + _width*_height; }
const value_type& operator[](size_t index) const { return _data[index]; }
value_type& operator[](size_t index) { return _data[index]; }
ImageT<NumT>& operator+=(const ImageT<NumT>& other);
ImageT<NumT>& operator-=(const ImageT<NumT>& other);
ImageT<NumT>& operator*=(value_type factor);
ImageT<NumT>& operator*=(const ImageT<NumT>& other);
void reset();
/** Cut-off the borders of an image.
* @param outWidth Should be <= inWidth.
* @param outHeight Should be <= inHeight.
*/
static void Trim(value_type* output, size_t outWidth, size_t outHeight, const value_type* input, size_t inWidth, size_t inHeight);
ImageT<NumT> Trim(size_t outWidth, size_t outHeight) const
{
ImageT<NumT> image(outWidth, outHeight);
Trim(image.data(), outWidth, outHeight, data(), Width(), Height());
return image;
}
ImageT<NumT> TrimBox(size_t x1, size_t y1, size_t boxWidth, size_t boxHeight) const
{
ImageT<NumT> image(boxWidth, boxHeight);
TrimBox(image.data(), x1, y1, boxWidth, boxHeight, data(), Width(), Height());
return image;
}
template<typename T>
static void TrimBox(T* output, size_t x1, size_t y1, size_t boxWidth, size_t boxHeight, const T* input, size_t inWidth, size_t inHeight);
template<typename T>
static void CopyMasked(T* to, size_t toX, size_t toY, size_t toWidth, const T* from, size_t fromWidth, size_t fromHeight, const bool* fromMask);
/** Extend an image with zeros, complement of Trim.
* @param outWidth Should be >= inWidth.
* @param outHeight Should be >= inHeight.
*/
static void Untrim(value_type* output, size_t outWidth, size_t outHeight, const value_type* input, size_t inWidth, size_t inHeight);
ImageT<NumT> Untrim(size_t outWidth, size_t outHeight) const
{
ImageT<NumT> image(outWidth, outHeight);
Untrim(image.data(), outWidth, outHeight, data(), Width(), Height());
return image;
}
static value_type Median(const value_type* data, size_t size)
{
aocommon::UVector<value_type> copy;
return median_with_copy(data, size, copy);
}
static value_type MAD(const value_type* data, size_t size);
value_type Sum() const;
value_type Average() const;
value_type Min() const;
value_type Max() const;
value_type StdDevFromMAD() const { return StdDevFromMAD(_data, _width*_height); }
static value_type StdDevFromMAD(const value_type* data, size_t size)
{
// norminv(0.75) x MAD
return value_type(1.48260221850560) * MAD(data, size);
}
value_type RMS() const { return RMS(_data, _width*_height); }
static value_type RMS(const value_type* data, size_t size)
{
value_type sum = 0.0;
for(size_t i=0; i!=size; ++i)
sum += data[i]*data[i];
return std::sqrt(sum/value_type(size));
}
void Negate()
{
for(value_type& d : *this)
d = -d;
}
void Serialize(class SerialOStream& stream) const;
void Unserialize(class SerialIStream& stream);
private:
value_type* _data;
size_t _width, _height;
static value_type median_with_copy(const value_type* data, size_t size, aocommon::UVector<value_type>& copy);
};
template<typename NumT>
template<typename T>
void ImageT<NumT>::TrimBox(T* output, size_t x1, size_t y1, size_t boxWidth, size_t boxHeight, const T* input, size_t inWidth, size_t /*inHeight*/)
{
size_t endY = y1 + boxHeight;
for(size_t y=y1; y!=endY; ++y)
{
std::copy_n(&input[y*inWidth + x1], boxWidth, &output[(y-y1)*boxWidth]);
}
}
template<typename NumT>
template<typename T>
void ImageT<NumT>::CopyMasked(T* to, size_t toX, size_t toY, size_t toWidth, const T* from, size_t fromWidth, size_t fromHeight, const bool* fromMask)
{
for(size_t y=0; y!=fromHeight; ++y)
{
for(size_t x=0; x!=fromWidth; ++x)
{
if(fromMask[y*fromWidth + x])
to[toX + (toY+y) * toWidth + x] = from[y*fromWidth + x];
}
}
}
typedef ImageT<double> Image;
typedef ImageT<float> ImageF;
typedef ImageT<std::complex<float>> ImageCF;
template<class T>
using ImageTC = ImageT<std::complex<T>>;
#endif
|