From d8739754bec1b6d63fc9bfba3608f88f0d7d7f4f Mon Sep 17 00:00:00 2001 From: crosstyan Date: Thu, 5 Dec 2024 17:06:54 +0800 Subject: [PATCH] x --- README.md | 8 +++++++ dlt.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ gen.sh | 47 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 README.md create mode 100644 dlt.md create mode 100644 gen.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..978d868 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# ChArUco experiments + +go to [`opencv_contrib/modules/aruco/misc/pattern_generator`](https://github.com/opencv/opencv_contrib/tree/4.x/modules/aruco/misc/pattern_generator) to generate custom patterns. + +See also [gen.sh](gen.sh) (put it in the same directory as the pattern generator). + +- A0 size, 10x7, square 115mm, marker 90mm +- 400mm x 400mm ArUco board (4x4, 0-5 id) diff --git a/dlt.md b/dlt.md new file mode 100644 index 0000000..baf58ef --- /dev/null +++ b/dlt.md @@ -0,0 +1,64 @@ +Direct Linear Transform (DLT) is fundamentally connected to triangulation through its ability to solve the intersection of projection rays. Here's how they relate: + +**Mathematical Foundation:** + +1. **Projection Model** +- A 3D point $X = [X,Y,Z,1]^T$ projects to 2D point $x = [u,v,1]^T$ through: + $\lambda x = PX$ + where $P$ is the 3×4 projection matrix + $\lambda$ is the projective depth + +2. **DLT Formulation** +- For each image point, we can write: + $\lambda u = \frac{P_{1}^TX}{P_{3}^TX}$ + $\lambda v = \frac{P_{2}^TX}{P_{3}^TX}$ + +- This leads to linear equations: + $uP_{3}^TX - P_{1}^TX = 0$ + $vP_{3}^TX - P_{2}^TX = 0$ + +3. **Triangulation System** +- For two views with points $x_1=(u_1,v_1)$ and $x_2=(u_2,v_2)$: + +$$\begin{bmatrix} +u_1P_{3,1}^T - P_{1,1}^T \\ +v_1P_{3,1}^T - P_{2,1}^T \\ +u_2P_{3,2}^T - P_{1,2}^T \\ +v_2P_{3,2}^T - P_{2,2}^T +\end{bmatrix} X = 0$$ + +**Why DLT Works for Triangulation:** + +1. **Geometric Interpretation** +- DLT finds the 3D point that minimizes algebraic error +- Each row in the equation system represents a constraint from one coordinate +- The solution is the intersection of projection rays in 3D space + +2. **Solution Method** +- The system $AX = 0$ is solved using SVD +- The solution is the eigenvector corresponding to smallest singular value +- This provides the optimal 3D point in a least-squares sense + +3. **Implementation Connection** +In your code: + +```python +A = [ + point1[1]*P1[2,:] - P1[1,:], + P1[0,:] - point1[0]*P1[2,:], + point2[1]*P2[2,:] - P2[1,:], + P2[0,:] - point2[0]*P2[2,:], +] +``` +This directly implements the linear system described above. + +**Advantages:** +- Linear solution +- Simple to implement +- Works with multiple views +- Computationally efficient + +**Limitations:** +- Sensitive to noise +- Assumes perfect point correspondences +- Minimizes algebraic (not geometric) error diff --git a/gen.sh b/gen.sh new file mode 100644 index 0000000..abcb36c --- /dev/null +++ b/gen.sh @@ -0,0 +1,47 @@ +SQUARE_MM=115 +MARKER_MM=90 +MARKER_SEP_MM=$(echo "scale=4; $SQUARE_MM - $MARKER_MM" | bc) + +if [ $MARKER_SEP_MM -lt 0 ]; then + echo "Marker size must be smaller than square size" + exit 1 +fi + +SQUARE_SIZE=$(echo "scale=4; $SQUARE_MM / 1000" | bc) +MARKER_SIZE=$(echo "scale=4; $MARKER_MM / 1000" | bc) +MARKER_SEP=$(echo "scale=4; $MARKER_SEP_MM / 1000" | bc) + +PAGE_PADDING_MM=10 +PAGE_PADDING=$(echo "scale=4; $PAGE_PADDING_MM / 1000" | bc) + +# A0 +PAGE_WIDTH_MM=1189 +PAGE_HEIGHT_MM=841 + +BOARD_WIDTH_IN_SQUARE=$(echo "scale=0; ($PAGE_WIDTH_MM - $PAGE_PADDING_MM) / $SQUARE_MM" | bc) +BOARD_HEIGHT_IN_SQUARE=$(echo "scale=0; ($PAGE_HEIGHT_MM - $PAGE_PADDING_MM) / $SQUARE_MM" | bc) +START_MARKER_ID=10 + +OUTPUT_FILENAME="charuco_${PAGE_WIDTH_MM}x${PAGE_HEIGHT_MM}_${BOARD_WIDTH_IN_SQUARE}x${BOARD_HEIGHT_IN_SQUARE}_s${SQUARE_MM}_m${MARKER_MM}.pdf" + +# DICT_4X4_1000 +# DICT_5X5_1000 +# DICT_6X6_1000 +# DICT_7X7_1000 +# DICT_ARUCO_ORIGINAL +# DICT_APRILTAG_16h5 +# DICT_APRILTAG_25h9 +# DICT_APRILTAG_36h10 +# DICT_APRILTAG_36h11 + +python MarkerPrinter.py --charuco \ + --file $OUTPUT_FILENAME \ + --dictionary DICT_4X4_1000 \ + --page_border_x $PAGE_PADDING \ + --page_border_y $PAGE_PADDING \ + --square_length $SQUARE_SIZE \ + --marker_length $MARKER_SIZE \ + --marker_separation $MARKER_SEP \ + --charuco_size_x $BOARD_WIDTH_IN_SQUARE \ + --charuco_size_y $BOARD_HEIGHT_IN_SQUARE \ + --first_marker $START_MARKER_ID