We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I use a shader to select a color.
Here it is for blueish for example:
Here for redish:
Now I wan't to blend the 2 in a LIGHTEST kind of fashion.
I tried blend(img, 0, 0, 512, 512, 0, 0, 512, 512, LIGHTEST);
but as expected this doesn't work.
Even worse, it makes crash JRE a lot it seems! (Is this a processing bug?).
What would be a good way to blend those results? I'm looking for a solution that is scalable (so also use the color select for 7 colors for example).
If possible: -a fast solution (so gpu prefered) -no edits to the current shader (if that makes sense to do)
PImage img;
PShader shader;
void settings() {
size(1512, 1000, P2D);
}
float[] targetColorRGB = new float[] {0.2, 0.4, 0.7};
float fuzzinessH = 0.1;
float fuzzinessS = 0.3;
float fuzzinessV = 0.3;
// for 2nd color:
float[] targetColor2RGB = new float[] {0.5, 0.3, 0.2};
float fuzziness2H = 0.1;
float fuzziness2S = 0.3;
float fuzziness2V = 0.3;
void setup() {
img = loadImage("http://" + "localhost:8888/catalogtree/helipad_detection/testImg2.png");
shader = loadShader("http://" + "localhost:8888/shaders/colorRangeHSV.glsl");
colorMode(RGB, 1, 1, 1, 1);
}
void draw() {
background(0);
shader(shader);
shader.set("targetColor", targetColorRGB, 3);
shader.set("fuzzinessH", fuzzinessH);
shader.set("fuzzinessS", fuzzinessS);
shader.set("fuzzinessV", fuzzinessV);
image(img, 512, 0, height, height);
//resetShader();
// now apply the shader again with different settings
shader(shader);
shader.set("targetColor", targetColor2RGB, 3);
shader.set("fuzzinessH", fuzziness2H);
shader.set("fuzzinessS", fuzziness2S);
shader.set("fuzzinessV", fuzziness2V);
//image(img, 512, 0, height, height);
// this also makes crash JRE a lot!
blend(img, 0, 0, 512, 512, 0, 0, 512, 512, LIGHTEST);
resetShader();
// the original
image(img, 0, 0, 512, 512);
}
The shader:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
#define PROCESSING_TEXTURE_SHADER
uniform sampler2D texture;
varying vec4 vertTexCoord;
// excepts a color in RGB
uniform vec3 targetColor;
uniform float fuzzinessH;
uniform float fuzzinessS;
uniform float fuzzinessV;
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
float norm(in float value, in float start, in float stop) {
return (value - start) / (stop - start);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
void main() {
vec3 texColor = texture2D(texture, vertTexCoord.st).rgb;
vec3 hsvTexColor = rgb2hsv(texColor);
vec3 hsvTargetColor = rgb2hsv(targetColor);
float distanceH = distance(hsvTexColor.r, hsvTargetColor.r);
float distanceS = distance(hsvTexColor.g, hsvTargetColor.g);
float distanceV = distance(hsvTexColor.b, hsvTargetColor.b);
/*
vec3 result;
if (distanceH < fuzzinessH && distanceS < fuzzinessS && distanceV < fuzzinessV) {
float normH = norm(distanceH, fuzzinessH, 0);
float normS = norm(distanceS, fuzzinessS, 0);
float normV = norm(distanceV, fuzzinessV, 0);
result = vec3(min(normH, min(normS, normV)));
}
else {
result = vec3(0);
}
*/
// the result looks the same without any if statements
// so we go for that cause shaders without if statements tend to be faster!
float normH = norm(distanceH, fuzzinessH, 0);
float normS = norm(distanceS, fuzzinessS, 0);
float normV = norm(distanceV, fuzzinessV, 0);
vec3 result = vec3(min(normH, min(normS, normV)));
gl_FragColor = vec4(result, 1.0);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Answers
did you try other blend modes? because i think ADD would also do what you want, given that you're only using greyscale images.
Add will give different results cause 128 grey + 128 grey is full white.
blend() calls loadPixels() internally which seems to be a little buggy in Processing 3. Anyways, blend() is CPU base, pretty slow and ignores any shader input/output. Use shader based blending instead:
I basically made the same shader you have but for some reason it does not work.
http://forum.processing.org/two/discussion/12869/use-an-extra-texture-with-a-shader#latest
Would be great if you can take a look.
Btw, would you have preferred if processing had the y axis flipped?
Does it work with the
#version 410
requirement used in your other thread?The problem is Processing is flipping anything along the Y axis, just so P2D and P3D have the same Y direction. It's a pain in the a** because Processing's flipping doesn't always work as expected and you have to code workarounds like in the snippet above.
I'm working slowly on my own framework and I'm thinking of matching the opelGL y axis. On the other hand, I think it makes more sense to have 0 at the top...
And yes! It works with
#version 410
, not sure if that was it cause I had a tiny other mistake and I have 2 many things open from today :) Anyway, I'm really happy it works!I think it makes more sense to use the same shader multiple times and blend those results with a filter. Although I didn't test for performance yet. My color select shader that can use an array of colors might be a lot faster...
Yeah, 0 at the top (and positive Y down) in 2D and in the middle (and positive Y up) in 3D like OpenGL and almost any other 3D environment.
Nice! Glad it works!
Sure, it should be faster. It would be optimal to handle the selecting and blending of multiple colors ranges in one shader pass.
I looked in the code for filer cause I wanted to filter only a specific area. Turns out it's written pretty bad.
https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java
Oh no. :(