BƯỚC 01
Bài toán và cách chuẩn bị
Hai camera nhìn một điểm ở hai vị trí khác nhau trên ảnh. Với cặp ảnh đã hiệu chỉnh phù hợp, độ lệch ngang giúp suy ra độ sâu. Bài này không che sự nhạy cảm của phép chia: cùng sai số nửa pixel có ảnh hưởng rất khác ở vật gần và vật xa.
Học sau phép chiếu, hiệu chuẩn và PnP. Cần biết đơn vị tiêu cự, baseline và phép đạo hàm cơ bản. Tạo một thư mục riêng cho bài. Chương trình tự tạo dữ liệu, chạy trên CPU và lưu ảnh trong thư mục results cạnh tệp mã.
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install numpy matplotlib opencv-pythonÝ nghĩa đoạn mã
venv tạo môi trường riêng. Lệnh pip cài các thư viện vào đúng môi trường đó. Không cần tải mô hình hay bộ dữ liệu bên ngoài cho thí nghiệm này.
BƯỚC 02
Ý tưởng cần nắm
Với hai camera pinhole song song, cùng tiêu cự và tọa độ tâm chính đã được xử lý nhất quán, f tính bằng pixel, B là baseline theo mét, d là disparity theo pixel, nên Z có đơn vị mét. Xấp xỉ độ lớn sai số nhỏ là
BƯỚC 03
Tạo dữ liệu và thực hiện phép tính
Mã tạo disparity lý tưởng ở độ sâu từ 1 đến 12 m với baseline 0,12 m và tiêu cự 700 pixel. Cộng cùng một sai số +0,5 pixel rồi so sánh độ sâu ước lượng với giá trị thật. Một mảng riêng chứa disparity bằng 0, âm và NaN để kiểm tra mặt nạ hợp lệ. Không thay chúng bằng một số rất nhỏ rồi diễn giải độ sâu khổng lồ như kết quả đo.
from pathlib import Path
import json
import numpy as np
import cv2 as cv
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
out = Path(__file__).resolve().parent / "results"
out.mkdir(exist_ok=True)
rng = np.random.default_rng(23)
plt.rcParams.update({"figure.facecolor": "#f7f8f2", "axes.spines.top": False, "axes.spines.right": False})
f=700.
baseline=.12
depth=np.linspace(1,12,100)
disparity=f*baseline/depth
estimated=f*baseline/(disparity+.5)
first_order=(depth**2/(f*baseline))*.5
valid_disparity=np.array([30.,0.,-2.,np.nan])
valid=np.isfinite(valid_disparity)&(valid_disparity>0)
safe_depth=np.full_like(valid_disparity,np.nan)
safe_depth[valid]=f*baseline/valid_disparity[valid]
assert valid.sum()==1 and np.isclose(safe_depth[0],2.8)
assert abs(estimated[-1]-depth[-1])>abs(estimated[0]-depth[0])Ý nghĩa đoạn mã
Path(__file__) xác định thư mục chứa tệp, vì vậy kết quả không phụ thuộc thư mục đang mở trong terminal. Các seed cố định giúp đối chiếu lần chạy. Những lệnh assert sẽ dừng chương trình nếu quan hệ cần kiểm tra không còn đúng.
BƯỚC 04
Vẽ kết quả để đối chiếu
Giữ cùng thang đo khi so sánh các ảnh. Đoạn mã dưới lưu result.png cùng các số kiểm tra. Những nhãn tiếng Anh trong biểu đồ trùng với tên biến để bạn dễ đối chiếu khi sửa chương trình.
fig,axes=plt.subplots(1,2,figsize=(11,4))
axes[0].plot(depth,disparity,color="#357354")
axes[0].set(xlabel="Depth Z (m)",ylabel="Disparity d (pixels)",title="Rectified parallel cameras")
axes[1].plot(depth,np.abs(estimated-depth),label="Exact error for +0.5 px")
axes[1].plot(depth,first_order,"--",label="First-order approximation")
axes[1].set(xlabel="True depth (m)",ylabel="Absolute depth error (m)")
axes[1].legend()
fig.tight_layout()
fig.savefig(out / "result.png",dpi=150)
print(json.dumps({"depth_error_at_1m":float(abs(estimated[0]-depth[0])),"depth_error_at_12m":float(abs(estimated[-1]-depth[-1]))}))
Ý nghĩa đoạn mã
Figure chứa bố cục biểu đồ. tight_layout giảm chồng lấn nhãn, savefig lưu ảnh 150 dpi. Backend Agg cho phép xuất hình cả khi không mở cửa sổ đồ họa. Dòng JSON cuối chứa các số để đối chiếu với hình.
BƯỚC 05
Chạy và đọc kết quả
Sai số ở 1 m khoảng 0,0059 m, còn ở 12 m là 0,8 m trong lần chạy này. Đường xấp xỉ bậc nhất gần đường sai số chính xác khi nhiễu nhỏ so với disparity. Ví dụ nhận disparity đã biết, chưa thực hiện stereo matching. Với StereoBM hoặc StereoSGBM, cần hiểu hệ số lưu disparity, mặt nạ không hợp lệ và ảnh đã rectified trước khi dùng công thức. Ảnh màu hóa disparity chỉ để xem, không phải bản đồ độ sâu theo mét.
Ảnh dưới được xuất từ chính chương trình của bài. Kết quả số có thể chênh lệch nhẹ giữa các phiên bản thư viện. Các kiểm tra assert xác nhận những quan hệ quan trọng trong thí nghiệm, không thay thế đánh giá trên dữ liệu sử dụng thực tế.

.\.venv\Scripts\python.exe geometry-stereo-depth.pyÝ nghĩa đoạn mã
Lệnh gọi đúng Python trong .venv và chạy tệp đã tải đầy đủ. Mở results/result.png cạnh tệp mã để xem hình. Nếu assert báo lỗi, kiểm tra thay đổi dữ liệu hoặc tham số trước khi bỏ kiểm tra.
ĐẾN LƯỢT BẠN
Thử một thay đổi nhỏ
- Tăng baseline lên 0,24 m rồi so sánh sai số.
- Sau đó giữ baseline và đổi sai số disparity thành −0,5 pixel.
- Giải thích vì sao hai phía nhiễu không cho sai số độ sâu hoàn toàn đối xứng.




