10 changed files with 524 additions and 45 deletions
@ -0,0 +1,37 @@ |
|||||
|
#ifndef ENHANCE_H |
||||
|
#define ENHANCE_H |
||||
|
|
||||
|
#include <QObject> |
||||
|
#include <QMetaType> |
||||
|
#include "model/processor/IProcessStrategy.h" |
||||
|
#include "utils/OpenCLHelper.h" |
||||
|
|
||||
|
typedef struct Enhance_t |
||||
|
{ |
||||
|
cl_int filterWidth; |
||||
|
cl_int filterHeight; |
||||
|
cl_int width; |
||||
|
cl_int height; |
||||
|
}Enhance_t; |
||||
|
|
||||
|
|
||||
|
class Enhance : public IProcessStrategy |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
public: |
||||
|
Q_INVOKABLE Enhance(const Context context, const QString kernelPath, const QObject *parent); |
||||
|
virtual void cpuProcess(ScenGenOutput_t parameters) override; |
||||
|
virtual void finalize() override; |
||||
|
|
||||
|
private: |
||||
|
KernelFunctor<Image2D, Image2D, Buffer, Enhance_t> _kernelFunctor; |
||||
|
virtual Image* processKernel(Image *frames, Buffer* scratchPad) override; |
||||
|
|
||||
|
Enhance_t _kernelParameters; |
||||
|
|
||||
|
bool _run; |
||||
|
|
||||
|
Buffer* _filter; |
||||
|
}; |
||||
|
|
||||
|
#endif // ENHANCE_H
|
@ -0,0 +1,41 @@ |
|||||
|
#ifndef PERSIST_H |
||||
|
#define PERSIST_H |
||||
|
|
||||
|
#include <QObject> |
||||
|
#include <QMetaType> |
||||
|
#include "model/processor/IProcessStrategy.h" |
||||
|
#include "utils/OpenCLHelper.h" |
||||
|
|
||||
|
#define PERSIST_MAX_SIZE 8 |
||||
|
|
||||
|
typedef struct Persist_t |
||||
|
{ |
||||
|
cl_int persist; |
||||
|
cl_int mode; |
||||
|
}Persist_t; |
||||
|
|
||||
|
|
||||
|
class Persist : public IProcessStrategy |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
public: |
||||
|
Q_INVOKABLE Persist(const Context context, const QString kernelPath, const QObject *parent); |
||||
|
virtual void cpuProcess(ScenGenOutput_t parameters) override; |
||||
|
virtual void finalize() override; |
||||
|
|
||||
|
private: |
||||
|
KernelFunctor<Image2D, Image2D, Image2D, Image2D, Persist_t> _kernelFunctor; |
||||
|
virtual Image* processKernel(Image *frames, Buffer* scratchPad) override; |
||||
|
|
||||
|
Persist_t _kernelParameters; |
||||
|
|
||||
|
QVector<Image*> _queue; |
||||
|
Image* _imageSum; |
||||
|
|
||||
|
bool _reCalc; |
||||
|
quint64 _lastWidth; |
||||
|
quint64 _lastHeight; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#endif // PERSIST_H
|
@ -0,0 +1,85 @@ |
|||||
|
// #define TEST |
||||
|
#define X 95 |
||||
|
#define Y 22 |
||||
|
|
||||
|
//#define USE_DBL |
||||
|
#ifdef USE_DBL |
||||
|
#define TYPE_FLT double |
||||
|
#define TYPE_INT long |
||||
|
#define MASK 0xFFFF |
||||
|
#define SHIFT 16 |
||||
|
#define EPSILSON 4.94065645841247E-324 |
||||
|
#else |
||||
|
#define TYPE_FLT float |
||||
|
#define TYPE_INT int |
||||
|
#define MASK 0x00FF |
||||
|
#define SHIFT 8 |
||||
|
#define EPSILSON 1.401298E-45 |
||||
|
#endif |
||||
|
|
||||
|
constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | |
||||
|
CLK_ADDRESS_CLAMP_TO_EDGE | |
||||
|
CLK_FILTER_LINEAR; |
||||
|
|
||||
|
|
||||
|
struct input { |
||||
|
int persist; |
||||
|
int mode; |
||||
|
}; |
||||
|
|
||||
|
TYPE_FLT read_data(image2d_t input_frame, int x, int z) |
||||
|
{ |
||||
|
int2 gid = (int2)(x, z); |
||||
|
uint4 pixel = read_imageui(input_frame, sampler, gid); |
||||
|
TYPE_INT temp = (TYPE_INT)((TYPE_INT)pixel.x & MASK) | |
||||
|
(TYPE_INT)(((TYPE_INT)pixel.y & MASK) << SHIFT) | |
||||
|
(TYPE_INT)(((TYPE_INT)pixel.z & MASK) << (SHIFT * 2)) | |
||||
|
(TYPE_INT)(((TYPE_INT)pixel.w & MASK) << (SHIFT * 3)); |
||||
|
TYPE_FLT raw_data = *((TYPE_FLT*)(&temp)); |
||||
|
return raw_data; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
kernel void Persist(read_only image2d_t input_frame, read_write image2d_t output_frame, read_write image2d_t sum_frame, read_write image2d_t removed_frame, struct input params) |
||||
|
{ |
||||
|
int2 gid = (int2)(get_global_id(0), get_global_id(1)); |
||||
|
TYPE_FLT input = read_data(input_frame, gid.x, gid.y); |
||||
|
TYPE_FLT output_data = 0; |
||||
|
TYPE_FLT sum = 0; |
||||
|
|
||||
|
if(params.mode == 0) |
||||
|
{ |
||||
|
sum = input; |
||||
|
} |
||||
|
else if(params.mode == 1) |
||||
|
{ |
||||
|
sum = read_data(sum_frame, gid.x, gid.y); |
||||
|
sum += input; |
||||
|
} |
||||
|
else if(params.mode == 2) |
||||
|
{ |
||||
|
sum = read_data(sum_frame, gid.x, gid.y); |
||||
|
sub = read_data(removed_frame, gid.x, gid.y); |
||||
|
sum = sum + input - sub; |
||||
|
} |
||||
|
|
||||
|
output_data = sum / params.persist; |
||||
|
|
||||
|
TYPE_INT out = *((TYPE_INT*)(&output_data)); |
||||
|
uint4 pixel; |
||||
|
pixel.x = (TYPE_INT)(out & MASK); |
||||
|
pixel.y = (TYPE_INT)((out >> SHIFT) & MASK); |
||||
|
pixel.z = (TYPE_INT)((out >> (SHIFT *2)) & MASK); |
||||
|
pixel.w = (TYPE_INT)((out >> (SHIFT * 3)) & MASK); |
||||
|
|
||||
|
write_imageui(output_frame, gid, pixel); |
||||
|
|
||||
|
out = *((TYPE_INT*)(&sum)); |
||||
|
pixel.x = (TYPE_INT)(out & MASK); |
||||
|
pixel.y = (TYPE_INT)((out >> SHIFT) & MASK); |
||||
|
pixel.z = (TYPE_INT)((out >> (SHIFT *2)) & MASK); |
||||
|
pixel.w = (TYPE_INT)((out >> (SHIFT * 3)) & MASK); |
||||
|
|
||||
|
write_imageui(sum_frame, gid, pixel); |
||||
|
} |
||||
|
|
@ -0,0 +1,164 @@ |
|||||
|
#include "model/processor/strategies/Enhance.h" |
||||
|
#include "model/processor/BIP.h" |
||||
|
#include <QPixmap> |
||||
|
#include <QImage> |
||||
|
|
||||
|
Enhance::Enhance(const Context context, |
||||
|
const QString kernelPath, |
||||
|
const QObject *parent = Q_NULLPTR) : |
||||
|
IProcessStrategy(context, kernelPath, "Enhance", parent), |
||||
|
_kernelFunctor(KernelFunctor<Image2D, Image2D, |
||||
|
Buffer, Enhance_t>(_kernel)) |
||||
|
{ |
||||
|
memset(&_kernelParameters, 0, sizeof (Enhance_t)); |
||||
|
_filter = Q_NULLPTR; |
||||
|
} |
||||
|
|
||||
|
void Enhance::cpuProcess(ScenGenOutput_t parameters) |
||||
|
{ |
||||
|
if(parameters.enhance.isUpdated || parameters.enhanceAlgorithm.isUpdated) |
||||
|
{ |
||||
|
_run = false; |
||||
|
if(parameters.enhance.value == 0) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
float *hpf; |
||||
|
int *backgroundRecovery; |
||||
|
|
||||
|
//sharpen
|
||||
|
if(parameters.enhanceAlgorithm.value == 0) |
||||
|
{ |
||||
|
auto alpha = 0.25f * (parameters.enhance.value - 1); |
||||
|
|
||||
|
_kernelParameters.filterWidth = 3; |
||||
|
_kernelParameters.filterHeight = 3; |
||||
|
|
||||
|
hpf = new float[9]; |
||||
|
backgroundRecovery = new int[9]; |
||||
|
|
||||
|
auto factor = 4 / (alpha + 1); |
||||
|
int index = 0; |
||||
|
|
||||
|
hpf[index++] = factor * (alpha / 4); |
||||
|
hpf[index++] = factor * ((1 - alpha) / 4); |
||||
|
hpf[index++] = factor * (alpha / 4); |
||||
|
|
||||
|
hpf[index++] = factor * ((1 - alpha) / 4); |
||||
|
hpf[index++] = factor * -1; |
||||
|
hpf[index++] = factor * ((1 - alpha) / 4); |
||||
|
|
||||
|
hpf[index++] = factor * (alpha / 4); |
||||
|
hpf[index++] = factor * ((1 - alpha) / 4); |
||||
|
hpf[index++] = factor * (alpha / 4); |
||||
|
|
||||
|
index = 0; |
||||
|
|
||||
|
memset(backgroundRecovery, 0, 9 * sizeof (int)); |
||||
|
backgroundRecovery[4] = 1; |
||||
|
|
||||
|
_run = true; |
||||
|
} |
||||
|
//log
|
||||
|
else if(parameters.enhanceAlgorithm.value == 1) |
||||
|
{ |
||||
|
_kernelParameters.filterWidth = 5; |
||||
|
_kernelParameters.filterHeight = 5; |
||||
|
|
||||
|
hpf = new float[25]; |
||||
|
backgroundRecovery = new int[25]; |
||||
|
|
||||
|
auto sigma = 0.5f + 0.25f * (parameters.enhance.value - 1); |
||||
|
float sumHg = 0; |
||||
|
float h[25]; |
||||
|
|
||||
|
for(int i = -2; i <= 2; i++) |
||||
|
{ |
||||
|
for(int j = -2; j <= 2; j++) |
||||
|
{ |
||||
|
float temp = expf(-(powf(i, 2) + powf(j, 2)) |
||||
|
/ 2 / powf(sigma, 2)); |
||||
|
h[(i + 2) * 5 + (j + 2)] = (powf(i, 2) + powf(j, 2) - 2 * powf(sigma, 2)) * |
||||
|
temp; |
||||
|
|
||||
|
sumHg += temp; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for(int i = 0; i < 25 ; i++) |
||||
|
{ |
||||
|
hpf[i] = h[i] / powf(sigma, 4) / sumHg; |
||||
|
} |
||||
|
|
||||
|
memset(backgroundRecovery, 0, 25 * sizeof (int)); |
||||
|
backgroundRecovery[12] = 1; |
||||
|
|
||||
|
_run = true; |
||||
|
} |
||||
|
|
||||
|
if(_run) |
||||
|
{ |
||||
|
auto filterSize = _kernelParameters.filterWidth * _kernelParameters.filterHeight; |
||||
|
float filter[filterSize]; |
||||
|
for(int i = 0; i < filterSize ; i++) |
||||
|
{ |
||||
|
filter[i] = backgroundRecovery[i] - hpf[i]; |
||||
|
} |
||||
|
|
||||
|
delete [] hpf; |
||||
|
delete [] backgroundRecovery; |
||||
|
|
||||
|
if(_filter) |
||||
|
delete _filter; |
||||
|
|
||||
|
_filter = _openCLHelper.array2CLBuffer(_CLContext, filterSize * sizeof (float)); |
||||
|
BIP::getInstance()->CLQueue.enqueueWriteBuffer(*_filter, CL_TRUE, |
||||
|
0, filterSize * sizeof (float), |
||||
|
filter); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Enhance::finalize() |
||||
|
{ |
||||
|
if(_filter) |
||||
|
delete _filter; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
Image* Enhance::processKernel(Image *frames, Buffer* scratchPad) |
||||
|
{ |
||||
|
if(_run) |
||||
|
{ |
||||
|
auto format = frames->getImageInfo<CL_IMAGE_FORMAT>(); |
||||
|
auto width = frames->getImageInfo<CL_IMAGE_WIDTH>(); |
||||
|
auto height = frames->getImageInfo<CL_IMAGE_HEIGHT>(); |
||||
|
|
||||
|
_kernelParameters.width = width; |
||||
|
_kernelParameters.height = height; |
||||
|
|
||||
|
auto imageOutput = new Image2D(_CLContext, |
||||
|
CL_MEM_READ_WRITE, |
||||
|
ImageFormat(format.image_channel_order, format.image_channel_data_type), |
||||
|
width, |
||||
|
height); |
||||
|
cl::EnqueueArgs eargs(BIP::getInstance()->CLQueue, cl::NDRange(width, height)); |
||||
|
_openCLHelper.runKernelFunctor<Image2D, Image2D, Buffer, Enhance_t>(_kernelFunctor, |
||||
|
eargs, |
||||
|
*static_cast<Image2D*>(frames), |
||||
|
*imageOutput, |
||||
|
*_filter, |
||||
|
_kernelParameters); |
||||
|
|
||||
|
|
||||
|
delete frames; |
||||
|
return imageOutput; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return frames; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,136 @@ |
|||||
|
#include "model/processor/strategies/Persist.h" |
||||
|
#include "model/processor/BIP.h" |
||||
|
#include <QPixmap> |
||||
|
#include <QImage> |
||||
|
|
||||
|
Persist::Persist(const Context context, |
||||
|
const QString kernelPath, |
||||
|
const QObject *parent = Q_NULLPTR) : |
||||
|
IProcessStrategy(context, kernelPath, "Persist", parent), |
||||
|
_kernelFunctor(KernelFunctor<Image2D, Image2D, |
||||
|
Image2D, Image2D, Persist_t>(_kernel)) |
||||
|
{ |
||||
|
memset(&_kernelParameters, 0, sizeof (Persist_t)); |
||||
|
_imageSum = Q_NULLPTR; |
||||
|
_reCalc = true; |
||||
|
} |
||||
|
|
||||
|
void Persist::cpuProcess(ScenGenOutput_t parameters) |
||||
|
{ |
||||
|
if(parameters.persist.isUpdated) |
||||
|
{ |
||||
|
_kernelParameters.persist = parameters.persist.value; |
||||
|
_reCalc = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Persist::finalize() |
||||
|
{ |
||||
|
foreach (auto frame, _queue) |
||||
|
{ |
||||
|
delete frame; |
||||
|
} |
||||
|
_queue.clear(); |
||||
|
|
||||
|
if(_imageSum) |
||||
|
delete _imageSum; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
Image* Persist::processKernel(Image *frames, Buffer* scratchPad) |
||||
|
{ |
||||
|
Image* temp; |
||||
|
|
||||
|
if(_queue.length() < PERSIST_MAX_SIZE) |
||||
|
{ |
||||
|
_queue.push_front(frames); |
||||
|
return frames; |
||||
|
} |
||||
|
|
||||
|
if(_kernelParameters.persist != 1) |
||||
|
{ |
||||
|
auto format = frames->getImageInfo<CL_IMAGE_FORMAT>(); |
||||
|
auto width = frames->getImageInfo<CL_IMAGE_WIDTH>(); |
||||
|
auto height = frames->getImageInfo<CL_IMAGE_HEIGHT>(); |
||||
|
|
||||
|
//if width or height changes we should erase everything
|
||||
|
if(_lastWidth != width || _lastHeight != height) |
||||
|
{ |
||||
|
_reCalc = false; |
||||
|
|
||||
|
if(_imageSum) |
||||
|
delete _imageSum; |
||||
|
|
||||
|
_imageSum = new Image2D(_CLContext, |
||||
|
CL_MEM_READ_WRITE, |
||||
|
ImageFormat(format.image_channel_order, format.image_channel_data_type), |
||||
|
width, |
||||
|
height); |
||||
|
|
||||
|
foreach (auto frame, _queue) |
||||
|
{ |
||||
|
delete frame; |
||||
|
} |
||||
|
_queue.clear(); |
||||
|
|
||||
|
_lastWidth = width; |
||||
|
_lastHeight = height; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
auto outputImage = new Image2D(_CLContext, |
||||
|
CL_MEM_READ_WRITE, |
||||
|
ImageFormat(format.image_channel_order, format.image_channel_data_type), |
||||
|
width, |
||||
|
height); |
||||
|
|
||||
|
|
||||
|
cl::EnqueueArgs eargs(BIP::getInstance()->CLQueue, cl::NDRange(width, height)); |
||||
|
|
||||
|
if(_reCalc) |
||||
|
{ |
||||
|
_reCalc = false; |
||||
|
for(auto i = 0; i < _kernelParameters.persist; i++) |
||||
|
{ |
||||
|
if(i == 0) |
||||
|
_kernelParameters.mode = 0; |
||||
|
else if(i < _kernelParameters.persist) |
||||
|
_kernelParameters.mode = 1; |
||||
|
|
||||
|
_openCLHelper.runKernelFunctor<Image2D, Image2D, Image2D, Image2D, Persist_t>(_kernelFunctor, |
||||
|
eargs, |
||||
|
*static_cast<Image2D*>(_queue[i]), |
||||
|
*outputImage, |
||||
|
*static_cast<Image2D*>(_imageSum), |
||||
|
*static_cast<Image2D*>(_queue[_kernelParameters.persist - 1]), |
||||
|
_kernelParameters); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
_kernelParameters.mode = 2; |
||||
|
_openCLHelper.runKernelFunctor<Image2D, Image2D, Image2D, Image2D, Persist_t>(_kernelFunctor, |
||||
|
eargs, |
||||
|
*static_cast<Image2D*>(frames), |
||||
|
*outputImage, |
||||
|
*static_cast<Image2D*>(_imageSum), |
||||
|
*static_cast<Image2D*>(_queue[_kernelParameters.persist - 1]), |
||||
|
_kernelParameters); |
||||
|
|
||||
|
temp = outputImage; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
temp = frames; |
||||
|
} |
||||
|
|
||||
|
delete _queue[PERSIST_MAX_SIZE - 1]; |
||||
|
for(auto i = 0; i < PERSIST_MAX_SIZE - 1; i++) |
||||
|
{ |
||||
|
_queue[i + 1] = _queue[i]; |
||||
|
} |
||||
|
|
||||
|
_queue[0] = frames; |
||||
|
|
||||
|
|
||||
|
return temp; |
||||
|
} |
Loading…
Reference in new issue