mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Original implementation of Edge Image filters
This commit is contained in:
@@ -566,6 +566,8 @@ set(VMIX_RSC_FILES
|
||||
./rsc/shaders/filters/blur.glsl
|
||||
./rsc/shaders/filters/blur_1.glsl
|
||||
./rsc/shaders/filters/blur_2.glsl
|
||||
./rsc/shaders/filters/lens_1.glsl
|
||||
./rsc/shaders/filters/lens_2.glsl
|
||||
./rsc/shaders/filters/hashedblur.glsl
|
||||
./rsc/shaders/filters/circularblur.glsl
|
||||
./rsc/shaders/filters/hashederosion.glsl
|
||||
@@ -574,6 +576,7 @@ set(VMIX_RSC_FILES
|
||||
./rsc/shaders/filters/sharpen.glsl
|
||||
./rsc/shaders/filters/sharpen_1.glsl
|
||||
./rsc/shaders/filters/sharpen_2.glsl
|
||||
./rsc/shaders/filters/contour_2.glsl
|
||||
./rsc/shaders/filters/sharpenedge.glsl
|
||||
./rsc/shaders/filters/chromakey.glsl
|
||||
./rsc/shaders/filters/bilinear.glsl
|
||||
|
||||
@@ -153,6 +153,9 @@ void CloneSource::setFilter(FrameBufferFilter::Type T)
|
||||
case FrameBufferFilter::FILTER_SHARPEN:
|
||||
filter_ = new SharpenFilter;
|
||||
break;
|
||||
case FrameBufferFilter::FILTER_EDGE:
|
||||
filter_ = new EdgeFilter;
|
||||
break;
|
||||
case FrameBufferFilter::FILTER_IMAGE:
|
||||
filter_ = new ImageFilter;
|
||||
break;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "FrameBufferFilter.h"
|
||||
|
||||
const char* FrameBufferFilter::type_label[FrameBufferFilter::FILTER_INVALID] = {
|
||||
"None", "Delay", "Blur", "Sharpen", "Shader code"
|
||||
"None", "Delay", "Blur", "Sharpen", "Edge", "Shader code"
|
||||
};
|
||||
|
||||
FrameBufferFilter::FrameBufferFilter() : enabled_(true), input_(nullptr)
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
FILTER_DELAY,
|
||||
FILTER_BLUR,
|
||||
FILTER_SHARPEN,
|
||||
FILTER_EDGE,
|
||||
FILTER_IMAGE,
|
||||
FILTER_INVALID
|
||||
} Type;
|
||||
|
||||
@@ -821,7 +821,7 @@ void ImGuiVisitor::visit (BlurFilter& f)
|
||||
void ImGuiVisitor::visit (SharpenFilter& f)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Blur ";
|
||||
oss << "Sharpen ";
|
||||
|
||||
// Method selection
|
||||
if (ImGuiToolkit::IconButton(2, 1)) {
|
||||
@@ -863,6 +863,51 @@ void ImGuiVisitor::visit (SharpenFilter& f)
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiVisitor::visit (EdgeFilter& f)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Edge ";
|
||||
|
||||
// Method selection
|
||||
if (ImGuiToolkit::IconButton(16, 8)) {
|
||||
f.setMethod( 0 );
|
||||
oss << EdgeFilter::method_label[0];
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
int m = (int) f.method();
|
||||
if (ImGui::Combo("Method", &m, EdgeFilter::method_label, IM_ARRAYSIZE(EdgeFilter::method_label) )) {
|
||||
f.setMethod( m );
|
||||
oss << EdgeFilter::method_label[m];
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
|
||||
|
||||
// List of parameters
|
||||
std::map<std::string, float> filter_parameters = f.program().parameters();
|
||||
for (auto param = filter_parameters.begin(); param != filter_parameters.end(); ++param)
|
||||
{
|
||||
ImGui::PushID( param->first.c_str() );
|
||||
float v = param->second;
|
||||
if (ImGuiToolkit::IconButton(13, 14)) {
|
||||
v = 0.f;
|
||||
f.setProgramParameter(param->first, v);
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
if (ImGui::SliderFloat( param->first.c_str(), &v, 0.f, 1.f, "%.2f")) {
|
||||
f.setProgramParameter(param->first, v);
|
||||
}
|
||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||
oss << EdgeFilter::method_label[ f.method() ];
|
||||
oss << " : " << param->first << " " << std::setprecision(3) <<param->second;
|
||||
Action::manager().store(oss.str());
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiVisitor::visit (ImageFilter& f)
|
||||
{
|
||||
// Selection of Algorithm
|
||||
|
||||
@@ -41,6 +41,7 @@ public:
|
||||
void visit (DelayFilter&) override;
|
||||
void visit (BlurFilter&) override;
|
||||
void visit (SharpenFilter&) override;
|
||||
void visit (EdgeFilter&) override;
|
||||
void visit (ImageFilter&) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -78,27 +78,17 @@ std::string fragmentFooter = "void main() {\n"
|
||||
|
||||
std::list< FilteringProgram > FilteringProgram::presets = {
|
||||
FilteringProgram(),
|
||||
FilteringProgram("Blur", "shaders/filters/blur_1.glsl", "shaders/filters/blur_2.glsl", { { "Amount", 0.5} }),
|
||||
FilteringProgram("HashBlur", "shaders/filters/hashedblur.glsl", "", { { "Radius", 0.5}, { "Iterations", 0.5 } }),
|
||||
FilteringProgram("Unfocus", "shaders/filters/focus.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Smooth", "shaders/filters/bilinear.glsl", "", { }),
|
||||
FilteringProgram("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 1.0} }),
|
||||
FilteringProgram("Denoise", "shaders/filters/denoise.glsl", "", { { "Threshold", 0.5} }),
|
||||
FilteringProgram("Noise", "shaders/filters/noise.glsl", "", { { "Amount", 0.25} }),
|
||||
FilteringProgram("Grain", "shaders/filters/grain.glsl", "", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharpen", "shaders/filters/sharp.glsl", "", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharp Edge", "shaders/filters/bilinear.glsl", "shaders/filters/sharpenedge.glsl", { { "Strength", 0.5} }),
|
||||
FilteringProgram("Edge", "shaders/filters/bilinear.glsl", "shaders/filters/edge.glsl", { { "Threshold", 0.5} }),
|
||||
FilteringProgram("Sobel", "shaders/filters/sobel.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Freichen", "shaders/filters/freichen.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Pixelate", "shaders/filters/pixelate.glsl", "", { { "Size", 0.5}, { "Sharpen", 0.5} }),
|
||||
FilteringProgram("Erosion", "shaders/filters/erosion.glsl", "", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Dilation", "shaders/filters/dilation.glsl", "", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Openning", "shaders/filters/erosion.glsl", "shaders/filters/dilation.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Closing", "shaders/filters/dilation.glsl", "shaders/filters/erosion.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("TopHat", "shaders/filters/erosion.glsl", "shaders/filters/tophat.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("BlackHat", "shaders/filters/dilation.glsl", "shaders/filters/blackhat.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("Bloom", "shaders/filters/bloom.glsl", "", { { "Intensity", 0.5} }),
|
||||
FilteringProgram("Bokeh", "shaders/filters/bokeh.glsl", "", { { "Radius", 1.0} }),
|
||||
FilteringProgram("Chalk", "shaders/filters/talk.glsl", "", { { "Factor", 1.0} }),
|
||||
@@ -595,13 +585,15 @@ void BlurFilter::accept (Visitor& v)
|
||||
////////////////////////////////////////
|
||||
|
||||
const char* SharpenFilter::method_label[SharpenFilter::SHARPEN_INVALID] = {
|
||||
"Unsharp mask", "Convolution", "Edge"
|
||||
"Unsharp mask", "Convolution", "Edge", "White hat", "Black hat"
|
||||
};
|
||||
|
||||
std::vector< FilteringProgram > SharpenFilter::programs_ = {
|
||||
FilteringProgram("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharpen", "shaders/filters/sharp.glsl", "", { { "Amount", 0.5} }),
|
||||
FilteringProgram("Sharp Edge", "shaders/filters/bilinear.glsl", "shaders/filters/sharpenedge.glsl", { { "Strength", 0.5} }),
|
||||
FilteringProgram("TopHat", "shaders/filters/erosion.glsl", "shaders/filters/tophat.glsl", { { "Radius", 0.5} }),
|
||||
FilteringProgram("BlackHat", "shaders/filters/dilation.glsl", "shaders/filters/blackhat.glsl", { { "Radius", 0.5} }),
|
||||
};
|
||||
|
||||
SharpenFilter::SharpenFilter (): ImageFilter(), method_(SHARPEN_INVALID)
|
||||
@@ -630,4 +622,47 @@ void SharpenFilter::accept (Visitor& v)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
///// //
|
||||
//// EDGE FILTERS ///
|
||||
/// ////
|
||||
////////////////////////////////////////
|
||||
|
||||
const char* EdgeFilter::method_label[EdgeFilter::EDGE_INVALID] = {
|
||||
"Thresholding", "Sobel", "Freichen", "Contour"
|
||||
};
|
||||
|
||||
std::vector< FilteringProgram > EdgeFilter::programs_ = {
|
||||
FilteringProgram("Edge", "shaders/filters/bilinear.glsl", "shaders/filters/edge.glsl", { { "Threshold", 0.5} }),
|
||||
FilteringProgram("Sobel", "shaders/filters/sobel.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Freichen", "shaders/filters/freichen.glsl", "", { { "Factor", 0.5} }),
|
||||
FilteringProgram("Contour", "shaders/filters/sharpen_1.glsl", "shaders/filters/contour_2.glsl", { { "Amount", 0.5} }),
|
||||
};
|
||||
|
||||
EdgeFilter::EdgeFilter (): ImageFilter(), method_(EDGE_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
void EdgeFilter::setMethod(int method)
|
||||
{
|
||||
method_ = (EdgeMethod) CLAMP(method, EDGE_THRESHOLD, EDGE_INVALID-1);
|
||||
setProgram( programs_[ (int) method_] );
|
||||
}
|
||||
|
||||
void EdgeFilter::draw (FrameBuffer *input)
|
||||
{
|
||||
// Default
|
||||
if (method_ == EDGE_INVALID)
|
||||
setMethod( EDGE_THRESHOLD );
|
||||
|
||||
ImageFilter::draw( input );
|
||||
}
|
||||
|
||||
void EdgeFilter::accept (Visitor& v)
|
||||
{
|
||||
FrameBufferFilter::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -148,6 +148,8 @@ public:
|
||||
SHARPEN_MASK = 0,
|
||||
SHARPEN_CONVOLUTION,
|
||||
SHARPEN_EDGE,
|
||||
SHARPEN_WHITEHAT,
|
||||
SHARPEN_BLACKHAT,
|
||||
SHARPEN_INVALID
|
||||
} SharpenMethod;
|
||||
static const char* method_label[SHARPEN_INVALID];
|
||||
@@ -166,5 +168,36 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class EdgeFilter : public ImageFilter
|
||||
{
|
||||
public:
|
||||
|
||||
EdgeFilter();
|
||||
|
||||
// Algorithms used for edge detection
|
||||
typedef enum {
|
||||
EDGE_THRESHOLD = 0,
|
||||
EDGE_SOBEL,
|
||||
EDGE_FREICHEN,
|
||||
EDGE_CONTOUR,
|
||||
EDGE_INVALID
|
||||
} EdgeMethod;
|
||||
static const char* method_label[EDGE_INVALID];
|
||||
EdgeMethod method () const { return method_; }
|
||||
void setMethod(int method);
|
||||
|
||||
// implementation of FrameBufferFilter
|
||||
Type type() const override { return FrameBufferFilter::FILTER_EDGE; }
|
||||
|
||||
void draw (FrameBuffer *input) override;
|
||||
void accept (Visitor& v) override;
|
||||
|
||||
private:
|
||||
EdgeMethod method_;
|
||||
static std::vector< FilteringProgram > programs_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // IMAGEFILTER_H
|
||||
|
||||
@@ -1273,6 +1273,30 @@ void SessionLoader::visit (SharpenFilter& f)
|
||||
f.setProgramParameters(filter_params);
|
||||
}
|
||||
|
||||
void SessionLoader::visit (EdgeFilter& f)
|
||||
{
|
||||
int m = 0;
|
||||
xmlCurrent_->QueryIntAttribute("method", &m);
|
||||
f.setMethod(m);
|
||||
|
||||
std::map< std::string, float > filter_params;
|
||||
XMLElement* parameters = xmlCurrent_->FirstChildElement("parameters");
|
||||
if (parameters) {
|
||||
XMLElement* param = parameters->FirstChildElement("uniform");
|
||||
for( ; param ; param = param->NextSiblingElement())
|
||||
{
|
||||
float val = 0.f;
|
||||
param->QueryFloatAttribute("value", &val);
|
||||
const char * name;
|
||||
param->QueryStringAttribute("name", &name);
|
||||
if (name)
|
||||
filter_params[name] = val;
|
||||
}
|
||||
}
|
||||
|
||||
f.setProgramParameters(filter_params);
|
||||
}
|
||||
|
||||
void SessionLoader::visit (ImageFilter& f)
|
||||
{
|
||||
const char * filter_name;
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
void visit (DelayFilter&) override;
|
||||
void visit (BlurFilter&) override;
|
||||
void visit (SharpenFilter&) override;
|
||||
void visit (EdgeFilter&) override;
|
||||
void visit (ImageFilter&) override;
|
||||
|
||||
// callbacks
|
||||
|
||||
@@ -726,6 +726,22 @@ void SessionVisitor::visit (SharpenFilter& f)
|
||||
}
|
||||
}
|
||||
|
||||
void SessionVisitor::visit (EdgeFilter& f)
|
||||
{
|
||||
xmlCurrent_->SetAttribute("method", (int) f.method());
|
||||
|
||||
std::map< std::string, float > filter_params = f.program().parameters();
|
||||
XMLElement *parameters = xmlDoc_->NewElement( "parameters" );
|
||||
xmlCurrent_->InsertEndChild(parameters);
|
||||
for (auto p = filter_params.begin(); p != filter_params.end(); ++p)
|
||||
{
|
||||
XMLElement *param = xmlDoc_->NewElement( "uniform" );
|
||||
param->SetAttribute("name", p->first.c_str() );
|
||||
param->SetAttribute("value", p->second );
|
||||
parameters->InsertEndChild(param);
|
||||
}
|
||||
}
|
||||
|
||||
void SessionVisitor::visit (ImageFilter& f)
|
||||
{
|
||||
xmlCurrent_->SetAttribute("name", f.program().name().c_str() );
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
void visit (DelayFilter&) override;
|
||||
void visit (BlurFilter&) override;
|
||||
void visit (SharpenFilter&) override;
|
||||
void visit (EdgeFilter&) override;
|
||||
void visit (ImageFilter&) override;
|
||||
|
||||
// callbacks
|
||||
|
||||
@@ -46,6 +46,7 @@ class PassthroughFilter;
|
||||
class DelayFilter;
|
||||
class BlurFilter;
|
||||
class SharpenFilter;
|
||||
class EdgeFilter;
|
||||
class ImageFilter;
|
||||
|
||||
class SourceCallback;
|
||||
@@ -108,6 +109,7 @@ public:
|
||||
virtual void visit (DelayFilter&) {}
|
||||
virtual void visit (BlurFilter&) {}
|
||||
virtual void visit (SharpenFilter&) {}
|
||||
virtual void visit (EdgeFilter&) {}
|
||||
virtual void visit (ImageFilter&) {}
|
||||
|
||||
virtual void visit (SourceCallback&) {}
|
||||
|
||||
29
rsc/shaders/filters/contour_2.glsl
Normal file
29
rsc/shaders/filters/contour_2.glsl
Normal file
@@ -0,0 +1,29 @@
|
||||
uniform float Amount;
|
||||
|
||||
#define N 7
|
||||
vec4 blur1D(vec2 U, vec2 D, float rad)
|
||||
{
|
||||
float w = rad * iResolution.y;
|
||||
float z = ceil(max(0.,log2(w/float(N)))); // LOD N/w = res/2^z
|
||||
vec4 O = vec4(0);
|
||||
float r = float(N-1)/2., g, t=0., x;
|
||||
for( int k=0; k<N; k++ ) {
|
||||
x = float(k)/r -1.;
|
||||
t += g = exp(-2.*x*x );
|
||||
O += g * texture(iChannel0, (U + w*x*D) / iResolution.xy );
|
||||
}
|
||||
return O/t;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
// get original image
|
||||
vec4 c = texture(iChannel1, fragCoord.xy / iResolution.xy);
|
||||
|
||||
// Remove blurred image to original image
|
||||
vec4 lumcoeff = vec4(0.299, 0.587, 0.114, 1.);
|
||||
float luminance = dot( blur1D(fragCoord, vec2(0,1), 0.1 * Amount ) - c, lumcoeff);
|
||||
|
||||
// composition
|
||||
fragColor = vec4(luminance, luminance, luminance, 1.0);
|
||||
}
|
||||
17
rsc/shaders/filters/lens_1.glsl
Normal file
17
rsc/shaders/filters/lens_1.glsl
Normal file
@@ -0,0 +1,17 @@
|
||||
float BRIGHT_SPOT_TRESHOLD=0.5;
|
||||
|
||||
vec3 BriSp(vec3 p){
|
||||
if(p.x+p.y+p.z>BRIGHT_SPOT_TRESHOLD*3.)p=(1./(1.-p)-1.)*(1.-BRIGHT_SPOT_TRESHOLD);
|
||||
p=clamp(p,0.,100.);
|
||||
return p;
|
||||
}
|
||||
|
||||
vec3 bright(vec2 n){
|
||||
vec3 p=texture(iChannel0,n).rgb;
|
||||
p=BriSp(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
|
||||
fragColor = vec4(bright(fragCoord/iResolution.xy),0.);
|
||||
}
|
||||
32
rsc/shaders/filters/lens_2.glsl
Normal file
32
rsc/shaders/filters/lens_2.glsl
Normal file
@@ -0,0 +1,32 @@
|
||||
uniform float Radius;
|
||||
|
||||
const float pi=4.*atan(1.);
|
||||
const float ang=(3.-sqrt(5.))*pi;
|
||||
float gamma=1.8;
|
||||
|
||||
const float SAMPLES=50.;
|
||||
|
||||
vec3 bokeh(sampler2D samp,vec2 uv,vec2 radius,float lod){
|
||||
vec3 col = vec3(0);
|
||||
for(float i=0.;i<SAMPLES;i++){
|
||||
float d=i/SAMPLES;
|
||||
vec2 p=vec2(sin(ang*i),cos(ang*i))*sqrt(d)*radius;
|
||||
col+=pow(texture(samp,uv+p,lod).rgb,vec3(gamma));
|
||||
}
|
||||
return pow(col/SAMPLES,vec3(1./gamma));
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
|
||||
vec2 uv = fragCoord/iResolution.xy;
|
||||
|
||||
vec2 pix=1./iResolution.xy;
|
||||
|
||||
float r=sin(Radius) * 2.0;
|
||||
r*=r*20.;
|
||||
|
||||
float lod=log2(r/SAMPLES*pi*5.);
|
||||
//lod=0.;
|
||||
vec3 col = bokeh(iChannel0,uv,r*pix,lod);
|
||||
|
||||
fragColor = vec4(col,1.0);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ vec4 blur1D(vec2 U, vec2 D, float rad)
|
||||
for( int k=0; k<N; k++ ) {
|
||||
x = float(k)/r -1.;
|
||||
t += g = exp(-2.*x*x );
|
||||
O += g * textureLod(iChannel0, (U + w*x*D) / iResolution.xy, z );
|
||||
O += g * texture(iChannel0, (U + w*x*D) / iResolution.xy );
|
||||
}
|
||||
return O/t;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ vec4 blur1D(vec2 U, vec2 D, float rad)
|
||||
for( int k=0; k<N; k++ ) {
|
||||
x = float(k)/r -1.;
|
||||
t += g = exp(-2.*x*x );
|
||||
O += g * textureLod(iChannel0, (U + w*x*D) / iResolution.xy, z );
|
||||
O += g * texture(iChannel0, (U + w*x*D) / iResolution.xy );
|
||||
}
|
||||
return O/t;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user