diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..638b9b9
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,39 @@
+AccessModifierOffset: -4
+AlignAfterOpenBracket: DontAlign
+AllowShortBlocksOnASingleLine: true
+AllowShortFunctionsOnASingleLine: All
+BasedOnStyle: LLVM
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+BreakBeforeBraces: Custom
+ColumnLimit: 0
+Cpp11BracedListStyle: false
+FixNamespaceComments: false
+IndentCaseLabels: false
+IndentPPDirectives: None
+IndentWidth: 4
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: All
+PointerAlignment: Right
+SortIncludes: false
+SortUsingDeclarations: false
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+TabWidth: 4
+UseTab: true
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index dfe0770..0000000
--- a/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..357329c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,55 @@
+# Build directories and files
+build/CMakeCache.txt
+build/cmake_install.cmake
+build/Makefile
+build/CMakeFiles/
+build/bin/
+
+# Compiled object files
+*.o
+*.obj
+
+# Compiled dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Compiled static libraries
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+
+# CMake generated files
+CMakeCache.txt
+cmake_install.cmake
+Makefile
+CMakeFiles/
+
+# IDE files
+.vscode/
+.idea/
+*.swp
+*.swo
+*~
+
+# System files
+.DS_Store
+Thumbs.db
+
+# Temporary files
+*.tmp
+*.temp
+*.log
+
+# Don't ignore output images - these are the results we want to keep
+!build/*.jpg
+!build/*.png
+!build/*.bmp
+!build/*.tiff
+!build/*.tif
+
+# But still ignore the executable in bin directory
+build/bin/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..a0c371f
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 3.10)
+project(avm)
+
+# Set C++ standard
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Set build type and optimization options
+set(CMAKE_BUILD_TYPE "Release")
+set(CMAKE_CXX_FLAGS "-O3")
+
+# Find OpenCV package
+find_package(OpenCV REQUIRED)
+
+# Print OpenCV information
+message(STATUS "OpenCV library status:")
+message(STATUS " version: ${OpenCV_VERSION}")
+message(STATUS " libraries: ${OpenCV_LIBS}")
+message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
+
+# Include OpenCV header files
+include_directories(${OpenCV_INCLUDE_DIRS})
+
+# Add header file directory
+include_directories(include)
+
+# Collect source files
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+
+# Create executable file
+add_executable(avm ${SOURCES})
+
+# Link OpenCV libraries
+target_link_libraries(avm ${OpenCV_LIBS})
+
+# Set output directory
+set_target_properties(avm PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
+)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..99f5cea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Xi Xu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..80abedb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,289 @@
+# AVM - Around View Monitoring System
+
+An OpenCV-based 360-degree surround view system that processes fisheye camera images to create a bird's eye view for vehicle parking assistance and navigation.
+
+## π Features
+
+- **Multi-Camera Fisheye Processing**: Supports 4 fisheye cameras (front, back, left, right)
+- **Automatic Corner Detection**: Uses advanced histogram-based algorithms for calibration board detection
+- **Real-time Undistortion**: Efficient fisheye-to-rectilinear image transformation
+- **Perspective Transformation**: Converts undistorted images to bird's eye view
+- **Seamless Stitching**: Blends multiple camera views into a single panoramic image
+- **Vehicle Overlay**: Adds vehicle model overlay for spatial reference
+
+## π οΈ Installation
+
+### Prerequisites
+
+- **OpenCV 3.0+** (4.x recommended)
+- **CMake 3.10+**
+- **GCC/Clang** with C++11 support
+- **Linux/macOS/Windows** (WSL2 recommended for Windows)
+
+### Quick Installation
+
+```bash
+# Clone the repository
+git clone https://github.com/xixu-me/AVM.git
+cd AVM
+
+# Make scripts executable
+chmod +x scripts/*.sh
+
+# Build the project
+./scripts/build.sh
+```
+
+For detailed installation instructions, see [INSTALLATION.md](docs/INSTALLATION.md).
+
+## π Quick Start
+
+### Run with Sample Data
+
+```bash
+# Execute the AVM system with provided sample images
+./scripts/run.sh
+```
+
+### Expected Output
+
+After successful execution, you'll find the following files in the `build/` directory:
+
+- `stitched_result_with_su7.jpg` - Final 360Β° panoramic view
+- `bird_*.jpg` - Individual bird's eye view images
+- `*_undis.jpg` - Undistorted fisheye images
+
+## πΈ Input Images
+
+The AVM system processes four fisheye camera images positioned around the vehicle:
+
+### Camera Configuration
+
+| Camera Position | File | Description |
+|----------------|------|-------------|
+| **Front** | `assets/images/front.png` | Front bumper center, covers front area |
+| **Back** | `assets/images/back.png` | Rear bumper center, covers rear area |
+| **Left** | `assets/images/left.png` | Left side mirror, covers left side |
+| **Right** | `assets/images/right.png` | Right side mirror, covers right side |
+
+### Sample Input Images
+
+
+
+| Front Camera | Back Camera |
+|:------------:|:-----------:|
+|  |  |
+| *Front fisheye camera capturing forward area* | *Rear fisheye camera capturing backward area* |
+
+| Left Camera | Right Camera |
+|:-----------:|:------------:|
+|  |  |
+| *Left side fisheye camera* | *Right side fisheye camera* |
+
+
+
+### Input Image Specifications
+
+- **Resolution**: 1280Γ960 pixels
+- **Format**: PNG/JPG
+- **Camera Type**: Fisheye lens with wide FOV
+- **Calibration**: 2Γ4 rectangular grid pattern visible in each image
+- **Bit Depth**: 8-bit RGB
+
+### Calibration Board Requirements
+
+Each input image must contain a **2Γ4 rectangular calibration pattern**:
+
+- **Grid Size**: 2 rows Γ 4 columns (8 corners total)
+- **Visibility**: Pattern must be clearly visible in overlapping areas
+- **Contrast**: High contrast between pattern and ground
+- **Position**: Within the valid detection region (20%-70% of image height)
+
+## π― Output Images
+
+The AVM system generates multiple intermediate and final output images:
+
+### Processing Pipeline Outputs
+
+
+
+| Stage | Description | Example |
+|-------|-------------|---------|
+| **1. Undistorted Images** | Fisheye correction applied |  |
+| **2. Bird's Eye View** | Perspective transformation |  |
+| **3. Final Stitched Result** | Complete 360Β° view |  |
+
+
+
+### Final Output Visualization
+
+The final stitched image provides a complete 360-degree around view:
+
+
+

+
Complete 360Β° Around View Monitor output with vehicle overlay
+
+
+### Output Image Details
+
+#### 1. Undistorted Images (`*_undis.jpg`)
+
+- **Purpose**: Corrected fisheye distortion
+- **Resolution**: 1280Γ960 pixels
+- **Features**: Corner points marked, distortion removed
+
+#### 2. Bird's Eye View Images (`bird_*.jpg`)
+
+- **Front/Back Views**: 792Γ305 pixels
+- **Left/Right Views**: 1131Γ281 pixels
+- **Perspective**: Top-down view transformation
+- **Rotation**: Automatically corrected for proper orientation
+
+#### 3. Debug Images
+
+- **Contrast Enhanced** (`*_img_contrast.jpg`): Gamma-corrected for corner detection
+- **Thresholded** (`*_img_thresh.jpg`): Binary images showing detected features
+- **Corner Detection** (`*_undis_1.jpg`): Undistorted images with detected corners marked
+
+#### 4. Final Stitched Image (`stitched_result_with_su7.jpg`)
+
+- **Composition**: All four camera views seamlessly blended
+- **Vehicle Overlay**: Su7 vehicle model positioned at center
+- **Dimensions**: Variable based on camera layout
+- **Blending**: Smooth transitions using mask images
+
+## ποΈ System Architecture
+
+### Processing Pipeline
+
+```
+[Fisheye Images] β [Undistortion] β [Corner Detection] β [Bird's Eye Transform] β [Image Stitching] β [Final Output]
+```
+
+### Key Components
+
+1. **Undistortion Engine**: Converts fisheye to rectilinear projection
+2. **Corner Detector**: Histogram-based calibration pattern detection
+3. **Perspective Transform**: Homography-based bird's eye view generation
+4. **Image Stitcher**: Mask-based seamless image blending
+
+### Camera Model
+
+The system uses a polynomial fisheye distortion model:
+
+```
+ΞΈ_distorted = ΞΈ_undistorted + kβΞΈΒ³ + kβΞΈβ΅ + kβΞΈβ· + kβΞΈβΉ
+```
+
+Default parameters optimized for automotive fisheye cameras.
+
+## βοΈ Configuration
+
+### Camera Parameters
+
+Key parameters that can be adjusted in `src/avm.cpp`:
+
+```cpp
+// Camera intrinsics
+float m_focal_length = 910.0; // Camera focal length (pixels)
+float m_fish_scale = 0.5; // Fisheye scaling factor
+float m_undis_scale = 1.55; // Undistortion scaling
+
+// Distortion coefficients
+cv::Vec4d distortion_coeffs = {
+ -0.05611147, // k1
+ -0.05377447, // k2
+ 0.0115717, // k3
+ 0.0030788 // k4
+};
+```
+
+### Layout Configuration
+
+```cpp
+#define IMAGE_BACK_PIXEL_Y 643 // Back image Y offset
+#define IMAGE_RIGHT_PIXEL_X 398 // Right image X offset
+```
+
+### Using Custom Images
+
+1. **Replace Input Images**: Place your fisheye images in `assets/images/`
+2. **Name Convention**: Use `front.png`, `back.png`, `left.png`, `right.png`
+3. **Calibration Pattern**: Ensure 2Γ4 grid is visible in overlapping areas
+4. **Adjust Parameters**: Modify camera parameters if using different lenses
+
+## π§ Troubleshooting
+
+### Common Issues
+
+#### Build Errors
+
+```bash
+# OpenCV not found
+sudo apt-get install libopencv-dev libopencv-contrib-dev
+
+# CMake version too old
+wget https://cmake.org/files/v3.20/cmake-3.20.0-linux-x86_64.sh
+```
+
+#### Runtime Issues
+
+```bash
+# Missing input images
+cp your_images/* assets/images/
+
+# Permission denied
+chmod +x scripts/*.sh
+```
+
+#### Corner Detection Failures
+
+- Ensure calibration board has high contrast
+- Check that pattern is within valid detection region
+- Verify image quality and lighting conditions
+
+### Debug Mode
+
+Enable debug output by modifying the source code:
+
+```cpp
+#define DEBUG_MODE 1 // Add this line for debug output
+```
+
+## π Performance
+
+### Typical Processing Times
+
+- **Image Loading**: ~10ms per image
+- **Undistortion**: ~50ms per image
+- **Corner Detection**: ~100-200ms per image
+- **Stitching**: ~100ms total
+- **Overall**: ~1-2 seconds for complete pipeline
+
+### Memory Usage
+
+- **Peak Memory**: ~30-40MB
+- **Input Images**: ~5MB total
+- **Intermediate Results**: ~20MB
+- **Output Images**: ~2-3MB
+
+## π License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## π Acknowledgments
+
+- OpenCV community for excellent computer vision library
+- Contributors to fisheye camera calibration algorithms
+- Automotive industry standards for AVM system requirements
+
+## π Support
+
+- **Documentation**: Check [docs/](docs/) directory for detailed guides
+
+---
+
+
+
Made with β€οΈ for safer driving
+
β Star this repo if you find it helpful!
+
diff --git a/assets/images/avm_image_1.jpg b/assets/images/avm_image_1.jpg
new file mode 100644
index 0000000..029b8e4
Binary files /dev/null and b/assets/images/avm_image_1.jpg differ
diff --git a/assets/images/back.png b/assets/images/back.png
new file mode 100644
index 0000000..0971a8e
Binary files /dev/null and b/assets/images/back.png differ
diff --git a/assets/images/front.png b/assets/images/front.png
new file mode 100644
index 0000000..afe3a09
Binary files /dev/null and b/assets/images/front.png differ
diff --git a/assets/images/left.png b/assets/images/left.png
new file mode 100644
index 0000000..9e8d775
Binary files /dev/null and b/assets/images/left.png differ
diff --git a/assets/images/right.png b/assets/images/right.png
new file mode 100644
index 0000000..191bcb9
Binary files /dev/null and b/assets/images/right.png differ
diff --git a/assets/images/su7.png b/assets/images/su7.png
new file mode 100644
index 0000000..ea18425
Binary files /dev/null and b/assets/images/su7.png differ
diff --git a/assets/masks/maskBack.jpg b/assets/masks/maskBack.jpg
new file mode 100644
index 0000000..c878664
Binary files /dev/null and b/assets/masks/maskBack.jpg differ
diff --git a/assets/masks/maskFront.jpg b/assets/masks/maskFront.jpg
new file mode 100644
index 0000000..fa13a3d
Binary files /dev/null and b/assets/masks/maskFront.jpg differ
diff --git a/assets/masks/maskLeft.jpg b/assets/masks/maskLeft.jpg
new file mode 100644
index 0000000..f7b8706
Binary files /dev/null and b/assets/masks/maskLeft.jpg differ
diff --git a/assets/masks/maskRight.jpg b/assets/masks/maskRight.jpg
new file mode 100644
index 0000000..1326b8d
Binary files /dev/null and b/assets/masks/maskRight.jpg differ
diff --git a/build/back_img_contrast.jpg b/build/back_img_contrast.jpg
new file mode 100644
index 0000000..589ea78
Binary files /dev/null and b/build/back_img_contrast.jpg differ
diff --git a/build/back_img_thresh.jpg b/build/back_img_thresh.jpg
new file mode 100644
index 0000000..bcc7d92
Binary files /dev/null and b/build/back_img_thresh.jpg differ
diff --git a/build/back_undis.jpg b/build/back_undis.jpg
new file mode 100644
index 0000000..c17f3e5
Binary files /dev/null and b/build/back_undis.jpg differ
diff --git a/build/back_undis_1.jpg b/build/back_undis_1.jpg
new file mode 100644
index 0000000..192fcfa
Binary files /dev/null and b/build/back_undis_1.jpg differ
diff --git a/build/bird_back.jpg b/build/bird_back.jpg
new file mode 100644
index 0000000..95af03e
Binary files /dev/null and b/build/bird_back.jpg differ
diff --git a/build/bird_back_2.jpg b/build/bird_back_2.jpg
new file mode 100644
index 0000000..fb5d101
Binary files /dev/null and b/build/bird_back_2.jpg differ
diff --git a/build/bird_front.jpg b/build/bird_front.jpg
new file mode 100644
index 0000000..336e79b
Binary files /dev/null and b/build/bird_front.jpg differ
diff --git a/build/bird_front_2.jpg b/build/bird_front_2.jpg
new file mode 100644
index 0000000..addca7a
Binary files /dev/null and b/build/bird_front_2.jpg differ
diff --git a/build/bird_left.jpg b/build/bird_left.jpg
new file mode 100644
index 0000000..2751f9b
Binary files /dev/null and b/build/bird_left.jpg differ
diff --git a/build/bird_left_2.jpg b/build/bird_left_2.jpg
new file mode 100644
index 0000000..f87dbd9
Binary files /dev/null and b/build/bird_left_2.jpg differ
diff --git a/build/bird_right.jpg b/build/bird_right.jpg
new file mode 100644
index 0000000..447f003
Binary files /dev/null and b/build/bird_right.jpg differ
diff --git a/build/bird_right_2.jpg b/build/bird_right_2.jpg
new file mode 100644
index 0000000..be79cac
Binary files /dev/null and b/build/bird_right_2.jpg differ
diff --git a/build/front_img_contrast.jpg b/build/front_img_contrast.jpg
new file mode 100644
index 0000000..8fd87e7
Binary files /dev/null and b/build/front_img_contrast.jpg differ
diff --git a/build/front_img_thresh.jpg b/build/front_img_thresh.jpg
new file mode 100644
index 0000000..00feda6
Binary files /dev/null and b/build/front_img_thresh.jpg differ
diff --git a/build/front_undis.jpg b/build/front_undis.jpg
new file mode 100644
index 0000000..8444a9b
Binary files /dev/null and b/build/front_undis.jpg differ
diff --git a/build/front_undis_1.jpg b/build/front_undis_1.jpg
new file mode 100644
index 0000000..ecec6c4
Binary files /dev/null and b/build/front_undis_1.jpg differ
diff --git a/build/left_img_contrast.jpg b/build/left_img_contrast.jpg
new file mode 100644
index 0000000..30465e8
Binary files /dev/null and b/build/left_img_contrast.jpg differ
diff --git a/build/left_img_thresh.jpg b/build/left_img_thresh.jpg
new file mode 100644
index 0000000..ce7146c
Binary files /dev/null and b/build/left_img_thresh.jpg differ
diff --git a/build/left_undis.jpg b/build/left_undis.jpg
new file mode 100644
index 0000000..0a151da
Binary files /dev/null and b/build/left_undis.jpg differ
diff --git a/build/left_undis_1.jpg b/build/left_undis_1.jpg
new file mode 100644
index 0000000..9e66d48
Binary files /dev/null and b/build/left_undis_1.jpg differ
diff --git a/build/right_img_contrast.jpg b/build/right_img_contrast.jpg
new file mode 100644
index 0000000..3963eee
Binary files /dev/null and b/build/right_img_contrast.jpg differ
diff --git a/build/right_img_thresh.jpg b/build/right_img_thresh.jpg
new file mode 100644
index 0000000..6ab8848
Binary files /dev/null and b/build/right_img_thresh.jpg differ
diff --git a/build/right_undis.jpg b/build/right_undis.jpg
new file mode 100644
index 0000000..032db13
Binary files /dev/null and b/build/right_undis.jpg differ
diff --git a/build/right_undis_1.jpg b/build/right_undis_1.jpg
new file mode 100644
index 0000000..6aa0bbb
Binary files /dev/null and b/build/right_undis_1.jpg differ
diff --git a/build/stitched_result_with_su7.jpg b/build/stitched_result_with_su7.jpg
new file mode 100644
index 0000000..4b87cb9
Binary files /dev/null and b/build/stitched_result_with_su7.jpg differ
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
new file mode 100644
index 0000000..ca19119
--- /dev/null
+++ b/docs/INSTALLATION.md
@@ -0,0 +1,280 @@
+# Installation Guide
+
+## System Requirements
+
+### Operating System
+
+- Linux (Ubuntu 18.04+, CentOS 7+)
+- macOS 10.14+
+- Windows 10+ (with WSL2 recommended)
+
+### Hardware Requirements
+
+- **Memory**: Minimum 4GB RAM, recommended 8GB+
+- **Storage**: 1GB free space for build and outputs
+- **CPU**: Multi-core processor recommended for optimal performance
+
+## Dependencies
+
+### Required Dependencies
+
+#### OpenCV (Version 3.0+)
+
+OpenCV is the core dependency for image processing operations.
+
+**Ubuntu/Debian:**
+
+```bash
+sudo apt update
+sudo apt install libopencv-dev libopencv-contrib-dev
+```
+
+**CentOS/RHEL:**
+
+```bash
+sudo yum install opencv-devel
+# or for newer versions:
+sudo dnf install opencv-devel
+```
+
+**macOS (using Homebrew):**
+
+```bash
+brew install opencv
+```
+
+**Manual Installation:**
+If package managers don't provide a recent enough version:
+
+```bash
+# Download OpenCV source
+git clone https://github.com/opencv/opencv.git
+cd opencv
+git checkout 4.x # or your preferred version
+
+# Build and install
+mkdir build && cd build
+cmake -D CMAKE_BUILD_TYPE=RELEASE \
+ -D CMAKE_INSTALL_PREFIX=/usr/local \
+ -D WITH_TBB=ON \
+ -D WITH_V4L=ON \
+ -D WITH_QT=OFF \
+ -D WITH_OPENGL=ON \
+ ..
+make -j$(nproc)
+sudo make install
+```
+
+#### CMake (Version 3.10+)
+
+Required for building the project.
+
+**Ubuntu/Debian:**
+
+```bash
+sudo apt install cmake
+```
+
+**CentOS/RHEL:**
+
+```bash
+sudo yum install cmake
+# or: sudo dnf install cmake
+```
+
+**macOS:**
+
+```bash
+brew install cmake
+```
+
+### Optional Dependencies
+
+#### Git (for version control)
+
+```bash
+# Ubuntu/Debian
+sudo apt install git
+
+# CentOS/RHEL
+sudo yum install git
+
+# macOS
+git --version # Usually pre-installed
+```
+
+## Installation Steps
+
+### Method 1: Clone from GitHub (Recommended)
+
+```bash
+# Clone the repository
+git clone https://github.com/xixu-me/AVM.git
+cd AVM
+
+# Make scripts executable
+chmod +x scripts/*.sh
+
+# Build the project
+./scripts/build.sh
+```
+
+### Method 2: Download and Build
+
+```bash
+# Download and extract source code
+wget https://github.com/xixu-me/AVM/archive/main.zip
+unzip main.zip
+cd AVM-main
+
+# Make scripts executable
+chmod +x scripts/*.sh
+
+# Build the project
+./scripts/build.sh
+```
+
+### Manual Build Process
+
+If you prefer to build manually:
+
+```bash
+# Create build directory
+mkdir -p build
+cd build
+
+# Configure with CMake
+cmake ..
+
+# Build (adjust -j flag based on your CPU cores)
+make -j$(nproc)
+
+# Verify build
+ls bin/avm # Should exist if build successful
+```
+
+## Verification
+
+### Test Installation
+
+```bash
+# Quick test with provided sample images
+./scripts/run.sh
+
+# Check output
+ls build/stitched_result_with_su7.jpg # Should exist after successful run
+```
+
+### Expected Output Files
+
+After successful execution, you should see:
+
+```
+build/
+βββ front_undis.jpg # Undistorted front view
+βββ back_undis.jpg # Undistorted back view
+βββ left_undis.jpg # Undistorted left view
+βββ right_undis.jpg # Undistorted right view
+βββ bird_front_2.jpg # Front bird's eye view
+βββ bird_back_2.jpg # Back bird's eye view
+βββ bird_left_2.jpg # Left bird's eye view
+βββ bird_right_2.jpg # Right bird's eye view
+βββ stitched_result_with_su7.jpg # Final panoramic result
+```
+
+## Troubleshooting
+
+### OpenCV Not Found
+
+```
+CMake Error: Could not find OpenCV
+```
+
+**Solution:**
+
+- Verify OpenCV installation: `pkg-config --modversion opencv`
+- Set OpenCV path manually: `export OpenCV_DIR=/path/to/opencv`
+- Reinstall OpenCV development packages
+
+### Build Errors
+
+```
+error: opencv2/opencv.hpp: No such file or directory
+```
+
+**Solution:**
+
+- Install OpenCV development headers
+- Check include paths in CMakeLists.txt
+- Verify compiler can find OpenCV includes
+
+### Runtime Errors
+
+```
+error while loading shared libraries: libopencv_core.so
+```
+
+**Solution:**
+
+- Update library path: `sudo ldconfig`
+- Add to LD_LIBRARY_PATH: `export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH`
+
+### Permission Errors
+
+```
+Permission denied: ./scripts/build.sh
+```
+
+**Solution:**
+
+```bash
+chmod +x scripts/*.sh
+```
+
+### Missing Input Images
+
+```
+[ERROR] Unable to read input image files
+```
+
+**Solution:**
+
+- Ensure input images exist in `assets/images/`
+- Check file permissions and formats (PNG/JPG supported)
+- Verify image files are not corrupted
+
+## Performance Optimization
+
+### Build Optimizations
+
+For maximum performance, build in Release mode:
+
+```bash
+cd build
+cmake -DCMAKE_BUILD_TYPE=Release ..
+make -j$(nproc)
+```
+
+### Runtime Optimizations
+
+- Use SSD storage for faster I/O operations
+- Ensure sufficient RAM to avoid swapping
+- Close unnecessary applications during processing
+
+## Next Steps
+
+After successful installation:
+
+1. **Read the Documentation**: Check `README.md` for usage instructions
+2. **Try Custom Images**: Replace sample images with your own fisheye images
+3. **Explore Configuration**: Review camera parameters in the source code
+4. **Contribute**: See `CONTRIBUTING.md` for development guidelines
+
+## Getting Help
+
+If you encounter issues:
+
+1. Check this troubleshooting section
+2. Search existing GitHub issues
+3. Create a new issue with detailed error information
+4. Include your system information and build logs
diff --git a/docs/SAMPLE_DATA.md b/docs/SAMPLE_DATA.md
new file mode 100644
index 0000000..eefcd7c
--- /dev/null
+++ b/docs/SAMPLE_DATA.md
@@ -0,0 +1,115 @@
+# Sample Data Description
+
+## Input Images Overview
+
+The AVM system comes with sample fisheye camera images that demonstrate the complete processing pipeline.
+
+### Image Specifications
+
+- **Resolution**: 1280Γ960 pixels
+- **Format**: PNG
+- **Camera Type**: Fisheye lens with wide field of view
+- **Calibration Pattern**: 2Γ4 rectangular grid visible in each image
+
+### Camera Positions
+
+#### Front Camera (`assets/images/front.png`)
+
+- Position: Front bumper center
+- Field of view: Covers front area and left/right sides
+- Calibration board: Positioned on ground in front of vehicle
+
+#### Back Camera (`assets/images/back.png`)
+
+- Position: Rear bumper center
+- Field of view: Covers rear area and left/right sides
+- Calibration board: Positioned on ground behind vehicle
+
+#### Left Camera (`assets/images/left.png`)
+
+- Position: Left side mirror or door
+- Field of view: Covers left side area
+- Calibration board: Positioned on ground to the left of vehicle
+
+#### Right Camera (`assets/images/right.png`)
+
+- Position: Right side mirror or door
+- Field of view: Covers right side area
+- Calibration board: Positioned on ground to the right of vehicle
+
+### Vehicle Model
+
+#### Vehicle Overlay (`assets/images/su7.png`)
+
+- **Type**: Top-down vehicle silhouette
+- **Format**: PNG with alpha channel for transparency
+- **Usage**: Overlaid on final stitched result to show vehicle position
+- **Positioning**: Automatically centered in panoramic view
+
+### Mask Images
+
+The system uses blending masks to create smooth transitions between camera views:
+
+#### Mask Specifications
+
+- **Location**: `assets/masks/`
+- **Files**:
+ - `maskFront.jpg` - Front camera blending mask
+ - `maskBack.jpg` - Back camera blending mask
+ - `maskLeft.jpg` - Left camera blending mask
+ - `maskRight.jpg` - Right camera blending mask
+- **Purpose**: Define blending regions for seamless image stitching
+- **Format**: Grayscale images where brightness indicates blending weight
+
+### Calibration Board Details
+
+#### Pattern Configuration
+
+- **Grid Size**: 2 rows Γ 4 columns
+- **Corner Count**: 8 total corners
+- **Board Size**: Approximately 50cm Γ 100cm (physical dimensions)
+- **Visibility**: Clearly visible in all four camera views
+
+#### Detection Requirements
+
+- **Contrast**: High contrast between board and ground
+- **Lighting**: Even illumination without shadows
+- **Position**: Fully within camera field of view
+- **Orientation**: Rectangular pattern aligned with vehicle axes
+
+## Using Your Own Images
+
+### Camera Setup Requirements
+
+To use your own images with the AVM system:
+
+1. **Camera Positioning**:
+ - Install fisheye cameras at four positions around vehicle
+ - Ensure overlapping fields of view between adjacent cameras
+ - Maintain consistent height and angle
+
+2. **Calibration Board**:
+ - Create a 2Γ4 rectangular calibration pattern
+ - Position board in overlapping areas between camera views
+ - Ensure board is flat and clearly visible
+
+3. **Image Capture**:
+ - Capture images simultaneously from all four cameras
+ - Maintain consistent lighting conditions
+ - Ensure calibration board is visible in each image
+
+4. **File Preparation**:
+ - Save images as PNG or JPG format
+ - Name files: `front.png`, `back.png`, `left.png`, `right.png`
+ - Place in `assets/images/` directory
+
+### Camera Parameter Adjustment
+
+If using different cameras, you may need to adjust parameters in the source code:
+
+- **Focal Length**: Modify based on your camera specifications
+- **Distortion Coefficients**: Calibrate using OpenCV calibration tools
+- **Image Resolution**: Update if using different image sizes
+- **Fisheye Scale Factor**: Adjust based on lens characteristics
+
+For detailed parameter tuning, refer to the [Technical Specifications](TECHNICAL_SPECS.md).
diff --git a/docs/TECHNICAL_SPECS.md b/docs/TECHNICAL_SPECS.md
new file mode 100644
index 0000000..a5f748f
--- /dev/null
+++ b/docs/TECHNICAL_SPECS.md
@@ -0,0 +1,133 @@
+# Technical Specifications
+
+## Camera Parameters
+
+### Fisheye Camera Specifications
+
+- **Focal Length**: 910.0 pixels
+- **Pixel Size**: 3.0ΞΌm Γ 3.0ΞΌm
+- **Image Resolution**: 1280Γ960 pixels
+- **Fisheye Scaling Factor**: 0.5
+- **Undistortion Scaling**: 1.55
+
+### Distortion Model
+
+The system uses a polynomial fisheye distortion model:
+
+```
+ΞΈ_distorted = ΞΈ_undistorted + kβΞΈΒ³ + kβΞΈβ΅ + kβΞΈβ· + kβΞΈβΉ
+```
+
+Default distortion coefficients:
+
+- kβ = -0.05611147
+- kβ = -0.05377447
+- kβ = 0.0115717
+- kβ = 0.0030788
+
+## Calibration Board Specifications
+
+### Pattern Configuration
+
+- **Pattern Type**: Rectangular grid
+- **Grid Size**: 2Γ4 (2 rows, 4 columns)
+- **Corner Count**: 8 corners total
+- **Detection Method**: Histogram-based adaptive thresholding
+
+### Detection Parameters
+
+- **Contrast Enhancement**: 2.5Γ gamma correction
+- **Valid Detection Region**: Y-axis 20%-70% of image height
+- **Corner Refinement**: Sub-pixel accuracy using `cornerSubPix`
+- **Backup Detection**: Adaptive threshold with 401Γ401 kernel
+
+## Bird's Eye View Parameters
+
+### Image Dimensions
+
+- **Front/Back Views**: 792Γ305 pixels
+- **Left/Right Views**: 1131Γ281 pixels
+- **Final Stitched Image**: Variable based on layout
+
+### Transformation Matrices
+
+Each camera view uses homography transformation calculated from:
+
+- Source: Detected corner points in undistorted image
+- Target: Predefined bird's eye view coordinates
+
+### Rotation Corrections
+
+- **Front View**: 0Β° (no rotation)
+- **Back View**: 180Β°
+- **Left View**: 90Β° clockwise
+- **Right View**: 90Β° counter-clockwise
+
+## Image Stitching Parameters
+
+### Layout Configuration
+
+- **Back Image Offset**: Y = 643 pixels
+- **Right Image Offset**: X = 398 pixels
+- **Vehicle Overlay**: Center positioned with alpha blending
+
+### Blending Masks
+
+- Individual masks for each camera view
+- Smooth transition zones between adjacent views
+- Alpha channel support for vehicle model overlay
+
+## Performance Characteristics
+
+### Processing Pipeline Timing
+
+1. **Image Loading**: ~10ms per image
+2. **Undistortion**: ~50ms per image
+3. **Corner Detection**: ~100-200ms per image
+4. **Perspective Transform**: ~30ms per image
+5. **Image Stitching**: ~100ms total
+
+### Memory Requirements
+
+- **Input Images**: ~5MB (4 Γ 1280Γ960Γ3)
+- **Intermediate Results**: ~20MB
+- **Output Image**: ~2-3MB
+- **Total Peak Usage**: ~30-40MB
+
+## Algorithm Details
+
+### Corner Detection Algorithm
+
+1. **Preprocessing**:
+ - Convert to grayscale
+ - Apply gamma correction for contrast enhancement
+ - Set valid detection region (20%-70% Y-axis)
+
+2. **Binarization**:
+ - Histogram analysis for optimal threshold
+ - Bimodal distribution detection
+ - Adaptive fallback if histogram method fails
+
+3. **Contour Analysis**:
+ - Find contours in binary image
+ - Filter by area (minimum threshold)
+ - Approximate polygonal shapes
+
+4. **Rectangle Validation**:
+ - Verify 4-sided polygon structure
+ - Check geometric constraints
+ - Sort corners in consistent order
+
+5. **Coordinate Transformation**:
+ - Transform from fisheye to undistorted coordinates
+ - Apply sub-pixel refinement
+ - Validate final corner positions
+
+### Homography Calculation
+
+Uses OpenCV's `findHomography` with:
+
+- **Method**: Direct Linear Transform (DLT)
+- **Source Points**: 8 detected corners
+- **Target Points**: Predefined bird's eye coordinates
+- **Robustness**: No RANSAC (assumes clean input)
diff --git a/scripts/build.sh b/scripts/build.sh
new file mode 100644
index 0000000..764f911
--- /dev/null
+++ b/scripts/build.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+# Build script for avm AVM project
+# This script builds the OpenCV-based Around View Monitoring system
+
+set -e # Exit on any error
+
+echo "=== Building avm AVM Project ==="
+
+# Get the project root directory (parent of scripts directory)
+PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+cd "$PROJECT_ROOT"
+
+# Check if we're in the right directory
+if [ ! -f "CMakeLists.txt" ]; then
+ echo "Error: CMakeLists.txt not found. Please run this script from the project root directory."
+ exit 1
+fi
+
+# Check if OpenCV is installed
+if ! pkg-config --exists opencv4 && ! pkg-config --exists opencv; then
+ echo "Error: OpenCV not found. Please install OpenCV development packages."
+ echo "On Ubuntu/Debian: sudo apt-get install libopencv-dev"
+ exit 1
+fi
+
+# Display OpenCV version
+OPENCV_VERSION=$(pkg-config --modversion opencv4 2>/dev/null || pkg-config --modversion opencv 2>/dev/null)
+echo "Found OpenCV version: $OPENCV_VERSION"
+
+# Create build directory if it doesn't exist
+if [ ! -d "build" ]; then
+ echo "Creating build directory..."
+ mkdir build
+fi
+
+# Change to build directory
+cd build
+
+# Configure with CMake
+echo "Configuring with CMake..."
+cmake ..
+
+# Build the project
+echo "Building project..."
+make -j$(nproc)
+
+# Check if build was successful
+if [ -f "bin/avm" ]; then
+ echo "=== Build completed successfully! ==="
+ echo "Executable created: build/bin/avm"
+else
+ echo "=== Build failed! ==="
+ exit 1
+fi
diff --git a/scripts/clean.sh b/scripts/clean.sh
new file mode 100644
index 0000000..cc9dbf3
--- /dev/null
+++ b/scripts/clean.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+# Cleanup script for avm AVM project
+# This script removes all generated output files and build artifacts
+
+set -e # Exit on any error
+
+# Get the project root directory (parent of scripts directory)
+PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+cd "$PROJECT_ROOT"
+
+echo "=== Cleaning up avm AVM Project ==="
+
+# List of generated output files to remove
+OUTPUT_FILES=(
+ "stitched_result_with_su7.jpg"
+ "bird_front.jpg"
+ "bird_back.jpg"
+ "bird_left.jpg"
+ "bird_right.jpg"
+ "bird_front_2.jpg"
+ "bird_back_2.jpg"
+ "bird_left_2.jpg"
+ "bird_right_2.jpg"
+ "front_img_contrast.jpg"
+ "back_img_contrast.jpg"
+ "left_img_contrast.jpg"
+ "right_img_contrast.jpg"
+ "front_img_thresh.jpg"
+ "back_img_thresh.jpg"
+ "left_img_thresh.jpg"
+ "right_img_thresh.jpg"
+ "front_undis_1.jpg"
+ "back_undis_1.jpg"
+ "left_undis_1.jpg"
+ "right_undis_1.jpg"
+ "front_undis.jpg"
+ "back_undis.jpg"
+ "left_undis.jpg"
+ "right_undis.jpg"
+)
+
+# Remove generated output files
+echo "Removing generated output files..."
+REMOVED_COUNT=0
+for file in "${OUTPUT_FILES[@]}"; do
+ if [ -f "$file" ]; then
+ rm "$file"
+ echo " Removed: $file"
+ REMOVED_COUNT=$((REMOVED_COUNT + 1))
+ fi
+done
+
+if [ $REMOVED_COUNT -eq 0 ]; then
+ echo " No generated output files found to remove."
+else
+ echo " Removed $REMOVED_COUNT output files."
+fi
+
+# Remove build directory and all build artifacts
+if [ -d "build" ]; then
+ echo "Removing build directory..."
+ rm -rf build
+ echo " Removed: build/ directory and all build artifacts"
+else
+ echo " Build directory not found (already clean)."
+fi
+
+echo ""
+echo "To rebuild and run the project:"
+echo " ./build.sh"
+echo " ./run.sh"
diff --git a/scripts/run.sh b/scripts/run.sh
new file mode 100644
index 0000000..3de8d8d
--- /dev/null
+++ b/scripts/run.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+
+# Run script for avm AVM project
+# This script runs the Around View Monitoring system
+
+set -e # Exit on any error
+
+# Get the project root directory (parent of scripts directory)
+PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+cd "$PROJECT_ROOT"
+
+echo "=== Running avm AVM System ==="
+
+# Check if executable exists
+if [ ! -f "build/bin/avm" ]; then
+ echo "Error: avm executable not found."
+ echo "Please run the build script first: ./scripts/build.sh"
+ exit 1
+fi
+
+# Check if required input images exist
+REQUIRED_IMAGES=("assets/images/front.png" "assets/images/back.png" "assets/images/left.png" "assets/images/right.png")
+MISSING_IMAGES=()
+
+for img in "${REQUIRED_IMAGES[@]}"; do
+ if [ ! -f "$img" ]; then
+ MISSING_IMAGES+=("$img")
+ fi
+done
+
+if [ ${#MISSING_IMAGES[@]} -gt 0 ]; then
+ echo "Warning: Some required input images are missing:"
+ for img in "${MISSING_IMAGES[@]}"; do
+ echo " - $img"
+ done
+ echo "The program may not work correctly without all input images."
+ echo ""
+fi
+
+# Check if mask images exist
+MASK_IMAGES=("assets/masks/maskFront.jpg" "assets/masks/maskBack.jpg" "assets/masks/maskLeft.jpg" "assets/masks/maskRight.jpg")
+MISSING_MASKS=()
+
+for mask in "${MASK_IMAGES[@]}"; do
+ if [ ! -f "$mask" ]; then
+ MISSING_MASKS+=("$mask")
+ fi
+done
+
+if [ ${#MISSING_MASKS[@]} -gt 0 ]; then
+ echo "Warning: Some required mask images are missing:"
+ for mask in "${MISSING_MASKS[@]}"; do
+ echo " - $mask"
+ done
+ echo "The final stitching may not work correctly without all mask images."
+ echo ""
+fi
+
+# Check if su7.png exists for final overlay
+if [ ! -f "assets/images/su7.png" ]; then
+ echo "Warning: su7.png overlay image is missing. Final image will not include the car overlay."
+ echo ""
+fi
+
+echo "Starting AVM processing..."
+echo "This will:"
+echo "1. Detect corner points in fisheye camera images"
+echo "2. Apply undistortion and perspective transformation"
+echo "3. Generate bird's eye view images"
+echo "4. Stitch images together with masks"
+echo "5. Create final 360-degree around view image"
+echo ""
+
+# Run the program
+./build/bin/avm
+
+# Check if output was generated
+if [ -f "build/stitched_result_with_su7.jpg" ]; then
+ echo ""
+ echo "=== AVM Processing completed successfully! ==="
+ echo ""
+ echo "Generated output files:"
+ echo " - build/stitched_result_with_su7.jpg (Final stitched image)"
+ echo " - build/bird_front_2.jpg, build/bird_back_2.jpg, build/bird_left_2.jpg, build/bird_right_2.jpg (Bird's eye views)"
+ echo " - build/*_img_contrast.jpg (Contrast enhanced images)"
+ echo " - build/*_img_thresh.jpg (Thresholded images with detected points)"
+ echo " - build/*_undis_1.jpg (Undistorted images with corner points)"
+ echo ""
+ echo "You can view the final result: build/stitched_result_with_su7.jpg"
+else
+ echo "=== Warning: Expected output file not found ==="
+ echo "The program completed but build/stitched_result_with_su7.jpg was not generated."
+ echo "This might be due to missing input files or processing errors."
+fi
diff --git a/src/avm.cpp b/src/avm.cpp
new file mode 100644
index 0000000..01643ad
--- /dev/null
+++ b/src/avm.cpp
@@ -0,0 +1,1439 @@
+/**
+ * @file avm.cpp
+ * @brief Around View Monitor (AVM) System Implementation
+ * @description This program implements a surround view system based on four fisheye cameras,
+ * including image undistortion, corner detection, perspective transformation, and image stitching
+ */
+
+#include
+#include
+#include
+#include
+#include // For creating directories
+
+using namespace cv;
+using namespace std;
+
+// Constants definition
+#define IMAGE_BACK_PIXEL_Y 643 // Y offset for back view image in stitched result
+#define IMAGE_RIGHT_PIXEL_X 398 // X offset for right view image in stitched result
+
+// Global variables
+cv::Mat g_intrinsic_undis; // Undistortion intrinsic matrix
+cv::Mat g_intrinsic; // Original intrinsic matrix
+cv::Vec4d g_fish2undis_params; // Fisheye to undistortion transformation parameters
+
+// Corner coordinates for four directions
+std::vector g_corner_front; // Front view corners
+std::vector g_corner_back; // Back view corners
+std::vector g_corner_left; // Left view corners
+std::vector g_corner_right; // Right view corners
+
+/**
+ * @brief Image type enumeration
+ */
+typedef enum {
+ IMAGE_FRONT = 0, // Front view image
+ IMAGE_BACK, // Back view image
+ IMAGE_LEFT, // Left view image
+ IMAGE_RIGHT // Right view image
+} ImageType;
+
+/**
+ * @brief Image undistortion processing class
+ * @description Responsible for converting fisheye images to undistorted images
+ */
+class Undistort {
+public:
+ /**
+ * @brief Constructor, initializes undistortion parameters
+ */
+ Undistort();
+
+ /**
+ * @brief Perform image undistortion
+ * @param img Input fisheye image
+ * @param remap_table Remapping table (output parameter)
+ * @return Undistorted image
+ */
+ cv::Mat undistort_func(cv::Mat img, vector &remap_table);
+
+private:
+ /**
+ * @brief Generate undistortion remapping table
+ * @param remap_table Remapping table (output)
+ * @param undist_w Undistorted image width
+ * @param undist_h Undistorted image height
+ * @param intrinsic_undis Undistortion intrinsic matrix
+ * @param intrinsic_fish Fisheye intrinsic matrix
+ * @param undis_param Undistortion parameters
+ * @param fish_scale Fisheye scaling factor
+ */
+ void getUndistortMap(vector &remap_table, int undist_w, int undist_h,
+ cv::Mat intrinsic_undis, cv::Mat intrinsic_fish,
+ cv::Vec4d undis_param, float fish_scale);
+
+ // Member variables
+ int m_undis_width; // Undistorted image width
+ int m_undis_height; // Undistorted image height
+ float m_fish_scale; // Fisheye scaling factor
+ float m_focal_length; // Focal length
+ float m_dx; // X direction pixel spacing
+ float m_dy; // Y direction pixel spacing
+ float m_fish_width; // Fisheye image width
+ float m_fish_height; // Fisheye image height
+ float m_undis_scale; // Undistortion scaling factor
+ cv::Vec4d m_undis2fish_params; // Undistortion to fisheye parameters
+ cv::Mat m_intrinsic_undis; // Undistortion intrinsic matrix
+ cv::Mat m_intrinsic; // Original intrinsic matrix
+};
+
+/**
+ * @brief Undistort class constructor
+ * @description Initialize various parameters and intrinsic matrices for fisheye camera
+ */
+Undistort::Undistort() {
+ // Initialize camera parameters
+ m_fish_scale = 0.5f; // Fisheye scaling factor
+ m_focal_length = 910.0f; // Focal length
+ m_dx = 3.0f; // X direction pixel spacing
+ m_dy = 3.0f; // Y direction pixel spacing
+ m_fish_width = 1280.0f; // Fisheye image width
+ m_fish_height = 960.0f; // Fisheye image height
+ m_undis_scale = 1.55f; // Undistortion scaling factor
+
+ // Polynomial parameters from undistortion to fisheye
+ m_undis2fish_params = { 0.18238692, -0.08579553, 0.03366532, -0.00561911 };
+
+ // Calculate undistorted image dimensions
+ m_undis_width = static_cast(m_undis_scale * m_fish_width);
+ m_undis_height = static_cast(m_undis_scale * m_fish_height);
+
+ // Build undistortion intrinsic matrix
+ m_intrinsic_undis = (cv::Mat_(3, 3) << m_focal_length / m_dx * m_fish_scale, 0, m_fish_width / 2 * m_undis_scale,
+ 0, m_focal_length / m_dy * m_fish_scale, m_fish_height / 2 * m_undis_scale,
+ 0, 0, 1);
+
+ cout << "[INFO] Undistortion intrinsic matrix initialization completed" << endl;
+
+ // Build original intrinsic matrix
+ m_intrinsic = (cv::Mat_(3, 3) << m_focal_length / m_dx, 0, m_fish_width / 2,
+ 0, m_focal_length / m_dy, m_fish_height / 2,
+ 0, 0, 1);
+
+ cout << "[INFO] Original intrinsic matrix initialization completed" << endl;
+}
+
+/**
+ * @brief OpenCV-style point coordinate transformation
+ * @param warp_xy Output transformed coordinates
+ * @param map_center_h Mapping center Y coordinate
+ * @param map_center_w Mapping center X coordinate
+ * @param x_ Input X coordinate
+ * @param y_ Input Y coordinate
+ * @param scale Scaling factor
+ */
+void warpPointOpencv(cv::Vec2f &warp_xy, float map_center_h, float map_center_w,
+ float x_, float y_, float scale) {
+ warp_xy[0] = x_ * scale + map_center_w;
+ warp_xy[1] = y_ * scale + map_center_h;
+}
+
+/**
+ * @brief Transform from undistorted coordinate system to fisheye coordinate system
+ * @description Use polynomial distortion model to implement coordinate transformation
+ * @param fish_scale Fisheye scaling factor
+ * @param f_dx X direction focal length to pixel spacing ratio
+ * @param f_dy Y direction focal length to pixel spacing ratio
+ * @param large_center_h Undistorted image center Y coordinate
+ * @param large_center_w Undistorted image center X coordinate
+ * @param fish_center_h Fisheye image center Y coordinate
+ * @param fish_center_w Fisheye image center X coordinate
+ * @param undis_param Undistortion parameters
+ * @param x Input X coordinate
+ * @param y Input Y coordinate
+ * @return Transformed fisheye coordinates
+ */
+cv::Vec2f warpUndist2Fisheye(float fish_scale, float f_dx, float f_dy,
+ float large_center_h, float large_center_w,
+ float fish_center_h, float fish_center_w,
+ const cv::Vec4d &undis_param, float x, float y) {
+ f_dx *= fish_scale;
+ f_dy *= fish_scale;
+
+ // Convert to normalized plane coordinates
+ float y_ = (y - large_center_h) / f_dy;
+ float x_ = (x - large_center_w) / f_dx;
+ float r_ = static_cast(sqrt(pow(x_, 2) + pow(y_, 2)));
+
+ // Calculate angle
+ float angle_undistorted = atan(r_);
+
+ // Polynomial expansion
+ float angle_undistorted_p2 = angle_undistorted * angle_undistorted;
+ float angle_undistorted_p3 = angle_undistorted_p2 * angle_undistorted;
+ float angle_undistorted_p5 = angle_undistorted_p2 * angle_undistorted_p3;
+ float angle_undistorted_p7 = angle_undistorted_p2 * angle_undistorted_p5;
+ float angle_undistorted_p9 = angle_undistorted_p2 * angle_undistorted_p7;
+
+ // Apply distortion model
+ float angle_distorted = static_cast(
+ angle_undistorted + undis_param[0] * angle_undistorted_p3 +
+ undis_param[1] * angle_undistorted_p5 +
+ undis_param[2] * angle_undistorted_p7 +
+ undis_param[3] * angle_undistorted_p9);
+
+ // Calculate scaling ratio
+ float scale = angle_distorted / (r_ + 0.00001f);
+ cv::Vec2f warp_xy;
+
+ float xx = (x - large_center_w) / fish_scale;
+ float yy = (y - large_center_h) / fish_scale;
+
+ warpPointOpencv(warp_xy, fish_center_h, fish_center_w, xx, yy, scale);
+
+ return warp_xy;
+}
+void Undistort::getUndistortMap(vector &remap_table, int undist_w,
+ int undist_h, cv::Mat intrinsic_undis,
+ cv::Mat intrinsic_fish, cv::Vec4d undis_param,
+ float fish_scale) {
+ float fisheye_width = intrinsic_fish.at(0, 2) * 2.0f;
+ float fisheye_height = intrinsic_fish.at(1, 2) * 2.0f;
+
+ cv::Mat map_x(undist_h, undist_w, CV_32F);
+ cv::Mat map_y(undist_h, undist_w, CV_32F);
+
+ // Calculate remapping coordinates for each pixel
+ for (int i = 0; i < undist_h; i++) {
+ float *row_x = map_x.ptr(i);
+ float *row_y = map_y.ptr(i);
+
+ for (int j = 0; j < undist_w; j++) {
+ cv::Vec2f xy = warpUndist2Fisheye(
+ fish_scale, intrinsic_fish.at(0, 0),
+ intrinsic_fish.at(1, 1), intrinsic_undis.at(1, 2),
+ intrinsic_undis.at(0, 2), intrinsic_fish.at(1, 2),
+ intrinsic_fish.at(0, 2), undis_param,
+ static_cast(j), static_cast(i));
+
+ // Boundary protection
+ xy[0] = xy[0] >= 0 ? xy[0] : 0.0f;
+ xy[1] = xy[1] >= 0 ? xy[1] : 0.0f;
+ xy[0] = xy[0] < fisheye_width ? xy[0] : fisheye_width - 1.0f;
+ xy[1] = xy[1] < fisheye_height ? xy[1] : fisheye_height - 1.0f;
+
+ row_x[j] = xy[0];
+ row_y[j] = xy[1];
+ }
+ }
+
+ remap_table.push_back(map_x);
+ remap_table.push_back(map_y);
+}
+
+cv::Mat Undistort::undistort_func(cv::Mat img, vector &remap_table) {
+ // Calibration initialization
+ getUndistortMap(remap_table, m_undis_width, m_undis_height, m_intrinsic_undis,
+ m_intrinsic, m_undis2fish_params, m_fish_scale);
+
+ cv::Mat undis_img;
+ cv::remap(img, undis_img, remap_table[0], remap_table[1], cv::INTER_LINEAR);
+ return undis_img;
+}
+
+// ========================================
+// Histogram processing related functions (based on OpenCV source code)
+// ========================================
+
+/**
+ * @brief Calculate gradient of 256-level histogram
+ * @description Used to detect peaks and valleys in histogram
+ * @param piHist Input histogram
+ * @param piHistGrad Output gradient histogram
+ */
+template
+static void icvGradientOfHistogram256(const ArrayContainer &piHist,
+ ArrayContainer &piHistGrad) {
+ CV_DbgAssert(piHist.size() == 256);
+ CV_DbgAssert(piHistGrad.size() == 256);
+
+ piHistGrad[0] = 0;
+ int prev_grad = 0;
+
+ for (int i = 1; i < 255; ++i) {
+ int grad = piHist[i - 1] - piHist[i + 1];
+ if (std::abs(grad) < 100) {
+ if (prev_grad == 0)
+ grad = -100;
+ else
+ grad = prev_grad;
+ }
+ piHistGrad[i] = grad;
+ prev_grad = grad;
+ }
+ piHistGrad[255] = 0;
+}
+
+/**
+ * @brief Smooth histogram using sliding window
+ * @description Reduce noise in histogram, window size is 2*iWidth+1
+ * @param piHist Input histogram
+ * @param piHistSmooth Output smoothed histogram
+ * @param iWidth Smoothing window radius
+ */
+template
+static void icvSmoothHistogram256(const ArrayContainer &piHist,
+ ArrayContainer &piHistSmooth,
+ int iWidth = 0) {
+ CV_DbgAssert(iWidth_ == 0 || (iWidth == iWidth_ || iWidth == 0));
+ iWidth = (iWidth_ != 0) ? iWidth_ : iWidth;
+ CV_Assert(iWidth > 0);
+ CV_DbgAssert(piHist.size() == 256);
+ CV_DbgAssert(piHistSmooth.size() == 256);
+
+ for (int i = 0; i < 256; ++i) {
+ int iIdx_min = std::max(0, i - iWidth);
+ int iIdx_max = std::min(255, i + iWidth);
+ int iSmooth = 0;
+
+ for (int iIdx = iIdx_min; iIdx <= iIdx_max; ++iIdx) {
+ CV_DbgAssert(iIdx >= 0 && iIdx < 256);
+ iSmooth += piHist[iIdx];
+ }
+ piHistSmooth[i] = iSmooth / (2 * iWidth + 1);
+ }
+}
+
+/**
+ * @brief Calculate grayscale histogram of image
+ * @description Count the number of pixels for each grayscale level
+ * @param img Input single-channel image
+ * @param piHist Output 256-level histogram
+ */
+template
+static void icvGetIntensityHistogram256(const cv::Mat &img,
+ ArrayContainer &piHist) {
+ // Initialize histogram
+ for (int i = 0; i < 256; i++)
+ piHist[i] = 0;
+
+ // Count occurrence of each pixel value
+ for (int j = 0; j < img.rows; ++j) {
+ const uchar *row = img.ptr(j);
+ for (int i = 0; i < img.cols; i++) {
+ piHist[row[i]]++;
+ }
+ }
+}
+
+/**
+ * @brief Image binarization based on bimodal histogram
+ * @description Automatically determine optimal threshold by analyzing image histogram to segment image into foreground and background
+ * @param img Input single-channel image
+ * @param fish_undis_flag Whether it is a fisheye undistortion flag
+ * @return Binarized image
+ */
+static cv::Mat icvBinarizationHistogramBased(cv::Mat img, int fish_undis_flag) {
+ CV_Assert(img.channels() == 1 && img.depth() == CV_8U);
+
+ int iCols = img.cols;
+ int iRows = img.rows;
+ int iMaxPix = iCols * iRows;
+ int iMaxPix1 = iMaxPix / 100;
+ const int iNumBins = 256;
+ const int iMaxPos = 20;
+
+ // Allocate histogram buffers
+ cv::AutoBuffer piHistIntensity(iNumBins);
+ cv::AutoBuffer piHistSmooth(iNumBins);
+ cv::AutoBuffer piHistGrad(iNumBins);
+ cv::AutoBuffer piMaxPos(iMaxPos);
+
+ // Calculate intensity histogram
+ icvGetIntensityHistogram256(img, piHistIntensity);
+
+ // Smooth histogram distribution
+ icvSmoothHistogram256<1>(piHistIntensity, piHistSmooth);
+
+ // Calculate gradient
+ icvGradientOfHistogram256(piHistSmooth, piHistGrad);
+
+ // Detect zero points (peaks)
+ unsigned iCntMaxima = 0;
+ for (int i = iNumBins - 2; (i > 2) && (iCntMaxima < iMaxPos); --i) {
+ if ((piHistGrad[i - 1] < 0) && (piHistGrad[i] > 0)) {
+ int iSumAroundMax = piHistSmooth[i - 1] + piHistSmooth[i] + piHistSmooth[i + 1];
+ if (!(iSumAroundMax < iMaxPix1 && i < 64)) {
+ piMaxPos[iCntMaxima++] = i;
+ }
+ }
+ }
+
+ int iThresh = 0;
+ CV_Assert((size_t)iCntMaxima <= piMaxPos.size());
+
+ if (iCntMaxima == 0) {
+ // No peaks detected, use median intensity
+ const int iMaxPix2 = iMaxPix / 2;
+ for (int sum = 0, i = 0; i < 256; ++i) {
+ sum += piHistIntensity[i];
+ if (sum > iMaxPix2) {
+ iThresh = i;
+ break;
+ }
+ }
+ }
+ else if (iCntMaxima == 1) {
+ // Single peak distribution
+ iThresh = piMaxPos[0] / 2;
+ }
+ else if (iCntMaxima == 2) {
+ // Bimodal distribution
+ iThresh = (piMaxPos[0] + piMaxPos[1]) / 2;
+ }
+ else { // iCntMaxima >= 3, multimodal distribution
+ // Check threshold for white part
+ int iIdxAccSum = 0, iAccum = 0;
+ for (int i = iNumBins - 1; i > 0; --i) {
+ iAccum += piHistIntensity[i];
+ if (iAccum > (iMaxPix / 5)) {
+ iIdxAccSum = i;
+ break;
+ }
+ }
+
+ unsigned iIdxBGMax = 0;
+ int iBrightMax = piMaxPos[0];
+
+ // Find zero point closest to white part
+ for (unsigned n = 0; n < iCntMaxima - 1; ++n) {
+ iIdxBGMax = n + 1;
+ if (piMaxPos[n] < iIdxAccSum) {
+ break;
+ }
+ iBrightMax = piMaxPos[n];
+ }
+
+ // Check threshold for black part
+ int iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]];
+
+ // If too close to 255, skip to next peak
+ if (piMaxPos[iIdxBGMax] >= 250 && iIdxBGMax + 1 < iCntMaxima) {
+ iIdxBGMax++;
+ iMaxVal = piHistIntensity[piMaxPos[iIdxBGMax]];
+ }
+
+ // Find the largest black peak
+ for (unsigned n = iIdxBGMax + 1; n < iCntMaxima; n++) {
+ if (piHistIntensity[piMaxPos[n]] >= iMaxVal) {
+ iMaxVal = piHistIntensity[piMaxPos[n]];
+ iIdxBGMax = n;
+ }
+ }
+
+ // Set binarization threshold
+ int iDist2 = (iBrightMax - piMaxPos[iIdxBGMax]) / 2;
+ iThresh = iBrightMax - iDist2;
+
+ // Special processing for fisheye dark areas
+ if (fish_undis_flag == 0) {
+ auto temp = static_cast(iThresh) * 0.8f;
+ iThresh = static_cast(temp);
+ }
+ }
+
+ cv::Mat img_thresh(img.rows, img.cols, img.type());
+ if (iThresh > 0) {
+ img_thresh = (img >= iThresh);
+ }
+ return img_thresh;
+}
+
+// ========================================
+// Image processing and corner detection related functions
+// ========================================
+
+/**
+ * @brief Image contrast enhancement for corner detection
+ * @description Enhance image contrast through gamma correction for subsequent corner detection
+ * @param img Input three-channel image
+ * @param contrast Contrast enhancement coefficient
+ * @return Enhanced image
+ */
+cv::Mat imgAugForPointDetect(const cv::Mat img, float contrast) {
+ cv::Mat mat_float_tmp;
+
+ // Convert to 32-bit floating-point three-channel image
+ img.convertTo(mat_float_tmp, CV_32FC3);
+
+ // Normalize to [0,1]
+ mat_float_tmp = mat_float_tmp / 255.0f;
+
+ // Find maximum value
+ float maxvalue_ = 0.0f;
+ for (int i = 0; i < mat_float_tmp.rows; ++i) {
+ float *data = mat_float_tmp.ptr(i);
+ for (int j = 0; j < mat_float_tmp.cols; ++j) {
+ if (data[j] > maxvalue_) {
+ maxvalue_ = data[j];
+ }
+ }
+ }
+
+ // Normalize again
+ mat_float_tmp = mat_float_tmp / maxvalue_;
+
+ // Apply gamma correction to enhance contrast
+ pow(mat_float_tmp, contrast, mat_float_tmp);
+ mat_float_tmp = mat_float_tmp * 255.0f;
+
+ // Convert back to 8-bit unsigned integer
+ cv::Mat contrast_img;
+ mat_float_tmp.convertTo(contrast_img, CV_8UC3);
+
+ return contrast_img;
+}
+
+/**
+ * @brief Find rectangles (calibration board corners) in binary image
+ * @description Find quadrilateral calibration boards through contour detection and polygon approximation
+ * @param img Input binary image
+ * @param valid_region_y Valid detection region in Y direction
+ * @param max_sz Maximum area threshold
+ * @param fish_scale Fisheye scaling factor
+ * @param detect_points Detected corner points (output)
+ * @param fish_undis_flag Fisheye undistortion flag
+ */
+void findRectangle(cv::Mat img, std::vector valid_region_y, float max_sz,
+ float fish_scale, std::vector &detect_points,
+ int fish_undis_flag) {
+ std::vector> contours;
+ std::vector hierarchy;
+
+ float min_y_thresh = valid_region_y[0];
+ float max_y_thresh = valid_region_y[1];
+
+ // Calculate minimum area threshold
+ int min_size = static_cast(max_sz * (pow(fish_scale, 2)));
+ if (fish_undis_flag == 0) {
+ auto temp = static_cast(min_size) * 0.5f;
+ min_size = static_cast(temp);
+ }
+
+ float approx_level = 10.0f * fish_scale;
+
+ // Extract contours
+ cv::findContours(img, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
+
+ cv::Rect contour_rect;
+ cv::Point pt[4];
+
+ for (int idx = (int)(contours.size() - 1); idx >= 0; --idx) {
+ auto contour = contours[idx];
+ contour_rect = boundingRect(contour);
+
+ // Area filtering
+ if (contour_rect.area() < min_size) {
+ continue;
+ }
+
+ std::vector approx_contour;
+ // Polygon curve approximation
+ cv::approxPolyDP(contour, approx_contour, approx_level, true);
+
+ // Check if it's a quadrilateral
+ if (approx_contour.size() == 4) {
+ for (int i = 0; i < 4; ++i)
+ pt[i] = approx_contour[i];
+
+ // Check if center point is inside (black)
+ int x_lable = (pt[0].x + pt[2].x) / 2;
+ int y_lable = (pt[0].y + pt[2].y) / 2;
+ if (img.at(y_lable, x_lable) != 0) {
+ continue;
+ }
+
+ // Calculate perimeter and area
+ double p = cv::arcLength(approx_contour, true);
+ double area = cv::contourArea(approx_contour, false);
+
+ // Calculate diagonal lengths
+ double d1 = sqrt(cv::normL2Sqr(pt[0] - pt[2]));
+ double d2 = sqrt(cv::normL2Sqr(pt[1] - pt[3]));
+
+ // Calculate side lengths
+ double d3 = sqrt(cv::normL2Sqr(pt[0] - pt[1]));
+ double d4 = sqrt(cv::normL2Sqr(pt[1] - pt[2]));
+
+ // Shape validation: check if it's close to square
+ if (!(d3 * 5 > d4 && d4 * 5 > d3 && d3 * d4 < area * 10 &&
+ area > min_size && d1 >= 0.1 * p && d2 >= 0.1 * p)) {
+ continue;
+ }
+
+ // Y coordinate region validation
+ float contour_y_average = static_cast(
+ approx_contour[0].y + approx_contour[1].y +
+ approx_contour[2].y + approx_contour[3].y) /
+ 4.0f;
+
+ if (contour_y_average < min_y_thresh || contour_y_average > max_y_thresh) {
+ continue;
+ }
+
+ // Add detected corner points
+ detect_points.push_back(approx_contour[0]);
+ detect_points.push_back(approx_contour[1]);
+ detect_points.push_back(approx_contour[2]);
+ detect_points.push_back(approx_contour[3]);
+ }
+ }
+}
+
+// ========================================
+// Sorting comparison functions
+// ========================================
+
+/**
+ * @brief Comparison function for sorting contours by area in descending order
+ */
+bool cmp(std::vector A, std::vector B) {
+ return (contourArea(A) > contourArea(B));
+}
+
+/**
+ * @brief Comparison function for sorting by Y coordinate in descending order
+ */
+bool cmpYmax(cv::Point A, cv::Point B) {
+ return (A.y > B.y);
+}
+
+/**
+ * @brief Comparison function for sorting by X coordinate in descending order
+ */
+bool cmpXmax(cv::Point A, cv::Point B) {
+ return (A.x > B.x);
+}
+
+/**
+ * @brief Comparison function for sorting by Y coordinate in ascending order
+ */
+bool cmpYmin(cv::Point A, cv::Point B) {
+ return (A.y < B.y);
+}
+
+/**
+ * @brief Comparison function for sorting by X coordinate in ascending order
+ */
+bool cmpXmin(cv::Point A, cv::Point B) {
+ return (A.x < B.x);
+}
+
+/**
+ * @brief Sort detected corner points
+ * @description Sort 8 corner points in order from top to bottom, left to right
+ * @param points Input 8 corner points
+ * @return Sorted sequence of corner points
+ */
+static std::vector detectPointsSort(std::vector points) {
+ // Sort by Y coordinate from small to large
+ sort(points.begin(), points.end(), cmpYmin);
+
+ // Divide into two rows, 4 points per row
+ std::vector mid1(points.begin(), points.begin() + 4);
+ std::vector mid2(points.begin() + 4, points.begin() + 8);
+
+ // Sort by X coordinate from small to large within each row
+ sort(mid1.begin(), mid1.end(), cmpXmin);
+ sort(mid2.begin(), mid2.end(), cmpXmin);
+
+ // Merge results
+ std::vector sortedPoints(mid1.begin(), mid1.end());
+ sortedPoints.insert(sortedPoints.end(), mid2.begin(), mid2.end());
+
+ return sortedPoints;
+}
+
+// ========================================
+// Coordinate transformation related functions
+// ========================================
+
+/**
+ * @brief Inverse point coordinate transformation
+ * @param warp_xy Output transformed coordinates
+ * @param map_center_h Mapping center Y coordinate
+ * @param map_center_w Mapping center X coordinate
+ * @param x_ Input X coordinate
+ * @param y_ Input Y coordinate
+ * @param scale Scaling factor
+ */
+void warpPointInverse(cv::Vec2f &warp_xy, float map_center_h,
+ float map_center_w, float x_, float y_, float scale) {
+ warp_xy[0] = x_ * scale + map_center_w;
+ warp_xy[1] = y_ * scale + map_center_h;
+}
+
+/**
+ * @brief Transform from fisheye coordinate system to undistorted coordinate system
+ * @description Implement coordinate transformation from fisheye image to normal perspective image
+ * @param fish_scale Fisheye scaling factor
+ * @param f_dx X direction focal length to pixel spacing ratio
+ * @param f_dy Y direction focal length to pixel spacing ratio
+ * @param undis_center_h Undistorted image center Y coordinate
+ * @param undis_center_w Undistorted image center X coordinate
+ * @param fish_center_h Fisheye image center Y coordinate
+ * @param fish_center_w Fisheye image center X coordinate
+ * @param undis_param Undistortion parameters
+ * @param x Input X coordinate
+ * @param y Input Y coordinate
+ * @return Transformed undistorted coordinates
+ */
+cv::Vec2f warpFisheye2Undist(float fish_scale, float f_dx, float f_dy,
+ float undis_center_h, float undis_center_w,
+ float fish_center_h, float fish_center_w,
+ cv::Vec4d undis_param, float x, float y) {
+ // Pixel projection to normalized imaging coordinate system
+ float y_ = (y - fish_center_h) / f_dy;
+ float x_ = (x - fish_center_w) / f_dx;
+ float r_distorted = static_cast(sqrt(pow(x_, 2) + pow(y_, 2)));
+
+ // Calculate refraction angle according to distortion formula
+ float r_distorted_p2 = r_distorted * r_distorted;
+ float r_distorted_p3 = r_distorted_p2 * r_distorted;
+ float r_distorted_p4 = r_distorted_p2 * r_distorted_p2;
+ float r_distorted_p5 = r_distorted_p2 * r_distorted_p3;
+
+ float angle_undistorted = static_cast(
+ r_distorted + undis_param[0] * r_distorted_p2 +
+ undis_param[1] * r_distorted_p3 + undis_param[2] * r_distorted_p4 +
+ undis_param[3] * r_distorted_p5);
+
+ // Calculate scale factor in normalized image
+ float r_undistorted = tanf(angle_undistorted);
+ float scale = r_undistorted / (r_distorted + 0.00001f);
+
+ cv::Vec2f warp_xy;
+
+ // Convert to real image coordinate system
+ float xx = (x - fish_center_w) * fish_scale;
+ float yy = (y - fish_center_h) * fish_scale;
+
+ // Project to undistorted image coordinate system
+ warpPointInverse(warp_xy, undis_center_h, undis_center_w, xx, yy, scale);
+
+ return warp_xy;
+}
+
+/**
+ * @brief Detect calibration board corners
+ * @description Detect 2x4 arranged calibration board corners in image and convert them to undistorted coordinate system
+ * @param img Input image
+ * @param max_sz Maximum area threshold
+ * @param fish_scale Fisheye scaling factor
+ * @param detect_points Detected corner points (output)
+ * @param fish_undis_flag Fisheye undistortion flag
+ * @param src_image_type Source image type
+ * @return Whether 8 corner points were successfully detected
+ */
+bool detectPoints(cv::Mat img, float max_sz, float fish_scale,
+ std::vector &detect_points,
+ int fish_undis_flag, ImageType src_image_type) {
+ // Set valid detection region (Y direction)
+ float max_y_thresh = static_cast(0.7f * img.rows);
+ float min_y_thresh = static_cast(0.2f * img.rows);
+ std::vector y_valid_area{ min_y_thresh, max_y_thresh };
+
+ // Convert to grayscale image
+ if (img.channels() != 1) {
+ cv::cvtColor(img, img, COLOR_BGR2GRAY);
+ }
+
+ // Image contrast enhancement
+ float contrast = 2.5f;
+ cv::Mat img_contrast = imgAugForPointDetect(img, contrast);
+
+ // Save enhanced image for debugging
+ switch (src_image_type) {
+ case ImageType::IMAGE_FRONT:
+ cv::imwrite("build/front_img_contrast.jpg", img_contrast);
+ break;
+ case ImageType::IMAGE_BACK:
+ cv::imwrite("build/back_img_contrast.jpg", img_contrast);
+ break;
+ case ImageType::IMAGE_LEFT:
+ cv::imwrite("build/left_img_contrast.jpg", img_contrast);
+ break;
+ case ImageType::IMAGE_RIGHT:
+ cv::imwrite("build/right_img_contrast.jpg", img_contrast);
+ break;
+ default:
+ cv::imwrite("build/img_contrast.jpg", img_contrast);
+ }
+
+ // Histogram-based binarization
+ cv::Mat img_thresh = icvBinarizationHistogramBased(img_contrast, 0);
+
+ // Find rectangular corner points
+ findRectangle(img_thresh, y_valid_area, max_sz, fish_scale, detect_points, fish_undis_flag);
+
+ // If 8 corner points are not found, use backup solution
+ if (detect_points.size() != 8) {
+ // Adaptive threshold binarization
+ cv::adaptiveThreshold(img_contrast, img_thresh, 255,
+ cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 401, 5);
+ detect_points.clear();
+ findRectangle(img_thresh, y_valid_area, max_sz, fish_scale, detect_points, fish_undis_flag);
+ }
+
+ // Draw detected corner points on binary image for debugging
+ for (int i = 0; i < detect_points.size(); i++) {
+ cv::circle(img_thresh, detect_points[i], 1, cv::Scalar(0, 255, 0), 5);
+ }
+
+ // Save binarization results
+ switch (src_image_type) {
+ case ImageType::IMAGE_FRONT:
+ cv::imwrite("build/front_img_thresh.jpg", img_thresh);
+ break;
+ case ImageType::IMAGE_BACK:
+ cv::imwrite("build/back_img_thresh.jpg", img_thresh);
+ break;
+ case ImageType::IMAGE_LEFT:
+ cv::imwrite("build/left_img_thresh.jpg", img_thresh);
+ break;
+ case ImageType::IMAGE_RIGHT:
+ cv::imwrite("build/right_img_thresh.jpg", img_thresh);
+ break;
+ default:
+ cv::imwrite("build/img_thresh.jpg", img_thresh);
+ }
+
+ // Check if 8 corner points were successfully detected
+ if (detect_points.size() != 8) {
+ return false;
+ }
+
+ // Sub-pixel level corner optimization
+ cv::cornerSubPix(img, detect_points, cv::Size(9, 9), cv::Size(-1, -1),
+ TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 0.1));
+
+ // Sort corner points
+ detect_points = detectPointsSort(detect_points);
+
+ // Get camera intrinsic parameters
+ float f_dx = g_intrinsic.at(0, 0);
+ float f_dy = g_intrinsic.at(1, 1);
+ float fish_center_x = g_intrinsic.at(0, 2);
+ float fish_center_y = g_intrinsic.at(1, 2);
+ float undis_center_x = g_intrinsic_undis.at(0, 2);
+ float undis_center_y = g_intrinsic_undis.at(1, 2);
+ cv::Vec4d fish2undis_params = g_fish2undis_params;
+
+ // Convert corner points from fisheye coordinate system to undistorted coordinate system
+ cv::Vec2f xy;
+ for (int j = 0; j < 8; j++) {
+ xy = warpFisheye2Undist(fish_scale, f_dx, f_dy, undis_center_y,
+ undis_center_x, fish_center_y, fish_center_x,
+ fish2undis_params, detect_points[j].x, detect_points[j].y);
+
+ detect_points[j].x = xy[0];
+ detect_points[j].y = xy[1];
+ }
+
+ return true;
+}
+
+// ========================================
+// Bird's eye view transformation related global variables and functions
+// ========================================
+
+// Target corner coordinates for four directions in bird's eye view
+std::vector g_corner_bird_front; // Front view bird's eye corner points
+std::vector g_corner_bird_back; // Back view bird's eye corner points
+std::vector g_corner_bird_left; // Left view bird's eye corner points
+std::vector g_corner_bird_right; // Right view bird's eye corner points
+
+// Homography matrices for four directions
+cv::Mat g_Homo_F; // Front view homography matrix
+cv::Mat g_Homo_B; // Back view homography matrix
+cv::Mat g_Homo_L; // Left view homography matrix
+cv::Mat g_Homo_R; // Right view homography matrix
+
+/**
+ * @brief Initialize front view bird's eye target corner points
+ * @description Set standard corner point positions for front view image in bird's eye view
+ */
+void init_des_front_points(void) {
+ g_corner_bird_front = std::vector(8);
+
+ // First row corner point X coordinates
+ g_corner_bird_front[0].x = 136;
+ g_corner_bird_front[1].x = 256;
+ g_corner_bird_front[2].x = 536;
+ g_corner_bird_front[3].x = 656;
+
+ // Second row corner point X coordinates
+ g_corner_bird_front[4].x = 136;
+ g_corner_bird_front[5].x = 256;
+ g_corner_bird_front[6].x = 536;
+ g_corner_bird_front[7].x = 656;
+
+ // First row corner point Y coordinates
+ g_corner_bird_front[0].y = 85;
+ g_corner_bird_front[1].y = 85;
+ g_corner_bird_front[2].y = 85;
+ g_corner_bird_front[3].y = 85;
+
+ // Second row corner point Y coordinates
+ g_corner_bird_front[4].y = 205;
+ g_corner_bird_front[5].y = 205;
+ g_corner_bird_front[6].y = 205;
+ g_corner_bird_front[7].y = 205;
+}
+
+/**
+ * @brief Initialize back view bird's eye target corner points
+ * @description Set standard corner point positions for back view image in bird's eye view
+ */
+void init_des_back_points(void) {
+ g_corner_bird_back = std::vector(8);
+
+ // Corner point X coordinate settings
+ g_corner_bird_back[0].x = 136;
+ g_corner_bird_back[1].x = 256;
+ g_corner_bird_back[2].x = 536;
+ g_corner_bird_back[3].x = 656;
+ g_corner_bird_back[4].x = 136;
+ g_corner_bird_back[5].x = 256;
+ g_corner_bird_back[6].x = 536;
+ g_corner_bird_back[7].x = 656;
+
+ // Corner point Y coordinate settings
+ g_corner_bird_back[0].y = 85;
+ g_corner_bird_back[1].y = 85;
+ g_corner_bird_back[2].y = 85;
+ g_corner_bird_back[3].y = 85;
+ g_corner_bird_back[4].y = 205;
+ g_corner_bird_back[5].y = 205;
+ g_corner_bird_back[6].y = 205;
+ g_corner_bird_back[7].y = 205;
+}
+
+/**
+ * @brief Initialize left view bird's eye target corner points
+ * @description Set standard corner point positions for left view image in bird's eye view
+ */
+void init_des_left_points(void) {
+ g_corner_bird_left = std::vector(8);
+
+ // Corner point X coordinate settings
+ g_corner_bird_left[0].x = 85;
+ g_corner_bird_left[1].x = 205;
+ g_corner_bird_left[2].x = 926;
+ g_corner_bird_left[3].x = 1046;
+ g_corner_bird_left[4].x = 85;
+ g_corner_bird_left[5].x = 205;
+ g_corner_bird_left[6].x = 926;
+ g_corner_bird_left[7].x = 1046;
+
+ // Corner point Y coordinate settings
+ g_corner_bird_left[0].y = 136;
+ g_corner_bird_left[1].y = 136;
+ g_corner_bird_left[2].y = 136;
+ g_corner_bird_left[3].y = 136;
+ g_corner_bird_left[4].y = 256;
+ g_corner_bird_left[5].y = 256;
+ g_corner_bird_left[6].y = 256;
+ g_corner_bird_left[7].y = 256;
+}
+
+/**
+ * @brief Initialize right view bird's eye target corner points
+ * @description Set standard corner point positions for right view image in bird's eye view
+ */
+void init_des_right_points(void) {
+ g_corner_bird_right = std::vector(8);
+
+ // Corner point X coordinate settings
+ g_corner_bird_right[0].x = 85;
+ g_corner_bird_right[1].x = 205;
+ g_corner_bird_right[2].x = 926;
+ g_corner_bird_right[3].x = 1046;
+ g_corner_bird_right[4].x = 85;
+ g_corner_bird_right[5].x = 205;
+ g_corner_bird_right[6].x = 926;
+ g_corner_bird_right[7].x = 1046;
+
+ // Corner point Y coordinate settings
+ g_corner_bird_right[0].y = 136;
+ g_corner_bird_right[1].y = 136;
+ g_corner_bird_right[2].y = 136;
+ g_corner_bird_right[3].y = 136;
+ g_corner_bird_right[4].y = 256;
+ g_corner_bird_right[5].y = 256;
+ g_corner_bird_right[6].y = 256;
+ g_corner_bird_right[7].y = 256;
+}
+
+/**
+ * @brief Initialize bird's eye target corner points for all directions
+ * @description Call corner point initialization functions for each direction
+ */
+void init_des_points(void) {
+ init_des_front_points();
+ init_des_back_points();
+ init_des_left_points();
+ init_des_right_points();
+}
+
+/**
+ * @brief Initialize Around View Monitor system parameters
+ * @description Initialize all necessary parameters and data structures
+ */
+void init_params(void) {
+ init_des_points();
+}
+
+// ========================================
+// Image rotation and stitching related functions
+// ========================================
+
+/**
+ * @brief Rotate image
+ * @description Rotate image by specified angle and save to target path
+ * @param src_image_path Source image path
+ * @param dst_image_path Target image path
+ * @param angle1 Rotation angle (degrees)
+ */
+void rotate(string src_image_path, string dst_image_path, double angle1) { // Read image
+ Mat image = imread(src_image_path);
+ if (image.empty()) {
+ cout << "[ERROR] Unable to read image file: " << src_image_path << endl;
+ return;
+ }
+
+ // Get image dimensions
+ int height = image.rows;
+ int width = image.cols;
+
+ // Set rotation center as image center
+ Point2f center(width / 2.0f, height / 2.0f);
+
+ // Set rotation angle and scaling factor
+ double angle = angle1;
+ double scale = 1.0;
+
+ // Get rotation matrix
+ Mat rotationMatrix = getRotationMatrix2D(center, angle, scale);
+
+ // Calculate rotated image dimensions to avoid content being cropped
+ Rect bbox = RotatedRect(center, image.size(), angle).boundingRect();
+
+ // Adjust translation part of rotation matrix to fit new image dimensions
+ rotationMatrix.at(0, 2) += bbox.width / 2.0 - center.x;
+ rotationMatrix.at(1, 2) += bbox.height / 2.0 - center.y;
+
+ // Create output image
+ Mat rotatedImage;
+
+ // Apply affine transformation (rotation)
+ warpAffine(image, rotatedImage, rotationMatrix, bbox.size());
+
+ // Save rotated image
+ imwrite(dst_image_path, rotatedImage);
+}
+
+/**
+ * @brief Image stitching and merging
+ * @description Merge source image into target image at specified position
+ * @param src_image Source image
+ * @param des_image Target image
+ * @param src_image_type Source image type
+ * @return Merged image
+ */
+cv::Mat ImageMerge(cv::Mat &src_image, cv::Mat &des_image, ImageType src_image_type) {
+ if (src_image.empty() || des_image.empty()) {
+ return cv::Mat();
+ }
+
+ cv::Mat output;
+ des_image.copyTo(output);
+
+ src_image.convertTo(src_image, CV_32FC3);
+
+ if (src_image_type == ImageType::IMAGE_FRONT || src_image_type == ImageType::IMAGE_BACK) {
+ // Process front and back view images
+ for (int i = 0; i < src_image.rows; i++) {
+ for (int j = 0; j < des_image.cols; j++) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (src_image_type == ImageType::IMAGE_FRONT) {
+ output.at(i, j)[channel] =
+ static_cast(src_image.at(i, j)[channel]);
+ }
+ else if (src_image_type == ImageType::IMAGE_BACK) {
+ output.at(i + IMAGE_BACK_PIXEL_Y, j)[channel] =
+ static_cast(src_image.at(i, j)[channel]);
+ }
+ }
+ }
+ }
+ }
+ else if (src_image_type == ImageType::IMAGE_LEFT || src_image_type == ImageType::IMAGE_RIGHT) {
+ // Process left and right view images
+ for (int i = 0; i < src_image.rows; i++) {
+ for (int j = 0; j < src_image.cols; j++) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (src_image_type == ImageType::IMAGE_LEFT) {
+ output.at(i, j)[channel] +=
+ static_cast(src_image.at(i, j)[channel]);
+ }
+ else if (src_image_type == ImageType::IMAGE_RIGHT) {
+ output.at(i, j + IMAGE_RIGHT_PIXEL_X)[channel] +=
+ static_cast(src_image.at(i, j)[channel]);
+ }
+ }
+ }
+ }
+ }
+ return output;
+}
+
+/**
+ * @brief Image stitching with mask
+ * @description Use mask image for more precise image stitching
+ * @param src_image Source image
+ * @param mask_image Mask image
+ * @param des_image Target image
+ * @param src_image_type Source image type
+ * @return Merged image
+ */
+cv::Mat ImageMergeWithMask(cv::Mat &src_image, cv::Mat &mask_image,
+ cv::Mat &des_image, ImageType src_image_type) {
+ cv::Mat output(des_image.rows, des_image.cols, CV_8UC3, cv::Scalar(0, 0, 0));
+ return output;
+}
+
+/**
+ * @brief Panoramic image stitching main function
+ * @description Stitch four directional bird's eye view images into a complete panoramic view and add vehicle model
+ */
+void join() {
+ // Read four bird's eye view images and corresponding mask images
+ Mat img_front = imread("build/bird_front_2.jpg");
+ Mat img_back = imread("build/bird_back_2.jpg");
+ Mat img_left = imread("build/bird_left_2.jpg");
+ Mat img_right = imread("build/bird_right_2.jpg");
+
+ // Resize images to fit stitching
+ cv::resize(img_front, img_front, cv::Size(616, 237));
+ cv::resize(img_back, img_back, cv::Size(616, 237));
+ cv::resize(img_left, img_left, cv::Size(218, 880));
+ cv::resize(img_right, img_right, cv::Size(218, 880));
+
+ // Read mask images (three channels)
+ Mat mask_front = imread("assets/masks/maskFront.jpg");
+ Mat mask_back = imread("assets/masks/maskBack.jpg");
+ Mat mask_left = imread("assets/masks/maskLeft.jpg");
+ Mat mask_right = imread("assets/masks/maskRight.jpg"); // Check if images are loaded successfully
+ if (img_front.empty() || img_back.empty() || img_left.empty() || img_right.empty() ||
+ mask_front.empty() || mask_back.empty() || mask_left.empty() || mask_right.empty()) {
+ cout << "[ERROR] Unable to load one or more image or mask files" << endl;
+ return;
+ }
+
+ // Normalize mask images to [0,1] range
+ mask_front.convertTo(mask_front, CV_32FC3, 1.0 / 255.0);
+ mask_back.convertTo(mask_back, CV_32FC3, 1.0 / 255.0);
+ mask_left.convertTo(mask_left, CV_32FC3, 1.0 / 255.0);
+ mask_right.convertTo(mask_right, CV_32FC3, 1.0 / 255.0);
+
+ // Convert original images to floating point for multiplication
+ Mat img_front_float, img_back_float, img_left_float, img_right_float;
+ img_front.convertTo(img_front_float, CV_32FC3);
+ img_back.convertTo(img_back_float, CV_32FC3);
+ img_left.convertTo(img_left_float, CV_32FC3);
+ img_right.convertTo(img_right_float, CV_32FC3);
+
+ // Apply masks (pixel-wise multiplication)
+ Mat masked_front, masked_back, masked_left, masked_right;
+ multiply(img_front_float, mask_front, masked_front);
+ multiply(img_back_float, mask_back, masked_back);
+ multiply(img_left_float, mask_left, masked_left);
+ multiply(img_right_float, mask_right, masked_right);
+
+ // Convert back to 8-bit unsigned integer
+ masked_front.convertTo(masked_front, CV_8UC3);
+ masked_back.convertTo(masked_back, CV_8UC3);
+ masked_left.convertTo(masked_left, CV_8UC3);
+ masked_right.convertTo(masked_right, CV_8UC3);
+
+ // Get image dimensions
+ Size frontSize = masked_front.size();
+ Size backSize = masked_back.size();
+ Size leftSize = masked_left.size();
+ Size rightSize = masked_right.size();
+
+ // Calculate total dimensions of stitched image
+ int totalWidth = frontSize.width;
+ int totalHeight = leftSize.height;
+
+ // Create result image
+ Mat result = Mat::zeros(totalHeight, totalWidth, CV_8UC3);
+
+ // Stitch images - left side image
+ masked_left.copyTo(result(Rect(0, 0, leftSize.width, leftSize.height)));
+
+ // Stitch images - right side image (add to overlapping area with left side)
+ Mat roi_right = result(Rect(totalWidth - rightSize.width, 0, rightSize.width, rightSize.height));
+ add(roi_right, masked_right, roi_right);
+
+ // Stitch images - front side image (add to existing content)
+ Mat roi_front = result(Rect(0, 0, frontSize.width, frontSize.height));
+ add(roi_front, masked_front, roi_front);
+
+ // Stitch images - back side image (add to existing content)
+ Mat roi_back = result(Rect(0, leftSize.height - backSize.height, backSize.width, backSize.height));
+ add(roi_back, masked_back, roi_back);
+
+ // Add vehicle model image
+ Mat img_su7 = imread("assets/images/su7.png", IMREAD_UNCHANGED);
+ if (img_su7.empty()) {
+ cout << "[ERROR] Unable to load vehicle model image file: assets/images/su7.png" << endl;
+ return;
+ }
+
+ // Rotate vehicle model 90 degrees (counterclockwise)
+ Mat rotated_su7;
+ rotate(img_su7, rotated_su7, ROTATE_90_COUNTERCLOCKWISE);
+
+ // Calculate target size of vehicle model (adjust according to stitched image size)
+ double target_width = totalWidth * 0.5; // Set to 50% of total width
+ double scale = target_width / rotated_su7.cols;
+ Size target_size(target_width, rotated_su7.rows * scale);
+
+ // Resize vehicle model
+ Mat resized_su7;
+ resize(rotated_su7, resized_su7, target_size);
+
+ // Separate channels, get Alpha channel
+ vector channels;
+ split(resized_su7, channels);
+
+ // Create three-channel color image and Alpha mask
+ Mat color_su7;
+ Mat alpha_mask;
+
+ if (channels.size() == 4) { // BGRA image
+ vector color_channels = { channels[0], channels[1], channels[2] };
+ merge(color_channels, color_su7);
+ alpha_mask = channels[3]; // Alpha channel
+ }
+ else {
+ color_su7 = resized_su7;
+ alpha_mask = Mat::ones(resized_su7.size(), CV_8UC1) * 255;
+ }
+
+ // Convert Alpha mask to floating point and normalize
+ alpha_mask.convertTo(alpha_mask, CV_32F, 1.0 / 255.0);
+
+ // Calculate position of vehicle model in result image (center placement)
+ int x = (totalWidth - resized_su7.cols) / 2;
+ int y = (totalHeight - resized_su7.rows) / 2;
+
+ // Create ROI in result image
+ Mat roi_su7 = result(Rect(x, y, resized_su7.cols, resized_su7.rows));
+ Mat roi_su7_float;
+ roi_su7.convertTo(roi_su7_float, CV_32FC3);
+
+ // Convert vehicle model to floating point
+ Mat color_su7_float;
+ color_su7.convertTo(color_su7_float, CV_32FC3);
+
+ // Use Alpha blending formula: result = alpha * foreground + (1 - alpha) * background
+ for (int i = 0; i < roi_su7.rows; i++) {
+ for (int j = 0; j < roi_su7.cols; j++) {
+ float alpha = alpha_mask.at(i, j);
+ roi_su7_float.at(i, j) = alpha * color_su7_float.at(i, j) +
+ (1.0f - alpha) * roi_su7_float.at(i, j);
+ }
+ }
+
+ // Convert back to 8-bit unsigned integer
+ roi_su7_float.convertTo(roi_su7, CV_8UC3);
+
+ // Save final result
+ imwrite("build/stitched_result_with_su7.jpg", result);
+ cout << "[SUCCESS] Panoramic stitching completed, result saved: build/stitched_result_with_su7.jpg" << endl;
+}
+
+// ========================================
+// Main function
+// ========================================
+
+/**
+ * @brief Around View Monitor system main function
+ * @description Complete AVM processing pipeline: image undistortion, corner detection, perspective transformation, image stitching
+ * @return Program execution status
+ */
+int main() {
+ cout << "===========================================" << endl;
+ cout << "[SYSTEM] Around View Monitor (AVM) System Started" << endl;
+ cout << "===========================================" << endl;
+
+ // Create output directory
+ struct stat st = { 0 };
+ if (stat("build", &st) == -1) {
+ if (mkdir("build", 0755) == 0) {
+ cout << "[INIT] Output directory created: build/" << endl;
+ }
+ else {
+ cout << "[WARNING] Unable to create output directory, will use current directory" << endl;
+ }
+ }
+
+ // Initialize corner containers
+ g_corner_front = std::vector(8);
+ g_corner_back = std::vector(8);
+ g_corner_left = std::vector(8);
+ g_corner_right = std::vector(8);
+
+ // Set camera parameters
+ float fish_scale = 0.5f;
+ float focal_length = 910.0f;
+ int dx = 3;
+ int dy = 3;
+ int fish_width = 1280;
+ int fish_height = 960;
+ float undis_scale = 1.55f;
+
+ // Fisheye to undistortion parameters
+ g_fish2undis_params = { -0.05611147, -0.05377447, 0.0115717, 0.0030788 };
+
+ // Build undistortion intrinsic matrix
+ g_intrinsic_undis = (cv::Mat_(3, 3) << focal_length / dx * fish_scale, 0, fish_width / 2 * undis_scale,
+ 0, focal_length / dy * fish_scale, fish_height / 2 * undis_scale,
+ 0, 0, 1);
+
+ // Build original intrinsic matrix
+ g_intrinsic = (cv::Mat_(3, 3) << focal_length / dx, 0, fish_width / 2,
+ 0, focal_length / dy, fish_height / 2,
+ 0, 0, 1);
+
+ cout << "[INIT] Camera parameters initialization completed" << endl;
+
+ // Read fisheye images from four directions
+ cout << "[STEP 1] Reading fisheye images..." << endl;
+ cv::Mat image_f = imread("assets/images/front.png");
+ cv::Mat image_b = imread("assets/images/back.png");
+ cv::Mat image_l = imread("assets/images/left.png");
+ cv::Mat image_r = imread("assets/images/right.png");
+
+ if (image_f.empty() || image_b.empty() || image_l.empty() || image_r.empty()) {
+ cout << "[ERROR] Unable to read input image files" << endl;
+ return -1;
+ }
+ cout << "[SUCCESS] Successfully read 4 fisheye images" << endl;
+
+ // Create undistortion processing object
+ cout << "[STEP 2] Starting image undistortion processing..." << endl;
+ Undistort undistort_handle;
+ std::vector undis2dis_front, undis2dis_back, undis2dis_left, undis2dis_right;
+
+ // Perform image undistortion
+ cv::Mat front_undis = undistort_handle.undistort_func(image_f, undis2dis_front);
+ cv::Mat back_undis = undistort_handle.undistort_func(image_b, undis2dis_back);
+ cv::Mat left_undis = undistort_handle.undistort_func(image_l, undis2dis_left);
+ cv::Mat right_undis = undistort_handle.undistort_func(image_r, undis2dis_right);
+
+ // Save undistorted images
+ cv::imwrite("build/front_undis.jpg", front_undis);
+ cv::imwrite("build/back_undis.jpg", back_undis);
+ cv::imwrite("build/left_undis.jpg", left_undis);
+ cv::imwrite("build/right_undis.jpg", right_undis);
+ cout << "[SUCCESS] Undistorted image processing completed and saved" << endl;
+
+ // Detect calibration board corners
+ cout << "[STEP 3] Detecting calibration board corners..." << endl;
+ bool success = true;
+ success &= detectPoints(image_f, 20000, 0.5, g_corner_front, 0, ImageType::IMAGE_FRONT);
+ success &= detectPoints(image_b, 20000, 0.5, g_corner_back, 0, ImageType::IMAGE_BACK);
+ success &= detectPoints(image_l, 20000, 0.5, g_corner_left, 0, ImageType::IMAGE_LEFT);
+ success &= detectPoints(image_r, 20000, 0.5, g_corner_right, 0, ImageType::IMAGE_RIGHT);
+
+ if (!success) {
+ cout << "[WARNING] Some corner detection failed, continuing processing..." << endl;
+ }
+ else {
+ cout << "[SUCCESS] All directional corner detection completed" << endl;
+ }
+
+ // Mark detected corners on undistorted images
+ for (int j = 0; j < 8; j++) {
+ circle(front_undis, g_corner_front[j], 3, cv::Scalar(0, 255, 0), 1);
+ circle(back_undis, g_corner_back[j], 3, cv::Scalar(0, 255, 0), 1);
+ circle(left_undis, g_corner_left[j], 3, cv::Scalar(0, 255, 0), 1);
+ circle(right_undis, g_corner_right[j], 3, cv::Scalar(0, 255, 0), 1);
+ }
+
+ // Save corner-marked images
+ cv::imwrite("build/front_undis_1.jpg", front_undis);
+ cv::imwrite("build/back_undis_1.jpg", back_undis);
+ cv::imwrite("build/left_undis_1.jpg", left_undis);
+ cv::imwrite("build/right_undis_1.jpg", right_undis);
+ cout << "[SUCCESS] Corner-marked images saved" << endl;
+
+ // Initialize bird's eye view parameters
+ init_params();
+
+ // Re-read undistorted images for perspective transformation
+ cv::Mat undisimage_f = imread("build/front_undis.jpg");
+ cv::Mat undisimage_b = imread("build/back_undis.jpg");
+ cv::Mat undisimage_l = imread("build/left_undis.jpg");
+ cv::Mat undisimage_r = imread("build/right_undis.jpg");
+
+ // Calculate homography matrices
+ cout << "[STEP 4] Calculating perspective transformation matrices..." << endl;
+ g_Homo_F = cv::findHomography(g_corner_front, g_corner_bird_front, 0);
+ g_Homo_B = cv::findHomography(g_corner_back, g_corner_bird_back, 0);
+ g_Homo_L = cv::findHomography(g_corner_left, g_corner_bird_left, 0);
+ g_Homo_R = cv::findHomography(g_corner_right, g_corner_bird_right, 0);
+ cout << "[SUCCESS] Perspective transformation matrices calculation completed" << endl;
+
+ // Perform perspective transformation to generate bird's eye view
+ cout << "[STEP 5] Generating bird's eye view..." << endl;
+ cv::Mat bird_front_image, bird_back_image, bird_left_image, bird_right_image;
+
+ cv::warpPerspective(undisimage_f, bird_front_image, g_Homo_F,
+ cv::Size(792, 305), cv::INTER_LINEAR);
+ cv::warpPerspective(undisimage_b, bird_back_image, g_Homo_B,
+ cv::Size(792, 305), cv::INTER_LINEAR);
+ cv::warpPerspective(undisimage_l, bird_left_image, g_Homo_L,
+ cv::Size(1131, 281), cv::INTER_LINEAR);
+ cv::warpPerspective(undisimage_r, bird_right_image, g_Homo_R,
+ cv::Size(1131, 281), cv::INTER_LINEAR);
+
+ // Save initial bird's eye view images
+ cv::imwrite("build/bird_front.jpg", bird_front_image);
+ cv::imwrite("build/bird_back.jpg", bird_back_image);
+ cv::imwrite("build/bird_left.jpg", bird_left_image);
+ cv::imwrite("build/bird_right.jpg", bird_right_image);
+ cout << "[SUCCESS] Bird's eye view generation completed" << endl;
+
+ // Rotate bird's eye view images to correct orientation
+ cout << "[STEP 6] Adjusting bird's eye view orientation..." << endl;
+ rotate("build/bird_front.jpg", "build/bird_front_2.jpg", 0);
+ rotate("build/bird_back.jpg", "build/bird_back_2.jpg", 180);
+ rotate("build/bird_left.jpg", "build/bird_left_2.jpg", 90);
+ rotate("build/bird_right.jpg", "build/bird_right_2.jpg", -90);
+ cout << "[SUCCESS] Bird's eye view orientation adjustment completed" << endl;
+
+ // Perform panoramic stitching
+ cout << "[STEP 7] Performing panoramic image stitching..." << endl;
+ join();
+
+ cout << "===========================================" << endl;
+ cout << "[SYSTEM] Around View Monitor system processing completed" << endl;
+ cout << "===========================================" << endl;
+ return 0;
+}