Skip to content

Instantly share code, notes, and snippets.

@Ajasra
Created July 30, 2020 05:34
Show Gist options
  • Save Ajasra/f6990eda2d857ee96f94db985dddd82e to your computer and use it in GitHub Desktop.
Save Ajasra/f6990eda2d857ee96f94db985dddd82e to your computer and use it in GitHub Desktop.
// BLUR
#define blur = mat3(
0.0, 0.2, 0.0,
0.2, 0.2, 0.2,
0.0, 0.2, 0.0
)
#define factor 1.0;
#define bias 0.0;
// bigger blur
double filter[filterHeight][filterWidth] =
{
0, 0, 1, 0, 0,
0, 1, 1, 1, 0,
1, 1, 1, 1, 1,
0, 1, 1, 1, 0,
0, 0, 1, 0, 0,
};
double factor = 1.0 / 13.0;
double bias = 0.0;
// gaussian
double filter[filterHeight][filterWidth] =
{
1, 2, 1,
2, 4, 2,
1, 2, 1,
};
double factor = 1.0 / 16.0;
double bias = 0.0;
// Approximation to 5x5 kernel:
#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
1, 4, 6, 4, 1,
4, 16, 24, 16, 4,
6, 24, 36, 24, 6,
4, 16, 24, 16, 4,
1, 4, 6, 4, 1,
};
double factor = 1.0 / 256.0;
double bias = 0.0;
// motion blur
#define filterWidth 9
#define filterHeight 9
double filter[filterHeight][filterWidth] =
{
1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1,
};
double factor = 1.0 / 9.0;
double bias = 0.0;
// find edges
#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
0, 0, -1, 0, 0,
0, 0, -1, 0, 0,
0, 0, 2, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
};
double factor = 1.0;
double bias = 0.0;
// vertical edges
#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
0, 0, -1, 0, 0,
0, 0, -1, 0, 0,
0, 0, 4, 0, 0,
0, 0, -1, 0, 0,
0, 0, -1, 0, 0,
};
double factor = 1.0;
double bias = 0.0;
// 45degree edges
#define filterWidth 5
#define filterHeight 5
double filter[filterHeight][filterWidth] =
{
-1, 0, 0, 0, 0,
0, -2, 0, 0, 0,
0, 0, 6, 0, 0,
0, 0, 0, -2, 0,
0, 0, 0, 0, -1,
};
double factor = 1.0;
double bias = 0.0;
// all directions
#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
-1, -1, -1,
-1, 8, -1,
-1, -1, -1
};
double factor = 1.0;
double bias = 0.0;
//sharpen
#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
-1, -1, -1,
-1, 9, -1,
-1, -1, -1
};
double factor = 1.0;
double bias = 0.0;
#define filterWidth 5
#define filterHeight 5
// sharpen 2
double filter[filterHeight][filterWidth] =
{
-1, -1, -1, -1, -1,
-1, 2, 2, 2, -1,
-1, 2, 8, 2, -1,
-1, 2, 2, 2, -1,
-1, -1, -1, -1, -1,
};
double factor = 1.0 / 8.0;
double bias = 0.0;
// emboss
#define filterWidth 3
#define filterHeight 3
double filter[filterHeight][filterWidth] =
{
-1, -1, 0,
-1, 0, 1,
0, 1, 1
};
double factor = 1.0;
double bias = 128.0;
// author : csblo
// Work made just by consulting :
// https://en.wikipedia.org/wiki/Kernel_(image_processing)
// Define kernels
#define identity mat3(0, 0, 0, 0, 1, 0, 0, 0, 0)
#define edge0 mat3(1, 0, -1, 0, 0, 0, -1, 0, 1)
#define edge1 mat3(0, 1, 0, 1, -4, 1, 0, 1, 0)
#define edge2 mat3(-1, -1, -1, -1, 8, -1, -1, -1, -1)
#define sharpen mat3(0, -1, 0, -1, 5, -1, 0, -1, 0)
#define box_blur mat3(1, 1, 1, 1, 1, 1, 1, 1, 1) * 0.1111
#define gaussian_blur mat3(1, 2, 1, 2, 4, 2, 1, 2, 1) * 0.0625
#define emboss mat3(-2, -1, 0, -1, 1, 1, 0, 1, 2)
#define factor 1
#define bias 0
// Find coordinate of matrix element from index
vec2 kpos(int index)
{
return vec2[9] (
vec2(-1, -1), vec2(0, -1), vec2(1, -1),
vec2(-1, 0), vec2(0, 0), vec2(1, 0),
vec2(-1, 1), vec2(0, 1), vec2(1, 1)
)[index] / iResolution.xy;
}
// Extract region of dimension 3x3 from sampler centered in uv
// sampler : texture sampler
// uv : current coordinates on sampler
// return : an array of mat3, each index corresponding with a color channel
mat3[3] region3x3(sampler2D sampler, vec2 uv)
{
// Create each pixels for region
vec4[9] region;
for (int i = 0; i < 9; i++)
region[i] = texture(sampler, uv + kpos(i));
// Create 3x3 region with 3 color channels (red, green, blue)
mat3[3] mRegion;
for (int i = 0; i < 3; i++)
mRegion[i] = mat3(
region[0][i], region[1][i], region[2][i],
region[3][i], region[4][i], region[5][i],
region[6][i], region[7][i], region[8][i]
);
return mRegion;
}
// Convolve a texture with kernel
// kernel : kernel used for convolution
// sampler : texture sampler
// uv : current coordinates on sampler
vec3 convolution(mat3 kernel, sampler2D sampler, vec2 uv)
{
vec3 fragment;
// Extract a 3x3 region centered in uv
mat3[3] region = region3x3(sampler, uv);
// for each color channel of region
for (int i = 0; i < 3; i++)
{
// get region channel
mat3 rc = region[i];
// component wise multiplication of kernel by region channel
mat3 c = matrixCompMult(kernel, rc);
// add each component of matrix
float r = c[0][0] + c[1][0] + c[2][0]
+ c[0][1] + c[1][1] + c[2][1]
+ c[0][2] + c[1][2] + c[2][2];
// for fragment at channel i, set result
fragment[i] = r * factor + bias;
}
return fragment;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
// Convolve kernel with texture
vec3 col = convolution(emboss, iChannel0, uv);
// Output to screen
fragColor = vec4(col, 1.0);
}
#define filterWidth 3
#define filterHeight 3
//color arrays
int red[filterWidth * filterHeight];
int green[filterWidth * filterHeight];
int blue[filterWidth * filterHeight];
int selectKth(int* data, int s, int e, int k);
int main(int argc, char *argv[])
{
//load the image into the buffer
unsigned long w = 0, h = 0;
std::vector<ColorRGB> image;
loadImage(image, w, h, "pics/noise.png");
std::vector<ColorRGB> result(image.size());
//set up the screen
screen(w, h, 0, "Median Filter");
ColorRGB color; //the color for the pixels
//apply the filter
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int n = 0;
//set the color values in the arrays
for(int filterY = 0; filterY < filterHeight; filterY++)
for(int filterX = 0; filterX < filterWidth; filterX++)
{
int imageX = (x - filterWidth / 2 + filterX + w) % w;
int imageY = (y - filterHeight / 2 + filterY + h) % h;
red[n] = image[imageY * w + imageX].r;
green[n] = image[imageY * w + imageX].g;
blue[n] = image[imageY * w + imageX].b;
n++;
}
int filterSize = filterWidth * filterHeight;
result[y * w + x].r = red[selectKth(red, 0, filterSize, filterSize / 2)];
result[y * w + x].g = green[selectKth(green, 0, filterSize, filterSize / 2)];
result[y * w + x].b = blue[selectKth(blue, 0, filterSize, filterSize / 2)];
}
//draw the result buffer to the screen
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
pset(x, y, result[y * w + x]);
}
//redraw & sleep
redraw();
sleep();
}
// selects the k-th largest element from the data between start and end (end exclusive)
int selectKth(int* data, int s, int e, int k) // in practice, use C++'s nth_element, this is for demonstration only
{
// 5 or less elements: do a small insertion sort
if(e - s <= 5)
{
for(int i = s + 1; i < e; i++)
for(int j = i; j > 0 && data[j - 1] > data[j]; j--) std::swap(data[j], data[j - 1]);
return s + k;
}
int p = (s + e) / 2; // choose simply center element as pivot
// partition around pivot into smaller and larger elements
std::swap(data[p], data[e - 1]); // temporarily move pivot to the end
int j = s; // new pivot location to be calculated
for(int i = s; i + 1 < e; i++)
if(data[i] < data[e - 1]) std::swap(data[i], data[j++]);
std::swap(data[j], data[e - 1]);
// recurse into the applicable partition
if(k == j - s) return s + k;
else if(k < j - s) return selectKth(data, s, j, k);
else return selectKth(data, j + 1, e, k - j + s - 1); // subtract amount of smaller elements from k
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment