Summary: The fundamental filters for 1D and 2D signals are introduced and examples are given in Processing.
Magnitude and phase response for the averaging filter![]() Figure 1 |
Magnitude and phase response of a second-order FIR filter
![]() Figure 2 |
Frequency response (magnitude) of first- (left) and
second- (right) order high-pass FIR filter.
Figure 3 |
Smoothing![]() Figure 4 |
// smoothed_glass
// smoothing filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html
size(210, 170);
PImage a; // Declare variable "a" of type PImage
a = loadImage("vetro.jpg"); // Load the images into the program
image(a, 0, 0); // Displays the image from point (0,0)
// corrupt the central strip of the image with random noise
float noiseAmp = 0.2;
loadPixels();
for(int i=0; i<height; i++) {
for(int j=width/4; j<width*3/4; j++) {
int rdm = constrain((int)(noiseAmp*random(-255, 255) +
red(pixels[i*width + j])), 0, 255);
pixels[i*width + j] = color(rdm, rdm, rdm);
}
}
updatePixels();
int n2 = 3/2;
int m2 = 3/2;
float val = 1.0/9.0;
int[][] output = new int[width][height];
float[][] kernel = { {val, val, val},
{val, val, val},
{val, val, val} };
// Convolve the image
for(int y=0; y<height; y++) {
for(int x=0; x<width/2; x++) {
float sum = 0;
for(int k=-n2; k<=n2; k++) {
for(int j=-m2; j<=m2; j++) {
// Reflect x-j to not exceed array boundary
int xp = x-j;
int yp = y-k;
if (xp < 0) {
xp = xp + width;
} else if (x-j >= width) {
xp = xp - width;
}
// Reflect y-k to not exceed array boundary
if (yp < 0) {
yp = yp + height;
} else if (yp >= height) {
yp = yp - height;
}
sum = sum + kernel[j+m2][k+n2] * red(get(xp, yp));
}
}
output[x][y] = int(sum);
}
}
// Display the result of the convolution
// by copying new data into the pixel buffer
loadPixels();
for(int i=0; i<height; i++) {
for(int j=0; j<width/2; j++) {
pixels[i*width + j] =
color(output[j][i], output[j][i], output[j][i]);
}
}
updatePixels();
Edge crispening![]() Figure 5 |
filtra() of the Sound Chooser presented in the
module Media Representation in
Processing in such a way that it implements the FIR
filter whose frequency response is represented in Figure 2. What happens if the filter is
applied more than once?
//filtra = new function
void filtra(float[] DATAF, float[] DATA, float a0, float a1) {
for(int i = 3; i < DATA.length; i++){
DATAF[i] = a0*DATA[i]+a1*DATA[i-1]+a0*DATA[i-2];//Symmetric FIR filter of the second order
}
}
for loop that repeats the
filtering operation a certain number of times, one can
verify that the effect of filtering is emphasized. This
intuitive result is due to the fact that, as far as the
signal is concerned, going through
// smoothing Gaussian filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html
size(200, 200);
PImage a; // Declare variable "a" of type PImage
a = loadImage("vetro.jpg"); // Load the images into the program
image(a, 0, 0); // Displays the image from point (0,0)
int n2 = 5/2;
int m2 = 5/2;
int[][] output = new int[width][height];
float[][] kernel = { {1, 4, 7, 4, 1},
{4, 16, 26, 16, 4},
{7, 26, 41, 26, 7},
{4, 16, 26, 16, 4},
{1, 4, 7, 4, 1} };
for (int i=0; i<5; i++)
for (int j=0; j< 5; j++)
kernel[i][j] = kernel[i][j]/273;
// Convolve the image
for(int y=0; y<height; y++) {
for(int x=0; x<width/2; x++) {
float sum = 0;
for(int k=-n2; k<=n2; k++) {
for(int j=-m2; j<=m2; j++) {
// Reflect x-j to not exceed array boundary
int xp = x-j;
int yp = y-k;
if (xp < 0) {
xp = xp + width;
} else if (x-j >= width) {
xp = xp - width;
}
// Reflect y-k to not exceed array boundary
if (yp < 0) {
yp = yp + height;
} else if (yp >= height) {
yp = yp - height;
}
sum = sum + kernel[j+m2][k+n2] * red(get(xp, yp));
}
}
output[x][y] = int(sum);
}
}
// Display the result of the convolution
// by copying new data into the pixel buffer
loadPixels();
for(int i=0; i<height; i++) {
for(int j=0; j<width/2; j++) {
pixels[i*width + j] = color(output[j][i], output[j][i], output[j][i]);
}
}
updatePixels();
// smoothed_glass
// smoothing filter, adapted from REAS:
// http://www.processing.org/learning/examples/blur.html
size(210, 170);
PImage a; // Declare variable "a" of type PImage
a = loadImage("vetro.jpg"); // Load the images into the program
image(a, 0, 0); // Displays the image from point (0,0)
// corrupt the central strip of the image with random noise
float noiseAmp = 0.1;
loadPixels();
for(int i=0; i<height; i++) {
for(int j=width/4; j<width*3/4; j++) {
int rdm = constrain((int)(noiseAmp*random(-255, 255) +
red(pixels[i*width + j])), 0, 255);
pixels[i*width + j] = color(rdm, rdm, rdm);
}
}
updatePixels();
int[][] output = new int[width][height];
int[] sortedValues = {0, 0, 0, 0, 0};
int grayVal;
// Convolve the image
for(int y=0; y<height; y++) {
for(int x=0; x<width/2; x++) {
int indSort = 0;
for(int k=-1; k<=1; k++) {
for(int j=-1; j<=1; j++) {
// Reflect x-j to not exceed array boundary
int xp = x-j;
int yp = y-k;
if (xp < 0) {
xp = xp + width;
} else if (x-j >= width) {
xp = xp - width;
}
// Reflect y-k to not exceed array boundary
if (yp < 0) {
yp = yp + height;
} else if (yp >= height) {
yp = yp - height;
}
if ((((k != j) && (k != (-j))) ) || (k == 0)) { //cross selection
grayVal = (int)red(get(xp, yp));
indSort = 0;
while (grayVal < sortedValues[indSort]) {indSort++; }
for (int i=4; i>indSort; i--) sortedValues[i] = sortedValues[i-1];
sortedValues[indSort] = grayVal;
}
}
}
output[x][y] = int(sortedValues[2]);
for (int i=0; i< 5; i++) sortedValues[i] = 0;
}
}
// Display the result of the convolution
// by copying new data into the pixel buffer
loadPixels();
for(int i=0; i<height; i++) {
for(int j=0; j<width/2; j++) {
pixels[i*width + j] =
color(output[j][i], output[j][i], output[j][i]);
}
}
updatePixels();
Magnitude and phase response of the IIR first-order filter![]() Figure 6 |
Magnitude and phase response of the second-order IIR filter ![]() Figure 7 |
filtra() of the Sound Chooser presented in module Media Representation in Processing
implements an IIR resonant filter. What is the relation
between