2025 年全國大學生電子設計競賽 C 題
發揮部分 1:多正方形 / 重疊正方形高精度識別與最小邊長測量
香橙派 + OpenCV C++ 全流程解析
目錄
賽題背景與需求 技術難點全景圖 系統總體架構 硬件平臺與接線 軟件架構與線程模型 算法流水線逐幀拆解 6.1 圖像預處理 6.2 輪廓提取與面積過濾 6.3 重疊正方形分割:向量夾角法 6.4 最小正方形邊長計算 6.5 透視畸變補償 6.6 亞像素級優化 關鍵代碼剖析 香橙派編譯與燒錄 調試工具鏈 性能 Benchmark 常見問題 FAQ 拓展閱讀與開源倉庫
1 賽題背景與需求
2025 年電賽 C 題 發揮部分 1 要求:
指標 說明 目標 正方形組合圖形,6 cm ~ 12 cm 邊長 狀態 可彼此分離,也可 局部重疊 ≤ 30 % 輸出 最小正方形邊長 ,誤差 ≤ 0.5 cm限制 單目固定攝像頭,禁止 PC,一鍵啟動,5 s 內完成
2 技術難點全景圖
難點 場景示例 傳統方案痛點 本文解決策略 邊緣粘連 兩正方形重疊 25 % 大輪廓誤判為 1 個 向量夾角分割 透視拉伸 視角傾斜 45° 像素長度失真 Homography + cosθ 補償 實時性 720 p 30 fps CPU 滿載 80 % NEON + ROI 裁剪 量化誤差 像素 → 厘米 ±1 px ≈ ±0.8 cm 亞像素角點 零依賴 現場無網 Tesseract 不可用 純 OpenCV
3 系統總體架構
4 硬件平臺與接線
模塊 接口 引腳 供電 備注 OV5640 MIPI-CSI CAM1 3.3 V 自帶 24 MHz 時鐘 OLED I2C1 PB8_SCL PB9_SDA 3.3 V 128×64 SSD1306 按鍵 GPIO PC13 3.3 V 一鍵啟動 調試串口 UART0 PA9_TX PA10_RX 5 V→3.3 V CH340G
5 軟件架構與線程模型
main.cpp 初始化攝像頭 → 啟動 4 個 std::thread
pic_deal.cpp thread_deal.cpp uart.cpp
6 算法流水線逐幀拆解
6.1 圖像預處理
Mat gray;
cvtColor ( frame, gray, COLOR_BGR2GRAY) ;
Ptr< CLAHE> clahe = createCLAHE ( 2.0 , Size ( 8 , 8 ) ) ;
clahe-> apply ( gray, gray) ;
GaussianBlur ( gray, blur, Size ( 5 , 5 ) , 1 ) ;
Canny ( blur, edges, 50 , 150 ) ;
6.2 輪廓提取與面積過濾
vector< vector< Point>> contours;
findContours ( edges, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE) ;
vector< RotatedRect> candidates;
for ( auto & c : contours) { double a = contourArea ( c) ; if ( a < 500 || a > 0.3 * frame. total ( ) ) continue ; RotatedRect rr = minAreaRect ( c) ; float ratio = rr. size. width/ rr. size. height; if ( ratio > 0.9f && ratio < 1.1f ) candidates. push_back ( rr) ;
}
6.3 重疊正方形分割:向量夾角法
6.3.1 四邊形頂點排序
vector< Point2f> orderPointsAlongContour ( const vector< Point> & contour, const vector< Point2f> & pts) { vector< float > cumLen ( contour. size ( ) ) ; float acc = 0 ; for ( size_t i= 1 ; i< contour. size ( ) ; ++ i) { acc += norm ( contour[ i] - contour[ i- 1 ] ) ; cumLen[ i] = acc; } return ordered;
}
6.3.2 向量夾角驗證
const double ANGLE_THRESH = CV_PI/ 18.0 ;
for ( size_t i= 0 ; i< ordered. size ( ) ; i+= 4 ) { Point2f v1 = ordered[ ( i+ 1 ) % 4 ] - ordered[ i] ; Point2f v2 = ordered[ ( i+ 2 ) % 4 ] - ordered[ ( i+ 1 ) % 4 ] ; double angle = fabs ( atan2 ( v1. cross ( v2) , v1. dot ( v2) ) ) ; if ( angle < ANGLE_THRESH) { squares. emplace_back ( ordered[ i] , ordered[ ( i+ 1 ) % 4 ] ) ; }
}
6.4 最小正方形邊長計算
double minSide = DBL_MAX;
for ( const auto & sq : squares) { double len = norm ( sq. first - sq. second) ; minSide = std:: min ( minSide, len * scale_w) ;
}
squareEdgeResult. minEdgeLength = minSide;
6.5 透視畸變補償
Homography 計算 :利用 A4 紙 4 角點cosθ 修正 :
6.6 亞像素級優化
cornerSubPix ( gray, corners, Size ( 5 , 5 ) , Size ( - 1 , - 1 ) , TermCriteria ( TermCriteria:: EPS+ TermCriteria:: MAX_ITER, 30 , 0.001 ) ) ;
7 關鍵代碼剖析
文件 職責 亮點 shibie_Square_min.cpp
重疊分割 + 最小邊 向量夾角法零依賴 pic_deal.cpp
全流程 NEON intrinsics 加速 thread_deal.cpp
多線程 無鎖隊列 + condition_variable
8 香橙派編譯與燒錄
8.1 依賴
sudo apt update
sudo apt install build-essential cmake libopencv-dev
8.2 一鍵腳本
git clone https://github.com/langhaofu/2025-C-Software.git
cd 2025 -C-Advance
chmod +x build.sh run.sh
./build.sh
./run.sh
9 調試工具鏈
工具 用途 指令 htop
CPU 占用 htop
perf
NEON 指令 perf stat ./bin/2025_C
v4l2-ctl
攝像頭參數 v4l2-ctl -d 0 --list-formats-ext
imwrite("debug.jpg")
中間結果 現場回溯
10 性能 Benchmark
場景 真值 測量 誤差 耗時 兩正方形重疊 25 % 最小 8 cm 8.1 cm 0.1 cm 1.7 s 三正方形并排 最小 6 cm 6.0 cm 0.0 cm 1.5 s 傾斜 40° 重疊 最小 10 cm 10.2 cm 0.2 cm 1.8 s 隨機 5 正方形 最小 7 cm 7.1 cm 0.1 cm 1.6 s
11 常見問題 FAQ
問題 根因 解決 最小邊 0 cm 角點 <4 個 降低 Canny 閾值 重疊未分割 面積過濾過嚴 調低 minArea CPU 100 % NEON 未開啟 -mfpu=neon
畫面卡頓 分辨率過高 鎖 640×480
12 拓展閱讀與開源倉庫
GitHub:github.com/langhaofu/2025-C-Software 香橙派鏡像:2025-C-ubuntu-22.04-lite.img.xz
本方案 純 OpenCV 實現,已在現場驗證 1.8 s 完成全流程。歡迎 Star & PR!