YOUR ACCOUNT

Login or Register to post new topics or replies
fisholith
Posts: 24
Filters: 2
Is there any way to prevent the median component from averaging colors?

The median component is really handy for smoothing boundaries between solid colored areas, but it occasionally outputs a pixel that's an average of two colors. I recognize that that's how the median function is supposed to work, but for certain tasks that can actually get in the way.



For example, suppose I have an image with 3 uniquely solid-colored regions. Say Red, Green, and Blue.

At some point, the Red area is to become Metal, Green is to become Stone, and Blue is to become Marble.

So far so good.
Now, say I want to smooth the edges of the colored regions, round off their corners and such. The only component that can smooth the region contours without altering the region colors is the median component, (as far as I know).

The problem is that sometimes the median component will output the average of two colors, and this introduces a new color that means nothing in the context of the Red-Green-Blue to Metal-Stone-Marble conversion.



I assume that what's happening is that the median component calculates an exact tie between colors for a pixel and so it takes the average. It would be nice if there was some way to force it to always pick just one of the tie colors in a tie situation.



So far the only possible solution that comes to mind is using a color scheme that can easily be quantized back to the correct set of meaningful colors. This way, if the median component pops out an averaged pixel, it can be snapped back to a meaningful color.

Any suggestions or ideas are welcome. smile:)

(Sorry about the odd line spacing, but when I initially had the text all together in big blocks it looked harder to follow.)
  Details E-Mail
Morgantao
Can't script

Posts: 2185
Filters: 20
It's hard to come up with a solution without seeing your nodes and toying with them, but perhaps adding a threshold somewhere before\after the median and recoloring would do the trick.
Another way would be to set an alpha for each color (Red, Gree, Blue) and smooth the corners of the alpha channel, so when you blend them back togather you already have a smooth region and don't need the median.
  Details E-Mail
SpaceRay
SpaceRay

Posts: 12299
Filters: 35
Quote
Morgantao wrote:
It's hard to come up with a solution without seeing your nodes and toying with them


Yes, is true, I think that if you want better help you could upload the .ffxml filter file you are making and so the person that wants to help you could download it and see much better how to fix it or how to help you better.

The filter you are making is inside the "my filters" folder. If you select your filter and then use the keys CTRL + L you will be directed automatically to the "my filters" folder and you will be able to copy it and upload here if you want.
  Details E-Mail
fisholith
Posts: 24
Filters: 2
Thanks for recommending that I upload an example, because in the course of building the example filter I planned to post, I actually realized what was going on, and what I'll need to do. Also, I didn't know about the Ctrl + L shortcut, that's pretty handy.


Short answer:
The FF Median Component never returns an average, as near as I can tell. The averaged-pixel-looking artifacts I was seeing resulted from the Median Component handling the RGB channels independently. (I can't believe that didn't occur to me sooner.) The solution, to rounding the contours of the colored regions via median, is to use unique shades of gray (rather than colors) to represent the region types.

Thanks again Morgantao and SpaceRay for the feedback. It looks like I've got things working correctly now. smile:)



The Details:
So, what was confusing me was that the Median Component looked like it would occasionally output an averaged pixel along boundaries, but not always. A median function only returns an average if it is given an even number of values.

e.g. median( 1 , 2 , 3 , 600 ) == 2.5

What struck me as odd was that if the FF Median Component samples are taken from a square region around a center pixel, then the number of samples should always be odd. (e.g. 3x3, 5x5, 7x7, and so on, and of course odd times odd is always odd.)

I couldn't figure out how it could sometimes return an average.
Well, it wasn't returning an average.
When I started building the example I was going to post here, I used only three colors. When I took my example Red, Green, and Blue color map, and ran it through the median, I started seeing these bid black areas show up between colors.

What I was seeing was the fact that the Median Component handles the Red, Green, and Blue channels separately. As far as the Median Component was concerned, each channel was just a gray scale image. Now it just so happens that the particular colors I was using in my actual full scale project were really good at hiding that fact, so I didn't realize it until I started building the RGB example I gave in the first post. (Yeah, I felt pretty stupid after realizing that of course the median handles the channels independently.)

Another way to look at it is that, for each region type, I had a specific color, essentially a 24-bit ID number (8-bit RGB) representing that region type (e.g. FF0000 = metal, 00FF00 = marble, etc). By running it through the Median Component, I was breaking the 24-bit number into 3 8-bit chunks, and applying a median to the low, middle, and high chunks separately.

This whole time I've been using the color map as what amounts to a texture index channel. While you can pass a grayscale index channel through a median with no problem and get the region smoothing effect I was looking for, it doesn't work so well if you try it with three separate RGB channels and expect the results to be cohesive.

The solution. I can extract a Hue channel from my color map, and use that as the aforementioned grayscale index channel. As long as the Saturation and Lightness channels are single solid shades of gray throughout, I'll get only the colors I started with when I recombine everything.

An alternative solution, is that I could actually combine the 8-bit R, G, and B channels of my original color map into a single 24-bit grey channel by stacking the bits in each channel end to end. Then each color would be represented as a unique shade of gray. I'm not sure if the Median Component can handle a single channel at 24-bit resolution, but it does have a "High Precision" option, so that might work, (as long as High Precision doesn't mean 16-bits.)


Anyway, thanks again Morgantao and SpaceRay for the feedback.
  Details E-Mail
Morgantao
Can't script

Posts: 2185
Filters: 20
You assume we know how a median function actualy works smile:D
Care to explain the e.g. median( 1 , 2 , 3 , 600 ) == 2.5 thingy?
  Details E-Mail
Casual Pixels
Dilettante

Posts: 96
A quick primer on the difference between mean, median, and mode.

Mean is what is often called average.

Mode is the quantity which appears most often - e.g. Mode(1, 2, 2, 3, 3, 3, 4) is 3.

Median is the middle value - e.g. Median(1, 3, 7, 8, 10) is 7.

However, while that works fine with an odd number of values, there is no "middle value" if there are an even number of values. In that case, one option is to take the average of the two "middle values" - e.g. Median (1, 2, 3, 600) is the average of (2, 3), which is 2.5.
  Details E-Mail
Morgantao
Can't script

Posts: 2185
Filters: 20
Thanks Gilles, that explanation is like an esspresso - short and good smile:)
  Details E-Mail
fisholith
Posts: 24
Filters: 2
Good explanation Gilles. smile:)
Sorry, I didn't think to include an explanation of median.

Incidentally, a "Mode" filter would be handy, though probably quite a bit slower than a median. Mode might also be a little tricky, in that it can return more than one value at a time, if multiple values happen to tie for most numerous.

e.g.
Mode( 1, 2, 3,3,3, 4,4,4 ,5,5 ) returns both 3 and 4.
  Details E-Mail
Indigo Ray
Adam

Posts: 1442
Filters: 82
So would a blur be a mean, the average of itself and the pixels near it?
  Details E-Mail
fisholith
Posts: 24
Filters: 2
Exactly right Indigo Ray.
Blur is an average, a "local" average. The "Radius" control specifies how local. and in the case of 2D Gaussian blur, it's a "weighted" average. That is, the farther you get from the center of that local area, the less a pixel contributes to the "average" color of the output pixel. The drop-off in pixel importance, as you move away from the center, is a Gaussian curve.

One of the really cool things about 2D Gaussian blur, is that it can be created from two 1D Gaussian blurs. You can pass an image through a horizontal 1D Gaussian blur, and pass the result through a vertical 1D Gaussian blur, and the result is a 2D Gaussian blur. And it will be uniform and rotationally symmetrical and everything, just like the built-in 2D Gaussian blur. To my knowledge this is a pretty special case. I know of no other 1D weighted blur curves that can be combined at right angles to make a rotationally symmetrical 2D blur with the same weighted curve. (There might be some others though, so if anyone knows of any I'd definitely be interested. Actually I should ask about that in another post.)

Similarly, if I recall, you can multiply a horizontal Gaussian black-to-white gradient, with a vertical Gaussian black-to-white gradient, and you get a Circular Gaussian gradient.

Gaussian's are fun like that. smile:)
  Details E-Mail
Morgantao
Can't script

Posts: 2185
Filters: 20
Quote
if I recall, you can multiply a horizontal Gaussian black-to-white gradient, with a vertical Gaussian black-to-white gradient, and you get a Circular Gaussian gradient


Yep, works like a charm!

  Details E-Mail

Join Our Community!

Filter Forge has a thriving, vibrant, knowledgeable user community. Feel free to join us and have fun!

33,712 Registered Users
+19 new in 30 days!

153,534 Posts
+31 new in 30 days!

15,348 Topics
+72 new in year!

Create an Account

Online Users Last minute:

14 unregistered users.