x
This commit is contained in:
8
README.md
Normal file
8
README.md
Normal file
@ -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)
|
||||||
64
dlt.md
Normal file
64
dlt.md
Normal file
@ -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
|
||||||
47
gen.sh
Normal file
47
gen.sh
Normal file
@ -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
|
||||||
Reference in New Issue
Block a user