mirror of
https://github.com/NotXia/unibo-ai-notes.git
synced 2025-12-14 18:51:52 +01:00
Add IPCV Canny, zero-crossing, and local features
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
@ -13,6 +13,7 @@
|
||||
\input{./sections/_image_acquisition.tex}
|
||||
\input{./sections/_spatial_filtering.tex}
|
||||
\input{./sections/_edge_detection.tex}
|
||||
\input{./sections/_local_features.tex}
|
||||
|
||||
\printbibliography[heading=bibintoc]
|
||||
|
||||
|
||||
@ -213,4 +213,179 @@ it is possible to use linear interpolation to estimate the gradients of $A$ and
|
||||
\begin{minipage}{0.35\linewidth}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{./img/_nms_interpolation.pdf}
|
||||
\end{minipage}
|
||||
\end{minipage}
|
||||
|
||||
|
||||
|
||||
\section{Canny's edge detector}
|
||||
|
||||
Method based on three criteria:
|
||||
\begin{descriptionlist}
|
||||
\item[Good detection] Correctly detect edges in noisy images.
|
||||
\item[Good localization] Minimize the distance between the found edges and the true edges.
|
||||
\item[One response to one edge] Detect only one pixel at each true edge.
|
||||
\end{descriptionlist}
|
||||
|
||||
In the 1D case, the optimal operator consists in finding the local extrema of the
|
||||
signal obtained by convolving the image and the Gaussian first-order derivative.
|
||||
|
||||
Generalized for the 2D case, Canny's edge detector does the following: \marginnote{Canny's edge detector}
|
||||
\begin{enumerate}
|
||||
\item Gaussian smoothing.
|
||||
\item Gradient computation.
|
||||
\item NMS and thresholding.
|
||||
\end{enumerate}
|
||||
|
||||
It is possible to exploit the convolutions property of being commutative w.r.t. differentiation
|
||||
and simplify the smoothing and gradient computation:
|
||||
\[
|
||||
\begin{split}
|
||||
\partial_x I(x, y) &= \frac{\partial}{\partial x} ( I(x, y) * G(x, y) ) = I(x, y) * \frac{\partial G(x, y)}{\partial x} \\
|
||||
\partial_y I(x, y) &= \frac{\partial}{\partial y} ( I(x, y) * G(x, y) ) = I(x, y) * \frac{\partial G(x, y)}{\partial y}
|
||||
\end{split}
|
||||
\]
|
||||
By leveraging the separability of a 2D Gaussian ($G(x, y) = G_1(x)G_2(y)$),
|
||||
the computation can be reduced to 1D convolutions:
|
||||
\[
|
||||
\begin{split}
|
||||
\partial_x I(x, y) &= I(x, y) * (G_1'(x)G_2(y)) = (I(x, y) * G_1'(x)) * G_2(y) \\
|
||||
\partial_y I(x, y) &= I(x, y) * (G_1(x)G_2'(y)) = (I(x, y) * G_1(x)) * G_2'(y)
|
||||
\end{split}
|
||||
\]
|
||||
|
||||
\begin{remark}
|
||||
When magnitude varies along the object contour, thresholding might remove true edges (edge streaking).
|
||||
\end{remark}
|
||||
|
||||
\begin{description}
|
||||
\item[Hysteresis thresholding] \marginnote{Hysteresis thresholding}
|
||||
Given a high threshold $T_\text{h}$ and a low threshold $T_\text{l}$,
|
||||
depending on its magnitude, a pixel $(i, j)$ can be considered a:
|
||||
\begin{descriptionlist}
|
||||
\item[Strong edge] $\nabla I(i, j) > T_h$.
|
||||
\item[Weak edge] $\nabla I(i, j) > T_l$ and the pixel $(i, j)$ is a neighbor of a strong/weak edge.
|
||||
\end{descriptionlist}
|
||||
In practice, the algorithm starts from strong edges and "propagates" them.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.5\linewidth]{./img/hysteresis thresholding.png}
|
||||
\caption{Application of hysteresis thresholding}
|
||||
\end{figure}
|
||||
\end{description}
|
||||
|
||||
\begin{remark}
|
||||
The output of Canny's edge detector is not an image with edges but a list of edges.
|
||||
|
||||
Note that if the edges of two objects intersect, this will be recognized as a single edge.
|
||||
\end{remark}
|
||||
|
||||
|
||||
|
||||
\section{Zero-crossing edge detector}
|
||||
|
||||
\begin{description}
|
||||
\item[Zero-crossing edge detector] \marginnote{Zero-crossing}
|
||||
Detect edges by finding zero-crossing of the second derivative of the signal.
|
||||
|
||||
\begin{remark}
|
||||
A zero-crossing is a point at 0 where the function changes sign.
|
||||
\end{remark}
|
||||
|
||||
\begin{remark}
|
||||
This approach does not require a threshold anymore but is computationally more expensive.
|
||||
\end{remark}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{subfigure}{0.3\linewidth}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{./img/zero_crossing_example1.png}
|
||||
\caption{Input signal}
|
||||
\end{subfigure}
|
||||
\begin{subfigure}{0.3\linewidth}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{./img/zero_crossing_example2.png}
|
||||
\caption{First-order derivative}
|
||||
\end{subfigure}
|
||||
\begin{subfigure}{0.3\linewidth}
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{./img/zero_crossing_example3.png}
|
||||
\caption{Second-order derivative}
|
||||
\end{subfigure}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\item[Laplacian] \marginnote{Laplacian}
|
||||
Approximation of the second-order derivative:
|
||||
\[ \nabla^2 I(x, y) \approx \frac{\partial^2 I(x, y)}{\partial x^2} + \frac{\partial^2 I(x, y)}{\partial y^2} = \partial_{x,x} I + \partial_{y, y} I \]
|
||||
|
||||
|
||||
\item[Discrete Laplacian] \marginnote{Discrete Laplacian}
|
||||
Use forward difference to compute first-order derivatives,
|
||||
followed by backward difference to compute second-order derivatives.
|
||||
\[
|
||||
\begin{split}
|
||||
\partial_{x,x} I(i, j) &\approx \partial_x I(i, j) - \partial_x I(i, j-1) \\
|
||||
&= \big ( I(i, j+1) - I(i, j) \big) - \big ( I(i, j) - I(i, j-1) \big) \\
|
||||
&= I(i, j+1) - 2I(i, j) + I(i, j-1)
|
||||
\end{split}
|
||||
\]
|
||||
\[
|
||||
\begin{split}
|
||||
\partial_{y,y} I(i, j) &\approx \partial_y I(i, j) - \partial_y I(i-1, j) \\
|
||||
&= \big ( I(i+1, j) - I(i, j) \big) - \big ( I(i, j) - I(i-1, j) \big) \\
|
||||
&= I(i+1, j) - 2I(i, j) + I(i-1, j)
|
||||
\end{split}
|
||||
\]
|
||||
|
||||
This is equivalent to applying the cross-correlation kernel:
|
||||
\[
|
||||
\nabla^2 = \begin{pmatrix}
|
||||
0 & 1 & 0 \\
|
||||
1 & -4 & 1 \\
|
||||
0 & 1 & 0 \\
|
||||
\end{pmatrix}
|
||||
\]
|
||||
|
||||
\begin{remark}
|
||||
It can be shown that zero-crossings of the Laplacian typically lay close to those of the second-order derivative.
|
||||
\end{remark}
|
||||
\end{description}
|
||||
|
||||
|
||||
\subsection{Laplacian of Gaussian (LOG)}
|
||||
|
||||
Laplacian of Gaussian (LOG) does the following: \marginnote{Laplacian of Gaussian (LOG)}
|
||||
\begin{enumerate}
|
||||
\item Gaussian smoothing.
|
||||
\item Second-order differentiation using the Laplacian filter.
|
||||
\item Zero-crossings extraction.
|
||||
\end{enumerate}
|
||||
|
||||
\begin{description}
|
||||
\item[Discrete zero-crossing]
|
||||
As the image consists of a discrete grid of pixels, finding a zero-crossing as per definition is not always possible.
|
||||
Instead, an edge is detected when there is a change of sign in the magnitude.
|
||||
The edge pixel can be identified as:
|
||||
\begin{itemize}
|
||||
\item The pixel where the magnitude is positive.
|
||||
\item The pixel where the magnitude is negative.
|
||||
\item The pixel where the absolute value of the magnitude is smaller.
|
||||
This is usually the best choice as it is closer to the true zero-crossing.
|
||||
\end{itemize}
|
||||
\end{description}
|
||||
|
||||
\begin{remark}
|
||||
A final thresholding might still be useful to remove uninteresting edges.
|
||||
\end{remark}
|
||||
|
||||
\begin{remark}
|
||||
Smaller values of $\sigma$ of the smoothing operator detect more detailed edges,
|
||||
while higher $\sigma$ captures more general edges.
|
||||
\end{remark}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.8\linewidth]{./img/_example_laplacian_gaussian.pdf}
|
||||
\end{figure}
|
||||
@ -0,0 +1,49 @@
|
||||
\chapter{Local features}
|
||||
|
||||
\begin{description}
|
||||
\item[Correspondence points] \marginnote{Correspondence points}
|
||||
Image points projected from the same 3D point from different views of the scene.
|
||||
|
||||
\begin{example}[Homography]
|
||||
Align two images of the same scene to create a larger image.
|
||||
Homography requires at least 4 correspondences.
|
||||
To find them, it does the following:
|
||||
\begin{itemize}
|
||||
\item Independently find salient points in the two images.
|
||||
\item Compute a local description of the salient points.
|
||||
\item Compare descriptions to find matching points.
|
||||
\end{itemize}
|
||||
\end{example}
|
||||
|
||||
|
||||
\item[Local invariant features] \marginnote{Local invariant features}
|
||||
Find correspondences in three steps:
|
||||
\begin{descriptionlist}
|
||||
\item[Detection] \marginnote{Detection}
|
||||
Find salient points (keypoints).
|
||||
|
||||
The detector should have the following properties:
|
||||
\begin{descriptionlist}
|
||||
\item[Repeatability] Find the same keypoints across different images.
|
||||
\item[Saliency] Find keypoints surrounded by informative patterns.
|
||||
\item[Fast] As it must scan the entire image.
|
||||
\end{descriptionlist}
|
||||
|
||||
|
||||
\item[Description] \marginnote{Description}
|
||||
Compute a descriptor for each salient point based on its neighborhood.
|
||||
|
||||
A descriptor should have the following properties:
|
||||
\begin{descriptionlist}
|
||||
\item[Invariant] Robust to as many transformations as possible (i.e. illumination, weather, scaling, viewpoint, \dots).
|
||||
\item[Distinctiveness/robustness trade-off] The description should only capture important information around a keypoint and
|
||||
ignore irrelevant features or noise.
|
||||
\item[Compactness] The description should be concise.
|
||||
\end{descriptionlist}
|
||||
|
||||
|
||||
\item[Matching] \marginnote{Matching}
|
||||
Identify the same descriptor across different images.
|
||||
\end{descriptionlist}
|
||||
\end{description}
|
||||
|
||||
Reference in New Issue
Block a user