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