138 lines
3.6 KiB
C
138 lines
3.6 KiB
C
|
#pragma once
|
||
|
|
||
|
/*--------------------------------
|
||
|
Iwa_TangentFlowFx
|
||
|
Computing a smooth, feature-preserving local edge flow (edge tangent flow, ETF)
|
||
|
Implementation of "Coherent Line Drawing" by H.Kang et al, Proc. NPAR 2007.
|
||
|
----------------------------------*/
|
||
|
|
||
|
#ifndef IWA_TANGENT_FLOW_FX_H
|
||
|
#define IWA_TANGENT_FLOW_FX_H
|
||
|
|
||
|
#include "stdfx.h"
|
||
|
#include "tfxparam.h"
|
||
|
|
||
|
#include <QThread>
|
||
|
|
||
|
struct double2 {
|
||
|
double x, y;
|
||
|
double2(double _x = 0., double _y = 0.) {
|
||
|
x = _x;
|
||
|
y = _y;
|
||
|
}
|
||
|
};
|
||
|
struct int2 {
|
||
|
int x, y;
|
||
|
|
||
|
int2 operator+(const int2& other) const {
|
||
|
return int2{x + other.x, y + other.y};
|
||
|
}
|
||
|
int2 operator-(const int2& other) const {
|
||
|
return int2{x - other.x, y - other.y};
|
||
|
}
|
||
|
int len2() const { return x * x + y * y; }
|
||
|
int2(int _x = 0, int _y = 0) {
|
||
|
x = _x;
|
||
|
y = _y;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class SobelFilterWorker : public QThread {
|
||
|
double* m_source_buf;
|
||
|
double2* m_flow_buf;
|
||
|
double* m_grad_mag_buf;
|
||
|
int2* m_offset_buf;
|
||
|
double m_mag_threshold;
|
||
|
TDimension m_dim;
|
||
|
int m_yFrom, m_yTo;
|
||
|
|
||
|
bool m_hasEmptyVector = false;
|
||
|
|
||
|
public:
|
||
|
SobelFilterWorker(double* source_buf, double2* flow_buf, double* grad_mag_buf,
|
||
|
int2* offset_buf, double mag_threshold, TDimension dim,
|
||
|
int yFrom, int yTo)
|
||
|
: m_source_buf(source_buf)
|
||
|
, m_flow_buf(flow_buf)
|
||
|
, m_grad_mag_buf(grad_mag_buf)
|
||
|
, m_offset_buf(offset_buf)
|
||
|
, m_mag_threshold(mag_threshold)
|
||
|
, m_dim(dim)
|
||
|
, m_yFrom(yFrom)
|
||
|
, m_yTo(yTo) {}
|
||
|
|
||
|
void run();
|
||
|
|
||
|
bool hasEmptyVector() { return m_hasEmptyVector; }
|
||
|
};
|
||
|
|
||
|
class TangentFlowWorker : public QThread {
|
||
|
double2* m_flow_cur_buf;
|
||
|
double2* m_flow_new_buf;
|
||
|
double* m_grad_mag_buf;
|
||
|
TDimension m_dim;
|
||
|
int m_kernelRadius;
|
||
|
int m_yFrom, m_yTo;
|
||
|
|
||
|
public:
|
||
|
TangentFlowWorker(double2* flow_cur_buf, double2* flow_new_buf,
|
||
|
double* grad_mag_buf, TDimension dim, int kernelRadius,
|
||
|
int yFrom, int yTo)
|
||
|
: m_flow_cur_buf(flow_cur_buf)
|
||
|
, m_flow_new_buf(flow_new_buf)
|
||
|
, m_grad_mag_buf(grad_mag_buf)
|
||
|
, m_dim(dim)
|
||
|
, m_kernelRadius(kernelRadius)
|
||
|
, m_yFrom(yFrom)
|
||
|
, m_yTo(yTo) {}
|
||
|
|
||
|
void run();
|
||
|
};
|
||
|
|
||
|
class Iwa_TangentFlowFx final : public TStandardRasterFx {
|
||
|
FX_PLUGIN_DECLARATION(Iwa_TangentFlowFx)
|
||
|
|
||
|
protected:
|
||
|
TRasterFxPort m_source;
|
||
|
|
||
|
TIntParamP m_iteration;
|
||
|
TDoubleParamP m_kernelRadius;
|
||
|
|
||
|
TDoubleParamP m_threshold;
|
||
|
|
||
|
TBoolParamP m_alignDirection;
|
||
|
TDoubleParamP m_pivotAngle;
|
||
|
|
||
|
// obtain source tile brightness, normalizing 0 to 1
|
||
|
template <typename RASTER, typename PIXEL>
|
||
|
void setSourceTileToBuffer(const RASTER srcRas, double* buf);
|
||
|
|
||
|
// render vector field in red & green channels
|
||
|
template <typename RASTER, typename PIXEL>
|
||
|
void setOutputRaster(double2* buf, double* grad_buf, const RASTER dstRas);
|
||
|
|
||
|
// compute the initial vector field.
|
||
|
// apply sobel filter, rotate by 90 degrees and normalize.
|
||
|
// also obtaining gradient magnitude (length of the vector length)
|
||
|
// empty regions will be filled by using Fast Sweeping Method
|
||
|
void computeInitialFlow(double* source_buf, double2* flow_buf,
|
||
|
double* grad_mag_buf, const TDimension dim,
|
||
|
double mag_threshold);
|
||
|
// 基準の角度に向きを合わせる
|
||
|
void alignFlowDirection(double2* flow_buf, const TDimension dim,
|
||
|
const double2& pivotVec);
|
||
|
|
||
|
public:
|
||
|
Iwa_TangentFlowFx();
|
||
|
|
||
|
void doCompute(TTile& tile, double frame,
|
||
|
const TRenderSettings& settings) override;
|
||
|
|
||
|
bool doGetBBox(double frame, TRectD& bBox,
|
||
|
const TRenderSettings& info) override;
|
||
|
|
||
|
bool canHandle(const TRenderSettings& info, double frame) override;
|
||
|
};
|
||
|
|
||
|
#endif
|