Introduction

Abstract

This Shock Filter sharpens edges of images by applying erosions or dilations depending on the sign of the Laplacian (or the so called Haralick-Canny edge detector).

Common sharpening algorithms often evolve the heat equation backwards (so called Gabor algorithm). This is done by convoluting the image with a mask with negative weights (like AviSynths build-in Sharpen function does). As this method violates a so called maximum principle (values of pixels calculated may be outside the value range of the original image), instabilities arise after some iterations, which can be observed as high oscillations.

This filter uses a morphological approach: In each iterations step, pixels are replaced by one of their neighbors. To avoid sharpening noise, a blurred version of the image is used only for the choice of each neighbor. This way high oscillations can be avoided even on large scales.

This plugin is designed to work with AviSynth 2.5 and is able to process YUY2 and YV12 colorspace clips.

Terms and Conditions for Execution, Copying, Distribution and Modification

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2, as published by the Free Software Foundation in June 1991 (see 'GNUGPLv2.txt').

There is no guaranty that the rights of third parties (including software patents) are not infringed upon by the execution or distribution of this program. Referring to section 8 of the General Public License, any use of this program (including all activities mentioned in section 0 and including execution) is restricted to countries where any of these activities do not infringe upon any such rights of third parties. It lies with the user to verify the compliance of his or her use (especially concerning but not limited to distribution) of this program with the rights of any third parties in the respective countries or regions.

This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License 2 along with this program; if not, write to the

Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

The mathematical formulars in this document require a HTML 4.0 compatible browser to be displayed correctly.

Usage

Loading the plugin

You need the file AVSShock.dll in your working directory. To load the plugin, your script should start with the following line:

LoadCPlugin("AVSShock.dll")

Shock Filter function

Shock(clip Clip, int "Steps", float "Strength", bool "Canny", float "Blur", int "BlurSize")

Shock applies the Shock Filter to the clip given.

Sample Scripts

This script opens a video file and applies the Shock Filter to sharpen it:

LoadPlugin("AviSynth_C.dll")
LoadCPlugin("AVSShock.dll")

AVISource("MyMovie.avi")
ConvertToYUY2
Shock(3)

This script gives you more control over the sharpening process:

LoadPlugin("AviSynth_C.dll")
LoadCPlugin("AVSShock.dll")

AVISource("MyMovie.avi")
ConvertToYV12
Shock(10,0.3,True,4.0,5)
The result will be a more accurate Shock Filter (ten iterations with a step size of 0.3) and the Canny edge detector will be used on a stronger blurred image.

If your clip as already YUY2 or YV12, you can ommit the color space conversion. E.g., this is the case when you load a clip with the well-known DGIndex.dll plugin:

LoadPlugin("DGIndex.dll")
LoadPlugin("AviSynth_C.dll")
LoadCPlugin("AVSShock.dll")

MPEG2Source("AnotherMovie.d2v")
Shock(3)

Mathematical Background

Shock Filter Equation for gray level images

In the following Du denotes the gradient of a gray level image u:R2→R, and D2u its Hessian. The two-dimensional Shock Filter equation for a gray level image u as stated by Osher and Rudin in [OR,(3.1)] reads:

ut = -Sign(Δu) ||Du||
with their F being the sign function (which satisfies [OR,(2.1)]), and Δu=uxx+uyy=tr(D2u) being the Laplacian of u (see [OR,(3.2c)]. This equation acts as morphological dilation in areas with negative Laplacian, and as erosion where the Laplace is positive.

The Laplacian Δu vanishes on edges of the image u (so-called Marr-Hildreth edge-detector). A probably more sophisticated method of edge detection is the Haralick-Canny edge-detector (as proposed in [OR,(3.2d)]). Here the Laplace operator is replaced by the second derivative in the direction of the gradient:

D2u⋅(Du,Du)

Inspired by [OR,(3.2b)] we can replace u by a convolution with a Gaussian convolution kernel Gs with standard deviation s in both edge-detectors:

Gs∗u
This effectively gives the following two equations, depending on the choice of the edge-detector
ut = -Sign(Δ(Gs∗u)) ||Du||   or   ut = -Sign(D2(Gs∗u)⋅(D(Gs∗u),D(Gs∗u)) ||Du||

Discretization on YUV color images

In each iteration step the following actions are performed:
  1. The blurring of the Y channel Gs∗u is done by applying a discrete convolution. The size of the kernel is determined by the argument BlurSize. To save some time, a one dimensional kernel is applied in both directions separately.
  2. The edge-detector determined by the Canny argument is applied to the blurred Y channel. This yields a sign (+1, -1 or 0) for each pixel.
  3. Based on the edge-detector signs gathered in the last step dilations or erosions are applied to each pixel of the original (unblurred) Y channel (or it is left unchanged). The discrete dilation replaces a pixel with the brightest neighbor, the erosion with the darkest one. The position of this neighbor is saved during this process.
  4. The U and V channels are modified accordingly: Each pixel is replaced by exactly the same neighbor pixel which has been choosen in the last step for the Y channel. So each luma value is accompanied by its chroma values. To treat subsampled chroma channels (e.g., in YV12 four pixels share one U and one V value), color channels are upsampled first, then modified as described above, then downsampled again by taking the mean value of all pixels which have to be merged.

The Strength argument is taken into account by using an appropriate convex combination of the original value and the new value of each pixel. Values outside the image (needed by the convolution and the morphological operations) are generated by mirroring the image at the border.

References

[OR] Stanley Osher, Leonid Iakov Rudin: Feature-Oriented Image Enhancement Using Shock Filters, SIAM Journal on Numerical Analysis, 27(4), pp. 919-940, 1990.

Version History

2006.12.19 Initial Version.
2007.01.04
  • Changed the Blur default from 2.0 to 1.0.
  • Changed the BlurSize default from Round(2∗Blur+1) to Ceil(2∗Blur).
  • Added this helpfile
  • Maybe memory consumption reduced: Source frame is released before second temporary frame is allocated. I don't know how AviSynth exactly handles frame allocation stuff.
  • About 25% speed up: Temporary memory was allocated by creating frames, now malloc is used.
  • Some minor code improvement. Numbering of pixels inside a 3×3 block is more elegant. Maybe undetectable speed up.
2007.01.25
  • Small extensions in the help file.
  • Small corrections in the help file html-layout.
  • Small corrections/improvements in code: Added forgotten calling-convention macro to Shock_Free, moved color space dependent undefs in CS-file.
  • Bug corrected: When an unknown color space was used (e.g. Y8), a "out of memory"-message came up.
  • Raised gcc optimization level from -O1 to -O3 (silly me).
2007.02.19
  • Simplified distinction of standard deviation and heat equation scale in Code.
  • GetFrame function rewritten. Size of binary reduced by 1 kB.
  • Added filter name to error messages.
  • Changed error handling in filter create function to avoid multiple memory allocation.
  • Small corrections in help file.
First public version.
2008.02.23
  • AviSynth_C.dll is not needed anymore (I updated MinGW (see the makefile) — thanks to Fizick).
  • Changed a lot floats to doubles, which increased blurring accuracy and speed.
  • Blur intensity is checked for too small values now.
  • Minor change to CreateGaussKernel function.
Wolfgang Boiger