I'm looking for a quick and dirty, very efficient edge detection shader or edge mesh for a video application. Since this will be done on a mobile device, I need something that places performance over accuracy. I'll be blurring the output anyway, and all edge detection algorithms I've seen tend to be done by comparing against a certain threshold an original image and a blurred one. I think it's the blur that tends to cause the most performance issues.
I have a function like this working:
vec4 edge()
{
float K00 = -1.0;
float K01 = -2.0;
float K02 = -1.0;
float K10 = 0.0;
float K11 = 0.0;
float K12 = 0.0;
float K20 = 1.0;
float K21 = 2.0;
float K22 = 1.0;
vec2 ox = vec2 (0.0,0.0);
ox[0] = width;
vec2 oy = vec2 (0.0,0.0);
oy[1] = height;
float g00, g01, g02;
float g10, g11, g12;
float g20, g21, g22;
vec4 CC;
vec2 PP = TextureCoord - oy;
CC = texture2D(blurredFrame, vec2(PP-ox));
g00 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP));
g01 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP+ox));
g02 = getGrey(CC);
PP = TextureCoord;
CC = texture2D(blurredFrame, vec2(PP-ox));
g10 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP));
g11 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP+ox));
g12 = getGrey(CC);
PP = TextureCoord + oy;
CC = texture2D(blurredFrame, vec2(PP-ox));
g20 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP));
g21 = getGrey(CC);
CC = texture2D(blurredFrame, vec2(PP+ox));
g22 = getGrey(CC);
float sx = 0.0, sy = 0.0;
sx = sx + g00 * K00;
sx = sx + g01 * K01;
sx = sx + g02 * K02;
sx = sx + g10 * K10;
sx = sx + g11 * K11;
sx = sx + g12 * K12;
sx = sx + g20 * K20;
sx = sx + g21 * K21;
sx = sx + g22 * K22;
sy = sy + g00 * K00;
sy = sy + g01 * K10;
sy = sy + g02 * K20;
sy = sy + g10 * K01;
sy = sy + g11 * K11;
sy = sy + g12 * K21;
sy = sy + g20 * K02;
sy = sy + g21 * K12;
sy = sy + g22 * K22;
float dist = sqrt(sx * sx + sy * sy);
return dist > threshold ? vec4 (0,0,0,1) : vec4 (1,1,1,1);
}
All examples I have seen are like this and seem to focus on a desktop platform--too involved and costly to get a decent framerate on an iPhone or Android device. This will be for a 2d application only, and speed is key.
Any ideas to make this more efficient, or perhaps a better alternative? Thanks everyone.
Not sure if I know of a different algorithm.
But, some suggestions come to mind:
I have a couple of ideas about optimizing the texture samples:
- No need to sample where the corresponding coefficient is zero (K1*).
- Use texture2DOffset instead of texture2D. It accepts constant integer offsets, allowing the driver to predict your access pattern more effectively.
- You are weighting the samples. You can use built-in linear filtering mechanics to do that. For example, to get a sum of samples in two neighbour texels you can sample linearly (only once) between them and multiply the result by 2. This variant excludes previous suggestion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With