Log in

View Full Version : New De-Rainbower Script: SmartSSIQ


LB
5th August 2005, 05:50
I've always been a fan of SSIQ. Not the new .dll version though. I found it doesn't work as well as the .vdf version. Remember, the vdf can be loaded in avisynth. The only downside is that it converts to RGB32 but you notice the rainbow removal more than negligable microscopic color changes.

I don't know a lot about color spaces and lumawhat and all that other crap that is really important when you're creating a rainbow remover, heh. But it's not important for what I've done. As of yet, I've tried every solution that works in Avisynth and there is no holy grail derainbower yet. So if you call yourself a good encoder, then you know that several de-rainbowers should be used in a project. So that is what SmartSSIQ is meant to be. As of yet, it shouldn't be used alone simply because it won't catch all the rainbows. But it "should" be used because it can catch rainbows that other filters miss.

So here is how SmartSSIQ works. In a nutshell, it's simply a script that uses SSIQ but only on the edgemask.

So here is the actual rundown of the script:

1. It applies VD_SmartSmoothIQ to the source
2. It then detects the edges using EdgeMask
3. Then it creates a mask of the edges on the SSIQ'd video
4. Finally, it layers the modified edges on top of the source

I've seen other people do something similar, but using MergedMask. The problem with that is, because SSIQ changes the colors in the video, the result of a MergedMask will be off-color. There is no way around that. So by using Layer(), no blending takes place and the resulting image should be identical in all respects except for the edges. :D

Here is the script:

#################################################################################
# This is a script which works with SSIQ. The basic problem with SSIQ is that
# it can alter the color on the entire picture, which is a very very bad thing.
# All we want to do is remove rainbows, while leaving everything else alone.
# This filter first applies SSIQ to the entire picture. Then it locates the edges.
# Finally, it layers ONLY the de-rainbowed edges onto the orig video.
#
#
# Filter Requirements: VD_SmartSmoothIQ()
#################################################################################
function SmartSSIQ(clip input, int "strength")
{

strength = Default(strength, 255) #processing strength, 0-255

inputrgb = input.ConvertToRGB32()

# apply rainbow remover to the entire video
derainbow = input.ConvertToRGB().VD_SmartSmoothIQ(11, 200, false).ConvertToRGB32()

# create an edge mask from the rainbow video
edgemask = input.Unsharpmask(100).edgemask(0, 255, 255, 255, "sobel").Inflate().GreyScale().Levels(0, 5, 255, 0, 255).ConvertToRGB32()

# create mask
maskedrainbow = mask(derainbow, edgemask)

# now layer the mask onto the input
result = layer(inputrgb, maskedrainbow, "add", strength)

return result
}

Now, there is a way we can make this even better. EdgeMask uses the Sobel method to detect edges. While it's really good, it can't compare to the Canny method. But at the moment, no one has produced a Avisynth edge detector using Canny.

Just so you can see the power of canny, check out this:

ORIG IMAGE (this is the actual image so you can save it and use it for testing to replicate my results)
http://img49.imageshack.us/img49/5388/0014sj.png

SOBEL IMAGE
http://img49.imageshack.us/img49/8396/0022xn.gif

CANNY IMAGE
http://img49.imageshack.us/img49/9000/0038li.gif

As you can see, the Canny method of edge detection is incredible. If someone were to code an Avisynth version then we might be able to reach the holy grail of DeRainbowing.

And you might be wondering how I made those images. Well, MatLab's Image Processing toolkit has both algorithms with full source code. I don't have the time to learn MatLab well enough to port the Canny method over to Avisynth (nor do I know enough about C++ and .dll creation to do so). But the tools are out there!

bill_baroud
5th August 2005, 09:21
just a good link on Canny's Method (well the first from google ;)) :
http://www.pages.drexel.edu/~weg22/can_tut.html

Sound not so fast to me... what the filter would have to do ? return a image mask like yours ?
If i'm bored this weekend, i'll try to take look at it.

LB
5th August 2005, 09:29
just a good link on Canny's Method (well the first from google ;)) :
http://www.pages.drexel.edu/~weg22/can_tut.html

Sound not so fast to me... what the filter would have to do ? return a image mask like yours ?
If i'm bored this weekend, i'll try to take look at it.

Speed shouldn't be a concern. Some people don't mind slow encodes, and pc's keep getting faster. But all-in-all, the algorithm isn't that slow. It might just drop you a few fps.

As for what the filter must do, it will need to output the image on the bottom. And if you could impliment this, it would not only help in the derainbow area, but also in a lot of other areas. Many filters rely on edge detection.

kassandro
5th August 2005, 13:00
just a good link on Canny's Method (well the first from google ;)) :
http://www.pages.drexel.edu/~weg22/can_tut.html

Sound not so fast to me... what the filter would have to do ? return a image mask like yours ?
If i'm bored this weekend, i'll try to take look at it.

Very good link. As I was recently concerned with edge masks, let me go through the various steps of the Canny edge detection method.

Step 1: Gaussian blur. Though I live near Gauss' brain (in alcohol since 150 years), this is not a good idea here. It only can blur noise. It is also not a good idea to take RemoveGrain(mode=4). While it can actually remove noise, it also may shave off some pixels from an edge resulting in a wrong location of the edge mask, which would be very bad. In my view, bilateral smoothing as implemented in TBilateral, is the right way to go. While it cannot remove noise completely, it is much better blurring, because unlike blurring it nicely steepens the gradients.

Step2 + Step3 + Step4: The task of finding the gradient can be implemented in a better way with the Prewitt method, which was pointed out to me by mg262.

Step 5: I ask myself, whether this step is reasonable. It really costs a lot of time and is very SSE hostile. It requires, that not only the gradient size, but also the gradient direction to be determined. Clearly, it makes edge mask thinner, but is this really good idea? An edge has always two sides, one with low pixel values and one with high pixels. Thus the edge mask curve should have a thickness of two and not one, as it is attempted in this step. While thin edge masks certainly look better, they are simply not appropriate.

Step 6 (binarisation): To get a binary mask from a continuous, one usually uses a threshold. A pixel is considered as an edge pixel if and only if the threshold is exceeded by the gradient size. As I reiterate all the time such simple threshold techniques are prone to unpleasant threshold artifacts. These are also discussed in the above article. Now Canny proposes a binarisation with two instead of one threshold, a high and a low threshold. If the gradient size is above the high threshold is marked as an edge pixel, but also those pixel which are above the low threshold and have a pixel with a high threshold in its 3x3 neighbourhood are marked as edge pixels as well. This is an excellent idea. I don't know, whether it is really, but I didn't know. It can be implemented in a very fast way along the lines of my RemoveGrain plugin (>1000 fps on my 2.66 GHZ CeleronD). The usefulness of such a filter goes well beyond edge detection.

I have already implemented Prewitt's original edge detection as well as my own variant of it with > 500 fps. Thus an improved version of Canny's algorithm without step 5 can be implemented essentially at the speed of TBilateral.

bill_baroud
5th August 2005, 14:40
Step 1 : i agree.... perhaps a configurable smoother would be a good idea (calling any filter that exist for avisynth)

Step 2+ : i don't know how many operators you use for prewitt, but sobel should be faster. I agree that the invtan() thing is overkill, another method should be used.

Step 5 : yep that why i say "not so fast" ... didn't sound mmxable ;)

You're taking the job ?

Chainmax
5th August 2005, 17:18
The Canny image looks awesome. If I'm not mistaken, there are lots of filters that use EdgeMask and they will probably greatly benefit from it. I anxiously await a release of SmartSSIQ with Canny edge detection, as I have a clip with quite nasty rainbowing that not even DeRainbow().Cnr2("xxx",4,5,255) could get rid of :).

LB
5th August 2005, 17:53
The Canny image looks awesome. If I'm not mistaken, there are lots of filters that use EdgeMask and they will probably greatly benefit from it. I anxiously await a release of SmartSSIQ with Canny edge detection, as I have a clip with quite nasty rainbowing that not even DeRainbow().Cnr2("xxx",4,5,255) could get rid of :).

In the meantime try this:

1. Before de-interlacing/ivtc place this line:
ConditionalFilter(last, last, last.DeDot(20,20,15,5), "YDifferenceFromPrevious()", ">", "5", false)

2. Right after the above line, place this line:
Bifrost(interlaced=true)

3. Finally, after de-interlacing/ivtc place this line:
SmartSSIQ()

Tell me how it works out. It should at least make a dent in it.

mg262
5th August 2005, 18:02
@LB,

I would like to see the effect of the Prewitt filter @kassandro mentions above on that image. I would do it myself, but as you say the picture is at a different size to the edge masks you provide... If you have a moment, would you mind either posting the original frame uncompressed or (given the bandwidth issues you mention) applying the filter? I have a link to a very primitive version of the Prewitt filter at

http://people.pwf.cam.ac.uk/mg262/posts/Prewitt.dll

I would recommend using @kassandro's version for any serious purposes, but this one should suffice to generate a mask in this case. The output of that filter will need binarisation to be applied to it... it depends on the image, but IIRC fairly low double-digit thresholds are appropriate.

The method used is very simple and is described on @kassandro`s forum here:

http://videoprocessing.11.forumer.com/viewtopic.php?p=150&sid=d3690dc5d350061f8ed99f7f44b7a899#150

... it's near the end of the thread. (And something I often forget to say... if anyone should happen to want the source code, you're welcome to it, though it's thoroughly unoptimised and again I would advise waiting for a better version.)

-- but don't worry if you don't have time to follow this up!

LB
5th August 2005, 18:27
@mg262

While I can't test out your filter (low on time), maybe you can. I re-captured the images and you can use the image above. It's the exact image (filesize and quality) I used to generate the two outputs. :)

mg262
5th August 2005, 19:04
Thank you for posting the picture. I've just tried, but realised its not straightforward to produce a comparable result because the simple prewitt method doesn't immediately produce edges that at a single pixel thick in the way that your method does. (In other words, I don't think the screenshots would contribute anything useful to this discussion...) This should have been obvious to me beforehand -- sorry! (But of course @kassandro's points above about this method still stand... it will be possible to get meaningful pictures to compare with, just with a bit more work.)

A separate point -- I don't think that using .GIF files in this kind of comparison necessarily gives a fair test... they are limited to a palette of 256 colours and the operation used to go from the full palette to the limited one may well interfere with the edge masking... perhaps a better way to save bandwidth is just to drop the chroma information, given that (I think) none of the filters we are currently discussing use it? i.e. if you grayscale and then convert to PNG, you would hopefully get a comparably small file.

LB
5th August 2005, 19:40
A separate point -- I don't think that using .GIF files in this kind of comparison necessarily gives a fair test... they are limited to a palette of 256 colours and the operation used to go from the full palette to the limited one may well interfere with the edge masking... perhaps a better way to save bandwidth is just to drop the chroma information, given that (I think) none of the filters we are currently discussing use it? i.e. if you grayscale and then convert to PNG, you would hopefully get a comparably small file.

Point taken. I've located the image in vdub, copied it into photoshop, converted to grayscale, then saved as png. Then I re-created the two results from the png and saved them as gif.

On a side but humerous note, I realised that the original program is called "SmartSmoothIQ" and since my filter is called SmartSSIQ, I guess the unabreviated version would be named SmartSmartSmoothIQ, hah!

Finally, this might really perk your interests. While I can't publicly post the MatLab code that produced my results becaues it's copyrighted that doesn't stop us from locating other solutions on the web. So I tracked down a JAVA implimentation of the Canny method. I have not tested it to find out how it fairs (so I don't know if its a proper implimentation of Canny). But since it's in Java, maybe it will be helpful to you mg262, or another coder, in jerryrigging a C++ version and thus avisynth dll. :cool:

http://homepages.inf.ed.ac.uk/rbf/HIPR2/flatjavasrc/Canny.java

kassandro
5th August 2005, 21:34
Step 2+ : i don't know how many operators you use for prewitt, but sobel should be faster. I agree that the invtan() thing is overkill, another method should be used.

Yes, Sobel is faster. Instead of 4 convolutions with Prewitt, you have to calculate only two. On the other hand Prewitt is certainly fast enough and is clearly superior.

mg262
5th August 2005, 21:40
briefly: interesting paper with section on edge finding

http://www.ph.tn.tudelft.nl/Courses/FIP/frames/fip-Segmenta.html

mg262
5th August 2005, 22:23
An edge has always two sides, one with low pixel values and one with high pixels. Thus the edge mask curve should have a thickness of two and not one, as it is attempted in this step.
Back around February/March, I tried implementing something that worked with edges of zero thickness... ie edges that ran between the pixels rather than through pixels. The results were quite disappointing compared to the corresponding solution with normal images, but that doesn't necessarily mean the method was flawed.

The representation is relatively simple... you need to store two bits for each pixel, one indicating whether there is a edge above the pixel and one indicating whether there's an edge to the left of it... and obviously you need to enlarge image width and height by one. (In the end, I ditched the filter that was a small part of because I wasn't happy with the results... but that's another story.)

kassandro
6th August 2005, 10:43
In view of the new information I have to revise my earlier comments about the Canny edge detection.
Firstly, I would like to remark that
http://homepages.inf.ed.ac.uk/rbf/H...asrc/Canny.java
is a rather accurate, though inefficient implementation of the algorithm described in
http://www.pages.drexel.edu/~weg22/can_tut.html
The Java program even helped me to better understand the above description. In particular, I know now that step 6 of the algorithm is more sophisticated. What I said earlier, was only the beginning. Unfortunately a full implementation of step will be much slower than 1000 fps.
Step 5 + 6 are the innovative part of the algorithm and are primarily responsible for the beautiful masks generated by this algorithm. Step 5 makes the curve thin and step 6 fills small gaps. Step 1-4 can be easily replaced by other gradient edge masking techniques like that of Prewitt.

While the Canny method certainly yields the most beautiful masks, I still doubt, whether the Canny method is really suitable for the tasks, masks are usually used for, namely to protect edges from getting filtered. For this purpose, the masks are simply too thin and one has to make them thicker, but then will look less beautiful. Nevertheless step 6 is a very good idea, which should be persued further.

mg262
6th August 2005, 15:41
@kassandro,

Do you think it would be possible to tweak the thing to produce closed contours? (I will try and root out/regenerate some screenshots to explain why that might be useful shortly, but I need to rerun a lot of the relevant scripts in light of the misplaced signs-bug you found... thank you again.)

Chainmax
6th August 2005, 17:57
Step 5 makes the curve thin and step 6 fills small gaps. Step 1-4 can be easily replaced by other gradient edge masking techniques like that of Prewitt.

While the Canny method certainly yields the most beautiful masks, I still doubt, whether the Canny method is really suitable for the tasks, masks are usually used for, namely to protect edges from getting filtered. For this purpose, the masks are simply too thin and one has to make them thicker, but then will look less beautiful. Nevertheless step 6 is a very good idea, which should be persued further.

Well, if Canny's masks are too thin and step 5 thins the curve, can't that be solved by either avoiding step 5 or doing its exact opposite after step 6?

By the way, would it be possible to make a line thinning filter out of step 5? I would love a good alternative to aWarpSharp.

kassandro
6th August 2005, 20:24
Do you think it would be possible to tweak the thing to produce closed contours? (I will try and root out/regenerate some screenshots to explain why that might be useful shortly, but I need to rerun a lot of the relevant scripts in light of the misplaced signs-bug you found... thank you again.)
As the algorithm is now, this is certainly not the case. Also you have the problem that solid objects may not only be limited by edges but also by the frame boundaries. Closedness of a curve is a global property, while the Canny alogrithm like most image processing algorithms is local. For instance, RemoveGrain uses only the 3x3 square around a pixel to determine the output value of a pixel. If I want a closed contour as an edge mask for a solid body, I would first select an inner point. Then I would look at its 8 neighbour for large gradients. If a large gradient is found, then that pixel is selected as an edge pixel, otherwise we look again at the 8 neighbours (without those pixels which have been already handled at an earlier stage) of that pixel for the gradient size. For pixels at the frame boundary there are of course fewer neighbours. That algorithm will certainly terminate at some point. While one cannot expect monster speed from such an algorithm, the speed would probably tolerable (above 5fps on my PC). The problem, of course, is the selection of the inner point, which requires interaction. Consequently such a algorithm is not feasible for Avisynth, but it may be for a PS plugin. In Photoshop there are already similar algorithms. For instance, the algorithm to fill a closed curve with a fixed color or pattern, proceeds in a similar way.


Well, if Canny's masks are too thin and step 5 thins the curve, can't that be solved by either avoiding step 5 or doing its exact opposite after step 6?

I think and hope that this is the case.


By the way, would it be possible to make a line thinning filter out of step 5? I would love a good alternative to aWarpSharp.

I don't know the details of aWarpSharp, but often sharpeners use gradients as well (they always use them at least in a hidden way) and then a step 5 type algorithm is feasible. On the other hand, if you sharpen at too few pixels, it probably will look quite ugly.

mg262
6th August 2005, 23:21
I phrased that badly... I should have said more closed contours. Looking at the screenshot above, it seems as if there are a lot of contours that are almost closed, but are missing a pixel or two (for example look at the roof tiles). It wasn't clear to me whether this was an artefact of steps five and six that could be removed by tweaking the algorithm slightly...

I did end up ditching the edge-mask-based filter in favour of a flood fill based approach, precisely because the former was too sensitive to certain kinds of local error (and that's also why I put down Prewitt -- at the time I wasn't confident enough with edge masks to post it) -- but the edge-mask-using region-based approach was surprisingly effective under some circumstances, so I'm keeping it at hand, as a benchmark if nothing else. And it will be interesting to try with better/more appropriate edge masks as they become available. I will try and generate some screenshots with the prewitt method tomorrow...

(The flood fill approach has its own awkwardnesses including the requirement for symmetry breaking which you mention, which I've been thinking my way around, but I don't want to drag this thread OT so I will leave that aside.... but on the off chance that you haven't seen it I just want to throw in a link to the standard ² seed fill" method which is both fast and very concise... http://ftp.arl.mil/ftp/pub/Gems/original/SeedFill.c )

LB
7th August 2005, 05:03
You know, who made masktools? The person that did, obviously knows edge filtering really well. Maybe we should ask him what he thinks about canny and the whole edge-thickness issue. He might be able to give us a list of filters that use edgemask and the thickness they work well at.

MG262: you mentioned "flood fill" and I don't think you meant it in the way I'm about to use the term, but what about analyzing the color areas? So far all the methods of edge detection rely on B&W images. An added step (not sole step, but merely an added step for accuracy) could be an option to enable color matching. The algorithm would try to find areas of similar color and maybe tweak the edges as a result. This might be able to help in finding the contours a little better. Granted though, this idea is probably only well suited for anime as it tends to have blocks all one color.

mg262
7th August 2005, 09:58
MaskTools is by kuruso and manao, iirc.

I have tried using colour and found that in practice it messed up more cases than it solved... IMO there are a few problems:

- For DVD source, each of U and V only stores 1/4 as much information as Y.
- Depending on what the original source was, the colour might be heavily frequency limited as well, which further reduces the information.
- The eye isn't very sensitive to chroma information as compared to luma...

take any source and try merging in the luma from a grey clip; something like this (which I haven't tested right now, so I hope it's okay...)
mergeluma(blankclip(color = $808080))
the results are quite surprising.

That's not to say that colour shouldn't be used at all... in fact I think that the right solution would use colour somehow, but it's not at all obvious to me how it should be utilised.

kassandro
7th August 2005, 19:40
I phrased that badly... I should have said more closed contours. Looking at the screenshot above, it seems as if there are a lot of contours that are almost closed, but are missing a pixel or two (for example look at the roof tiles). It wasn't clear to me whether this was an artefact of steps five and six that could be removed by tweaking the algorithm slightly...

Yes, I think you can improve this by lowering the lower threshold in step 6. Of course, if that threshold is too low, non-edge pixels may be marked as well. This is a problem with all edge masking: you have to fine tune the thresholds by visual inspection - not very Avisynth friendly. I am thinking a little bit about local, adpative thresholds as in the local constrast adjustments discussed at the end of the cited article from Delft University. Of course, that further complicates the algorithm, but one set of thresholds for an entire video may simply not be appropriate. In some cases you may even need different thresholds in different areas of a single picture.

mg262
7th August 2005, 22:31
Right, so, screenshots as promised. I took some animation and ran it through the Prewitt filter to produce an edge mask:

http://people.pwf.cam.ac.uk/mg262/posts/separation/frame 329.jpg http://people.pwf.cam.ac.uk/mg262/posts/separation/frame 329 mask.PNG

The original and the edge mask were fed into a filter which considered the regions defined by the edge mask, computed one of a choice of accumulative properties on that region, and coloured each region based on some function of the relevant property. For example, I could colour regions by their area or by the average colour of the pixel in the region (which is quite a useful denoising operation on animation foreground). The main case I was working on was to look at the variance of the pixels in the region, and select regions with low variance, which roughly means flat blocks of colour, colouring those white to produce a foreground mask (and similarly for the background). The resulting forward/background for the above image were as follows:

http://people.pwf.cam.ac.uk/mg262/posts/separation/frame 329 foreground.jpg http://people.pwf.cam.ac.uk/mg262/posts/separation/frame 329 background.jpg

(I have glossed over a range of details, such as e.g. the use of the above filter to remove mask components without any "holes"... but these are not relevant to the current discussion.)

Splitting the image like allows a very wide range of techniques exploiting the very structured nature of animation (or at least, the kind of animation I'm concerned with)... but that is not something I am going to go into here. Unfortunately, the process didn't work anywhere near as well on other clips or even on other frames of this clip, so (back in March or so) I abandoned the method and the filter in favour of flood-fill/graph based alternatives. The source of the filter and the filter are available, but please be very aware that I consider this to be a failed experiment. It's only here to highlight the possible usefulness of thin masks.

Edit: I've just looked at the Java sample, and I have a clearer idea of what's happening... it seems to me that step 5 is not only compatible with the Prewitt algorithm but fits with it much more naturally than with the Canny algorithm; step 6 can be used with any algorithm (provided that it is applied before binarisation of course) and probably belongs in a separate plug-in.

mg262
8th August 2005, 06:33
Well, I couldn't sleep so I threw together a version with an option for a thin mask:

http://people.pwf.cam.ac.uk/mg262/posts/Prewitt_08Aug05.dll

Prewitt(bool thin = false)

That returnsa greyscale mask, suitable for binarisation or the hysteresis type method of step six. I would recommend using levels(0, 1, 128, 0, 255, coring = false) or the like to make the output clearer.

I don't mean it as more than a reference implementation.
It's still very possible that there are silly bugs in this...

The code is in a mess but you are all welcome to it... just PM me if you want it.

Edit: The reference says this:
Nonmaximum suppression is used to trace along the edge in the edge direction and suppress any pixel value (sets it equal to 0) that is not considered to be an edge.... but on re-reading that doesn't quite make sense. It seems to me that we should be tracing not in the edge direction (i.e. along the edge) but rather at 90° to it? [I.e. if you have a horizontal edge, you want to suppress a pixel precisely when it is smaller than the number above it or the number below it...] Certainly that version seems to be the one that produces the right output, so is the one I've put up.

It's also probably worth considering this: for the Prewitt algorithm, which takes the maximum of four normal edge masks (one horizontal, one vertical, two diagonal), it makes more sense to apply the non-maximum suppression before the maximum is taken, both conceptually and to facilitate SIMD optimisation. (That's not the way I have implemented it at present.)

bill_baroud
8th August 2005, 08:26
looking at your screenshot, i was thinking .... throwing an erosion/dilatation at it would make the edges "cleaner", suppressing "peaks" and filling gap, making the edge thicker depending on how much you dilate. Don't know if it's the goal, though ;)

Btw your "seed filling" is it something similar to "water shed" in mathematical morphology (http://cmm.ensmp.fr/~beucher/wtshed.html) ?

Mug Funky
8th August 2005, 15:50
just thinking: prewitt and canny edge detection (hitherto unknown to me... learn something every day :)) are all well and good, but shouldn't a de-rainbower's edge detection work in a similar way to what caused the rainbows in the first place? a lot of it is aliasing, which cannot be reversed, but rainbowing on the whole only happens in areas of high frequency - not just edges as defined by canny/sobel/prewitt, but anywhere the frequency is high enough for crosstalk to show up. [edit] including textures.

it seems to me that it would be faster to mimic this. though i can't think of how off the top of my head right now :)

now... how are rainbows caused _exactly_? if we can get a good model of that then a filter could find the places it's likely to show up and nuke them there without too much fuss.

dedot is a good example of a really simple and effective filter, however it's not always completely successful because it's removal technique assumes that the crawls will cancel exactly, which is not always the case (there's weird asymmery for some reason... analog distortion? i suppose TVs aren't completely linear after all).

hmm. i'm too sleepy to have a "eureka" moment, but if i do i'll post it here right away :)

btw, that edge detection is still a kickass idea :)

Chainmax
8th August 2005, 16:54
I don't know the details of aWarpSharp, but often sharpeners use gradients as well (they always use them at least in a hidden way) and then a step 5 type algorithm is feasible. On the other hand, if you sharpen at too few pixels, it probably will look quite ugly.

I phrased myself wrong, what aWarpSharp does is line thinning, so what I'd like to know is if there would be a way to implement a line thinning filter out of step 5.

Manao
8th August 2005, 19:49
Hi guys,

I read quickly that thread that seems interesting. I made a filter that might be handy for you. It basically works like DEdgeMask, except that instead of 2 low / high thresholds, it takes 2 other clips. Each clips contains local thresholds for each pixels.

Like that, doesn't sound usefull.

But now, let's say you want adaptive thresholds taking local contrast into account. Well, local min & max can be obtained through inpand() and expand(). Difference can be made with YV12LUTxy or YV12Subtract. And voilą, you've got a threshold clip containing local contrasts.

Here is the syntax :

DEdgeMask2(clip source, clip low_thres, clip high_thres, string matrix, int int divisor, ...)

Here is the set of filters :

http://manao4.free.fr/MaskTools-v1.5.8.zip

Tell me if it works ( it should ) and if it helps ( it... well, i don't know, i'll let you do the thinking :p )

Edit : btw, i use this thread to remind you that a hysteresis filter is already implemented in the MaskTools. I wouldn't call it fast, but at least, you can play with it.

mg262
9th August 2005, 10:24
@bill_baroud,

At the moment the goal is toseparate background and foreground as precisely as possible (and in some pathological cases the boundary can be quite complicated), so I can't smooth... thanks for the idea though!

Watersheds: flood filling is similar but faster...but thank you very much for that link! That site is absolutely jam-packed full of interesting ideas.

@Mug Funky, high pass filter? There's one in the set of Photoshop plug-ins found here... http://members.ozemail.com.au/~binaryfx/PSTV_convolcorner.html as well as many many edge masks to play around with. (And it is done in such a way that the method for each one is extractable so they can be converted to AVISynth.)

Edit: Thinking about what happens when you have two edges meeting each other, I'm becoming less and less confident about the method used in both the canny algorithm and the prewitt implementation above... I think you can end up with cases where a horizontal edge is suppressed by a vertical edge that comes to meet it (but doesn't cross it)... indeed, I think this is quite possibly the reason for some (but not all) of the one pixel holes I was referring to in the image in the original post. so I think prewitt with maximum after suppression is definitely the way to go.

LB
10th August 2005, 04:13
just thinking: prewitt and canny edge detection (hitherto unknown to me... learn something every day :)) are all well and good, but shouldn't a de-rainbower's edge detection work in a similar way to what caused the rainbows in the first place? a lot of it is aliasing, which cannot be reversed, but rainbowing on the whole only happens in areas of high frequency - not just edges as defined by canny/sobel/prewitt, but anywhere the frequency is high enough for crosstalk to show up. [edit] including textures.

btw, that edge detection is still a kickass idea :)

I think that's a great idea, but no one has made a solution yet. Though, in most anime, rainbows only occur on the edges (most, not all). Also, there are tons of filters that rely on edge detection, so the creation of a canny edge detector won't simply help SmartSSIQ, but a whole host of other filters.

mg262
10th August 2005, 05:28
I think that's a great idea, but no one has made a solution yet.The thinned prewitt version above + 2x binarize + the hysteresymask @manao reminded us about gives an attempt at a solution... I haven't had time to play with a thresholds enough to see how it compares to canny.