Data Structures | |
struct | VCEdgeCfg |
Edge Configuration Data Holder. More... | |
Functions | |
I32 | gradient_2x2 (image *src, image *dst) |
Vector Gradient Image (using Robert's Cross Routine). More... | |
I32 | init_gradient_2x2 () |
Memory Initialization for 2×2 Pixel Based Vector Gradient Image Calculation. More... | |
void | deinit_gradient_2x2 () |
Memory Deinitialization for 2×2 Pixel Based Vector Gradient Image Calculation. More... | |
I32 | gradient_3x3 (image *src, image *dst) |
Vector Gradient Image (using Sobel Routine). More... | |
I32 | init_gradient_3x3 () |
Memory Initialization for 3×3 Pixel Based Vector Gradient Image Calculation. More... | |
void | deinit_gradient_3x3 () |
Memory Deinitialization for 3×3 Pixel Based Vector Gradient Image Calculation. More... | |
I32 | gradient_3x3_thresh (image *src, image *dst, I32 thresh) |
Simple Gradient Image (using Sobel Routine with Threshold). More... | |
I32 | init_gradient_3x3T () |
Memory Initialization for 3×3 Pixel Based Vector Gradient Image Calculation. More... | |
void | deinit_gradient_3x3T () |
Memory Deinitialization for 3×3 Pixel Based Vector Gradient Image Calculation. More... | |
I32 | edge (image *src, image *dst, I32 type, F32 sigma, I32 BinMode, I32 MinContrast, F32 fthresh, I32 binar_value) |
Image Edge Calculation. More... | |
I32 | nonmax_suppress (image *src, image *dst) |
Vector Non-Maximum Suppression. More... | |
F32 | GradientAngle (image *imgGrad, I32 kx) |
Calculates the Main Direction in a Gradient Image. More... | |
I32 | block_orientation_histogram_16x16_threshold (image *src, image *dst, U8 magThr, U8 dirBg) |
Calculation of the Block Orientation Histogram with Magnitude Threshold. More... | |
I32 | block_orientation_histogram_16x16 (image *src, image *dst) |
Calculation of the Block Orientation Histogram. More... | |
#define | edge_canny(src, dst, binar_value) edge(src, dst, 4, 0.625, -2, 5, 0.10, binar_value) |
Canny Edge Detection (Macro). More... | |
#define | edge_fast(src, dst, binar_value) edge(src, dst, 4, 0.625, 2, 5, 0.15, binar_value) |
Fast Edge Detection (Macro). More... | |
#define | edge_sobel(src, dst, binar_value) edge(src, dst, 1, 0.0, 2, 5, 0.10, binar_value) |
Sobel Edge Detection (Macro). More... | |
In an image, homogeneous regions, i.e. regions with slowly moving grey values are of minor importance for the recognition process. Most of the information is located where grey values change rapidly, i.e. in the edges of an image. Edge detection is a method to locate the relevant pixel changes precisely and robustly in an image.
Edge detection is quite vulnerable to noise. Noise can be reduced using low-pass filters. For this very reason, all edge detection algorithms essentially use some kind of low-pass filter as a preprocessing stage. Some images have much noise, others not. The noise does not even have to stem from the sensor or the camera electronic, e.g. if you imagine a rough or grinded surface on an industrial part, the surface structure might be considered as noise, whereas for a similar part with a polished, shiny surface, a rough structure might be a flaw that must be detected. Edge detection solves this conflict, using low-pass filters with different filter size. So for an object with rough surface a large filter size would be required to average over the surface structure; for the second example a smaller size of the filter kernel would allow to detect even tiny flaws.
The edge detection itself is performed by calculating the first or second derivative of an image and thresholding. For the detection of the edges, clever methods have been developed, to
One of the methods is a maximum search technique, that detects the maximum of the gradient image either directly in the first order or as zero crossings in the second order derivative.
In the literature, quite a lot of edge detection algorithms have been suggested, the Marr-Hildredth, Canny, Shen-Castan, SUSAN etc.
The algorithms mostly differ in their low-pass filter design. Some of them are even “optimum” detectors, i.e. they give the best possible result – according to an edge criterion or an edge model.
In practice, the differences are not so much of importance. Since some of the techniques used require quite a bit of computational effort, it is sometimes worth taking a somewhat sub-optimal approach and saving a lot of computing time. We have therefore provided options that allow the user to tailor the edge detector to the specific application.
There is a variety of low-pass filters to choose from. From a theoretical point of view, a Gauss filter should be preferred. We have fixed-sized 3x3, 5x5 and 7x7 filters, as well as a recursive filter design with variable size. For edge binarization, there are 3 modes available. For BinMode=0 gradient values below MinContrast are set to zero, all other edge grey values are kept without binarization. The second mode uses a locally variable threshold using moving average for binarization, and the third mode uses a global threshold that is automatically calculated, so that a predefined percentage of all pixels are above the threshold.
In addition, a technique called hysteresis thresholding may optionally be used. Here, two different thresholds are used. The high threshold is used to detect the edge. Due to the high threshold, the detected edge might have some holes. To close the holes, the low threshold is used. The edges are then extended to those edges of the low-threshold image that connect to those of the high-threshold image. The whole procedure produces high quality edge images with less noise than a simple threshold.
struct VCEdgeCfg |
This struct bundles configuration data for the edge() function. It is just here to help organizing the data.
#define edge_canny | ( | src, | |
dst, | |||
binar_value | |||
) | edge(src, dst, 4, 0.625, -2, 5, 0.10, binar_value) |
The macro calculates an edge image using Canny style edge detection.
It uses the following Settings:
edge_canny() is a macro which calls edge().
#define edge_fast | ( | src, | |
dst, | |||
binar_value | |||
) | edge(src, dst, 4, 0.625, 2, 5, 0.15, binar_value) |
The macro calculates an edge image optimzed for speed.
It uses the following Settings:
edge_fast() is a macro which calls edge().
#define edge_sobel | ( | src, | |
dst, | |||
binar_value | |||
) | edge(src, dst, 1, 0.0, 2, 5, 0.10, binar_value) |
The macro calculates an edge image using Sobel style edge detection.
It uses the following Settings:
edge_sobel() is a macro which calls edge().
Directions of an edge are defined normal to the edge pointing from the dark side to the bright side. The function returns the standard error code. The function requires a large table for the calculation which can be initialized using the function init_gradient_2x2(), which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_2x2() should be used. gradient_2x2() also works, if init_gradient_2x2() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
src | Source Image (Grey Image). |
dst | Destination Image (Vector Image). |
ERR_TYPE | if src Image is not a Grey Image. |
ERR_TYPE | if dst Image is not of Type IMAGE_VECTOR. |
ERR_MEMORY | if Memory Allocation Fails. |
ERR_NONE | on Success. |
I32 init_gradient_2x2 | ( | ) |
The function gradient_2x2() requires a large table for the calculation which can be initialized using this function, which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_2x2() should be used. gradient_2x2() also works, if init_gradient_2x2() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
ERR_MEMORY | if Memory Allocation Fails. |
ERR_NONE | on Success. |
void deinit_gradient_2x2 | ( | ) |
Directions of an edge are defined normal to the edge pointing from the dark side to the bright side. The function returns the standard error code. The function requires a large table for the calculation which can be initialized using the function init_gradient_3x3(), which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_3x3() should be used. gradient_3x3() also works, if init_gradient_3x3() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
src | Source Image (Grey Image). |
dst | Destination Image (Vector Image). |
ERR_TYPE | if src Image is not a Grey Image. |
ERR_TYPE | if dst Image is not of Type ERR_TYPE. |
ERR_MEMORY | if Memory Allocation Fails. |
ERR_NONE | on Success. |
I32 init_gradient_3x3 | ( | ) |
The function gradient_3x3() requires a large table for the calculation which can be initialized using this function, which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_3x3() should be used. gradient_3x3() also works, if init_gradient_3x3() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
ERR_MEMORY | if Memory Allocation Fails. |
ERR_NONE | on Success. |
void deinit_gradient_3x3 | ( | ) |
The function calculates a simplified gradient image with only one component for the destination image, resulting in higher execution speed and less memory requirement.
The function works on an image of type IMAGE_GREY and calculates a one-component vector image dst
, also of type IMAGE_GREY.
Images of this type contain direction information coded with values from 0x00 (0 degrees) up to 0x7F (178.6 degrees) and with the value BELOW_THRESHOLD (0x80) for all parts of the image where the gradient magnitude is below the threshold value thresh
. Values above 0x81 will not be output for the destination image.
Directions of an edge are defined normal to the edge pointing from the dark side to the bright side. The function requires a large table for the calculation which can be initialized using the function init_gradient_3x3T(), which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_3x3T() should be used. gradient_3x3_thresh() also works, if init_gradient_3x3() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
The function returns the standard error code.
src | Source image (Grey Image). |
dst | Destination image (one-component vector image). |
thresh | Threshold Value. |
ERR_TYPE | if src Image is not a Grey Image. |
ERR_TYPE | if dst Image is not of Type ERR_TYPE. |
ERR_NONE | on Success. |
I32 init_gradient_3x3T | ( | ) |
The function init_gradient_3x3T() requires a large table for the calculation which can be initialized using this function, which allocates memory for the table and initializes it with the proper values. To deallocate the memory, the function deinit_gradient_3x3() should be used. gradient_3x3() also works, if init_gradient_3x3() is not called beforehand. It does the memory allocation and initialisation, but this may take some time, the first time the function is called, so the user might like to do the initialisation at the time when the program starts to guarantee equal processing times.
ERR_MEMORY | if Memory Allocation Fails. |
void deinit_gradient_3x3T | ( | ) |
I32 edge | ( | image * | src, |
image * | dst, | ||
I32 | type, | ||
float | sigma, | ||
I32 | BinMode, | ||
I32 | MinContrast, | ||
float | fthresh, | ||
I32 | binar_value | ||
) |
The function performs an edge detection on src
. Various operating modes can be set.
If the destination image is of type IMAGE_VECTOR, the full directional information of the edges image is provided.
The following types of low-pass filters are supported:
type | Low Pass Filter | Role of sigma | Gradient Routine |
---|---|---|---|
0 | - | - | gradient_2x2() |
1 | Sobel | - | gradient_3x3() |
2 | Moving Average | kx and ky of avgm() | gradient_2x2() |
3 | Gauss | sigma of gauss() | gradient_2x2() |
4 | Gauss FIR | sigma of gauss_fir() | gradient_2x2() |
5 | ISEF | b of isef() | gradient_2x2() |
sigma
specifies the size of the filter and therefore the amount of noise reduction. For type<2
, sigma
is not used. For type=2
, we have kx=
ky=
sigma
for the moving average filter. See documentation of avgm() for further information. For type=3
and 4, see documentation of the functions gauss() and gauss_fir() for the description of sigma
. For type=5
, we have b=
sigma
. See documentation of the function isef() for further information. Please note, that in this case the value of sigma
must be less than 1.0.
type | Low Pass Filter | Range of sigma |
---|---|---|
2 | Moving Average | kx= ky= |
3 | Gauss | 0.0 < sigma ≤ 5.0 |
4 | Gauss FIR | sigma = 0.391 or 0.625 or 0.812 |
5 | ISEF | 0.0 < b= sigma < 1.0 |
edge() will return ERR_PARAM, if the above limitations for sigma
are violated.
The following binarization modes are supported:
BinMode | Mode | Hysteresis Threshold |
---|---|---|
0 | No Binarization | - |
1 | VC Style | No |
2 | Canny Style | No |
-1 | VC Style | Yes |
-2 | Canny Style | Yes |
BinMode=0
, edge values below MinContrast
are still set to zero.BinMode=±1
, the edge image is subtracted from a 3x3 moving average filter. All pixels above MinContrast
are set to binar_value. If hysteresis threshold is selected, the high threshold is MinContrast
, the low threshold is MinContrast/4
.thr
for the edge image is automatically computed so that always a certain percentage of all pixels, fthresh
, of the gradient image is above the computed threshold. Reasonable values for fthresh
are between 0.05 (5%) and 0.20 (20%). The automatic threshold also never falls below MinContrast
. If hysteresis threshold is selected, the high threshold is thr
, the low threshold is thr/4
.sigma
and fthresh
are outside the following range:BinMode
= 2 and 0.0 ≤ fthresh
< 1.0type
= 3 and 0.0 < sigma
≤ 5.0type
= 5 and 0.0 < sigma
< 1.0Since edge() calls the functions gradient_2x2() or depending on the value of type
, the necessary tables should be initialized using the functions init_gradient_2x2() or init_gradient_3x3(). To deallocate the memory, the functions deinit_gradient_2x2() or deinit_gradient_3x3() should be used.
src | Source Image of Type IMAGE_GREY. |
dst | Destination Image of Type IMAGE_GREY or IMAGE_VECTOR. |
type | Low-Pass Filter Type. |
sigma | Low-Pass Filter Size. |
BinMode | Binarization Mode: 0, 1, 2. |
MinContrast | Minimum Contrast, Internal Minimum = 1. |
fthresh | Threshold Percentage for BinMode = 2. |
binar_value | Output Value for Binarizaion. |
Since edge() has quite a few options, there are the following macros to simplify the use:
This function follows the contour at the vector image src
as indicated by the direction of the gradient image vector (which is orthogonal to the contour direction) and retains pixels that are local maximum, set others to zero: The two neighbors of the pixels in the direction specified are searched, and if their gradient magnitude is greater or equal to the pixel's magnitude, the pixel is set to 0.
The routine is faster for inplace operation.
src | Source Image of Type IMAGE_VECTOR. |
dst | Destination Image of Type IMAGE_GREY or IMAGE_VECTOR. |
ERR_TYPE | if src or dst is not of Type IMAGE_VECTOR, or dst is not of Type IMAGE_GREY or IMAGE_VECTOR. |
ERR_MEMORY | if allocation fails (only done at in-place mode). |
ERR_NONE | on Success. |
The function works similar to a hough transform by calculating a histogram of gradients (hog) for the image. The maximum of the histogram is calculated with subpixel accuracy. The function is accurate to about 1 to 2 units within the full range from 0.0 to 128.0 with less accuracy for low-contrast or noisy images. In this case an additional averaging filter for the histogram may be used.
imgGrad
contains direction and magnitude information. The histogram is calculated by weighting the directions with their corresponding magnitudes.
Direction | Predominant Direction as float Value. |
imgGrad | Source Image of Type IMAGE_VECTOR. |
kx | Moving Average Filter for Histogram; must be odd, 0 = no filter if kx is not odd, a filter with kx+1 will be used. |
The function works on a one-component gradient image src
which can be the output of the function gradient_3x3_thresh(). src
must be of type IMAGE_GREY.
Input Images of this type must contain direction information coded with values from 0x00 (0 degrees) up to 0x7F (178.6 degrees) and with the value BELOW_THRESHOLD (0x80) for all parts of the image where the gradient magnitude is below a certain threshold. Values in the range [0x81 .. 0xFF] are not allowed in the source image and will result in malfunction.
The input image is divided in blocks of 16x16 pixels. The function works overlapping, i.e. it produces output pixels also for the rows and columns inbetween the 16x16 pixels. The number of output pixels therefore is (src->dx/8 - 1) and (src->dy/8 - 1).
A directional histogram is calculated for all blocks with 16 bins each. The function performs bin averaging of the histograms. The function then searches for the maximum of the histograms and stores its value (the magnitude) and its position (the direction) as a vector image.
src | the source image with one-component direction information |
dst | the destination image (vector image with smaller resolution) |
ERR_TYPE | if src->type != IMAGE_GREY or dst->type != IMAGE_VECTOR. |
ERR_FORMAT | if dst->dx < 2*(src->dx/16)-1 or dst->dy < 2*(src->dy/16)-1. |
ERR_MEMORY | if out of memory. |
ERR_TYPE | if src->type != IMAGE_GREY or dst->type != IMAGE_VECTOR. |
ERR_FORMAT | if dst->dx < 2*(src->dx/16)-1 or dst->dy < 2*(src->dy/16)-1. |
ERR_MEMORY | if out of memory. |
The function works on a one-component gradient image src
which can be the output of the function gradient_3x3_thresh(). src
must be of type IMAGE_GREY.
Input Images of this type must contain direction information coded with values from 0x00 (0 degrees) up to 0x7F (178.6 degrees) and with the value BELOW_THRESHOLD (0x80) for all parts of the image where the gradient magnitude is below a certain threshold. Values in the range [0x81 .. 0xFF] are not allowed in the source image and will result in malfunction.
The input image is divided in blocks of 16x16 pixels. The function works overlapping, i.e. it produces output pixels also for the rows and columns inbetween the 16x16 pixels. The number of output pixels therefore is (src->dx/8 - 1) and (src->dy/8 - 1).
A directional histogram is calculated for all blocks with 16 bins each. The function performs bin averaging of the histograms. The function then searches for the maximum of the histograms and stores its value (the magnitude) and its position (the direction) as a vector image. If the magnitude is below the magThr threshold, the output pixel is set to dirBg.
src | the source image with one-component direction information |
dst | the destination image (vector image with smaller resolution) |
magThr,dirBg | the destination image direction is set to dirBg if magnitude drops below magThr |
ERR_TYPE | if src->type != IMAGE_GREY or dst->type != IMAGE_VECTOR. |
ERR_FORMAT | if dst->dx < 2*(src->dx/16)-1 or dst->dy < 2*(src->dy/16)-1. |
ERR_MEMORY | if out of memory. |