
簡介這套基于 Python 與 OpenCV 的雙目視覺尺寸測量項目源碼及配套文檔面向需要完成畢業(yè)設(shè)計、期末大作業(yè)或課程設(shè)計的計算機視覺方向讀者旨在幫助快速搭建物體尺寸測量系統(tǒng)理解雙目視差、相機標定與三角測量等核心原理。資源包共 23 個文件壓縮后約 2.27MB內(nèi)含 21 張左右目測試圖像、1 個帶詳細注釋的 Python 主程序以及 1 份 Markdown 說明文檔代碼覆蓋圖像預處理、特征提取、立體匹配和尺寸換算等關(guān)鍵環(huán)節(jié)文檔則配合源碼講解項目結(jié)構(gòu)、運行方式與算法思路。整套項目目前已有 83 人學習界面直觀、功能完整可在本地直接部署運行項目經(jīng)過嚴格調(diào)試整體流程清晰適合作為高分離線項目參考。對初學者而言清晰的注釋能降低入門門檻對進階者也能提供從圖像標定到實際測距的完整工程參考。1. 雙目視覺測尺寸為什么說它比單目靠譜又容易在哪里翻車期末大作業(yè)要測一個紙盒的長寬高你首先想到的是用 OpenCV 加單目攝像頭把畫面里像素換算成毫米。但拍過就知道物體離鏡頭近一點、遠一點同樣一個盒子的像素高度變了而單目圖像里根本沒有深度信息比例尺是猜的?;?OpenCV 的雙目視覺測量被攝物體尺寸本質(zhì)就是用兩個固定間距的攝像頭模擬人眼通過左右圖像的視差把每個像素的深度算出來再在三維空間里量兩點距離。這個方案能解決的正是“物體不在同一平面、相機距離未知”時的尺寸測量問題適合期末大作業(yè)、畢設(shè)里需要展示完整技術(shù)鏈路的場景。它能同時拿到深度圖和三維坐標但前提是標定、立體匹配、測量三環(huán)都別出錯任何一個環(huán)節(jié)失守測出來的數(shù)字比單目還離譜。2. 從相機標定到極線校正先把雙目系統(tǒng)的“尺子”校準2.1 雙目測距的原理與坐標系視差、基線、焦距的關(guān)系雙目測尺寸的核心不是“拍兩張圖”而是知道左右兩個相機之間的空間關(guān)系。一個理想的雙目系統(tǒng)里左右相機光心距離叫基線b焦距是f空間中某一點 P 在左右相機成像平面上的水平坐標分別是xl和xr視差d xl - xr。根據(jù)相似三角形深度z f * b / d。有了 z再加上相機內(nèi)參就能把像素坐標(u, v)換算成相機坐標系下的三維坐標X (u - cx) * z / fx Y (v - cy) * z / fy Z z所以整個測量流程可以拆成三步先把左右相機各自的內(nèi)參和畸變算出來這叫單目標定再算兩個相機之間的旋轉(zhuǎn)矩陣 R 和平移向量 T這叫雙目標定最后把左右圖像校正成嚴格的“左右對齊只差視差”的形態(tài)這叫立體校正。校準這一步是后面所有數(shù)字的尺子尺子歪了測出來的尺寸全是錯的。2.2 標定板采集與 calibrateCamera 參數(shù)棋盤格數(shù)量與角點提取我一般建議用 OpenCV 的經(jīng)典標定流程不需要額外下載標定工具。首先打印一張棋盤格貼在硬紙板上。內(nèi)角點數(shù)量建議用 9×6 或者 8×6不要用太少角點太少解出來的內(nèi)參不穩(wěn)定。采集時左右相機各拍一組同一時刻拍同一個棋盤格姿勢至少拍 15 組角度要覆蓋傾斜、平移、遠近不同。采集代碼如下import cv2 import numpy as np # 棋盤格內(nèi)角點數(shù)比如橫向9個縱向6個 pattern_size (9, 6) criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) def collect_chessboard(cap_left, cap_right, save_dir, count20): for i in range(count): ret_l, frame_l cap_left.read() ret_r, frame_r cap_right.read() gray_l cv2.cvtColor(frame_l, cv2.COLOR_BGR2GRAY) gray_r cv2.cvtColor(frame_r, cv2.COLOR_BGR2GRAY) found_l, corners_l cv2.findChessboardCorners(gray_l, pattern_size, None) found_r, corners_r cv2.findChessboardCorners(gray_r, pattern_size, None) if found_l and found_r: corners_l cv2.cornerSubPix(gray_l, corners_l, (11, 11), (-1, -1), criteria) corners_r cv2.cornerSubPix(gray_r, corners_r, (11, 11), (-1, -1), criteria) cv2.imwrite(f{save_dir}/left_{i:02d}.jpg, frame_l) cv2.imwrite(f{save_dir}/right_{i:02d}.jpg, frame_r) print(f采集第 {i1} 組左右同時檢測到角點)cornerSubPix是把角點精度從像素級提升到亞像素級的關(guān)鍵窗口大小取(11, 11)即可。采集時要注意左右兩張圖必須同時按下快門或者用支持同步的雙目攝像頭否則棋盤格在運動中拍出來的左右位置不匹配后面的立體標定會出現(xiàn)無法收斂的畸變。保存圖像后再統(tǒng)一讀取文件做標定避免實時標定時相機還在自動調(diào)節(jié)曝光。這里有一個細節(jié)OpenCV 標定需要的是“世界坐標”的棋盤格角點如果用 9×6 棋盤每個格子邊長記得量準確單位用毫米。標定主體代碼def calibrate_camera(image_paths, pattern_size, square_size): # 生成棋盤格角點的三維世界坐標假設(shè)棋盤格在Z0平面 objp np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32) objp[:, :2] np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) objp * square_size obj_points [] img_points [] for path in image_paths: img cv2.imread(path) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, pattern_size, None) if ret: corners cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) obj_points.append(objp) img_points.append(corners) ret, mtx, dist, rvecs, tvecs cv2.calibrateCamera( obj_points, img_points, gray.shape[::-1], None, None) return mtx, distsquare_size是實際標定板的格子邊長單位必須一致比如 25 毫米后面測尺寸的結(jié)果單位就是毫米。如果這里寫錯內(nèi)參里的焦距會等比例錯最終測出來的長寬高全部偏移。標定完成之后用cv2.projectPoints把角點重新投影回圖像計算重投影誤差一般小于 0.1 像素算合格。如果誤差在 0.5 像素以上多半是采集圖像模糊、標定板不平整或者圖片數(shù)量太少。2.3 立體校正與 stereoRectify 參數(shù)alpha 和平衡單目標定之后還需要雙目標定來求兩臺相機的相對位置關(guān)系。這里用stereoCalibrate輸入左右相機各自的內(nèi)參和畸變系數(shù)以及每一對圖像的角點坐標輸出旋轉(zhuǎn)矩陣R、平移向量T。拿到R和T后用stereoRectify生成校正映射def stereo_rectify(mtx_l, dist_l, mtx_r, dist_r, R, T, image_size): R1, R2, P1, P2, Q, _, _ cv2.stereoRectify( mtx_l, dist_l, mtx_r, dist_r, image_size, R, T, alpha0, flagscv2.CALIB_ZERO_DISPARITY) map1_l, map2_l cv2.initUndistortRectifyMap( mtx_l, dist_l, R1, P1, image_size, cv2.CV_32FC1) map1_r, map2_r cv2.initUndistortRectifyMap( mtx_r, dist_r, R2, P2, image_size, cv2.CV_32FC1) return map1_l, map2_l, map1_r, map2_r, QstereoRectify的alpha參數(shù)控制校正后圖像保留多少原始像素。alpha0會裁剪掉圖像邊緣的非公共區(qū)域?qū)е乱暡顖D有效區(qū)域變小alpha1會保留全部像素但邊緣會出現(xiàn)黑色條帶。我一般取alpha0讓有效區(qū)域最大化同時配合CALIB_ZERO_DISPARITY讓主點保持一致這樣后續(xù) SGBM 搜索范圍更整齊。Q是重投影矩陣后面從視差圖轉(zhuǎn)三維坐標全靠它。校正之后可以用cv2.remap生成校正圖再用鼠標點同一物理點在左右圖上的像素坐標看是否在同一水平線上明顯不在就說明標定失敗。3. 用 OpenCV 實現(xiàn)視差圖與深度圖SGBM 參數(shù)是唯一玄學3.1 視差計算的最小閉環(huán)SGBM 創(chuàng)建與參數(shù)初始化標定和校正都通過后下一步是立體匹配。OpenCV 里有兩種常見的匹配器StereoBM和SGBM。BM 快但噪聲大SGBM 慢但更平滑實測中 SGBM 配合 WLS 濾波是期末作業(yè)和畢設(shè)里最穩(wěn)妥的組合。最小閉環(huán)代碼def create_sgbm(min_disparity0, num_disparities64, block_size11): left_matcher cv2.StereoSGBM_create( minDisparitymin_disparity, numDisparitiesnum_disparities, blockSizeblock_size, P18 * 3 * block_size ** 2, P232 * 3 * block_size ** 2, disp12MaxDiff1, uniquenessRatio10, speckleWindowSize100, speckleRange32, modecv2.STEREO_SGBM_MODE_SGBM_3WAY ) return left_matchernumDisparities必須能被 16 整除它決定了搜索的視差范圍。如果被測物體離相機較近視差范圍大取 96 或 128物體在 1 米以外64 就夠。blockSize必須是奇數(shù)值越大對噪聲越不敏感但也會抹掉邊緣細節(jié)。P1和P2是平滑懲罰項控制視差圖的平滑程度。經(jīng)驗值是小 blockSize 時用8 * 3 * blockSize**2和32 * 3 * blockSize**2當 blockSize 增大時P1、P2 按比例調(diào)大。uniquenessRatio用于排除低置信度的匹配點10 到 15 之間比較合適。這些參數(shù)沒有萬能取值我用一組默認值跑完再根據(jù)視差圖里的空洞和橫條紋調(diào)。3.2 從視差到深度重投影矩陣 Q 與 point cloud 的換算得到原始視差圖disp后需要用reprojectImageTo3D把它轉(zhuǎn)換成三維點集。這個函數(shù)用到雙目標定時輸出的Q矩陣def compute_depth(disp, Q, min_depth100, max_depth2000): # disp 是 int16 格式值表示實際視差 * 16 disp_float disp.astype(np.float32) / 16.0 disp_float[disp_float 0] 0.1 # 避免除零 points_3d cv2.reprojectImageTo3D(disp_float, Q, handleMissingValuesTrue) # 取出每個像素的深度 Z depth_map points_3d[:, :, 2] depth_map[depth_map min_depth] 0 depth_map[depth_map max_depth] 0 return points_3d, depth_map一個常見的坑SGBM 輸出的disp是定點數(shù)真實視差必須除以 16。如果漏掉這一步深度會小 16 倍測出來的尺寸也小 16 倍。另外handleMissingValuesTrue會把無效點置成 0但處理時會引入邊緣的異常值所以后面必須做深度裁剪。min_depth和max_depth根據(jù)你的拍攝距離設(shè)置比如物體離相機 50 到 150 厘米就設(shè) 500 和 1500 毫米能過濾掉大部分噪聲。如果你只想看深度可以用cv2.normalize把深度圖映射到 0-255 顯示但測量尺寸時一定要用三維坐標點而不是直接用視差換算的近似深度。3.3 深度圖后處理WLS 濾波與空洞填充的參數(shù)選擇原始視差圖通常有大量黑色空洞尤其是紋理少的區(qū)域比如紙箱的純色表面。OpenCV 的ximgproc模塊提供了 WLS 濾波需要左右兩個方向的一致性檢查。做法是先創(chuàng)建右匹配器算出右視差圖再傳給createDisparityWLSFilterdef wls_filter(left_matcher, left_img, right_img, disp_l, disp_r, sigma1.5, lmbda8000): right_matcher cv2.ximgproc.createRightMatcher(left_matcher) disp_r right_matcher.compute(right_img, left_img) wls_filter cv2.ximgproc.createDisparityWLSFilter(left_matcher) wls_filter.setLambda(lmbda) wls_filter.setSigmaColor(sigma) filtered_disp wls_filter.filter(disp_l, left_img, disparity_map_rightdisp_r) return filtered_displmbda是平滑權(quán)重值越大視差圖越平滑但實際物體的棱角也會被抹平導致邊緣向外擴測出來的尺寸偏大。我用 8000 到 10000 之間sigma用 1.5。濾波后仍然會有小塊空洞可以再做一步中值濾波或者形態(tài)學閉合。注意createRightMatcher使用的參數(shù)必須與左匹配器完全一致否則左右一致性檢查會失效。這一章做完你已經(jīng)能從一對圖像中得到每個像素的三維坐標接下來該怎么量尺寸取決于被測物體放在哪里、你要量的是哪個部位。4. 測量被攝物體的尺寸像素坐標到世界坐標的換算與 ROI 操作4.1 目標分割與基準平面擬合在最簡單場景下先跑通測量尺寸時最直接的思路是鼠標在左圖上框出被測區(qū)域然后取這一區(qū)域內(nèi)的三維點云計算兩點間距離。但要保證精度必須知道物體放置的平面。如果物體放在桌面上我們可以先用標定板或者一個已知平面擬合出桌面方程這樣物體表面即使不平整也能用平面投影來消除視角誤差。一個更簡單的方案適合期末大作業(yè)把被測物體放在一個棋盤格標定板上用標定板所在的平面作為基準面。檢測棋盤格角點得到該平面的位姿然后把物體上的像素點投影到這個平面。代碼思路如下def segment_object_by_roi(image, depth_map, roi): x, y, w, h roi roi_depth depth_map[y:yh, x:xw] # 用ROI內(nèi)深度中值作為物體表面深度 valid_depth roi_depth[roi_depth 0] if len(valid_depth) 0: return None surface_depth np.median(valid_depth) # 得到ROI中心像素的三維坐標 cx x w // 2 cy y h // 2 # 根據(jù)深度和相機內(nèi)參反算三維坐標 fx mtx_l[0, 0] fy mtx_l[1, 1] cx_intr mtx_l[0, 2] cy_intr mtx_l[1, 2] X (cx - cx_intr) * surface_depth / fx Y (cy - cy_intr) * surface_depth / fy Z surface_depth return (X, Y, Z)這個簡化模型假設(shè)物體表面是一個平面并且深度取中值。實測時如果物體的厚度不能忽略比如一個盒子要分別測頂面和放置平面的距離來得到高度而不是直接取表面深度。roi可以用cv2.selectROI讓用戶手動框選這比自動分割更穩(wěn)因為復雜背景下自動分割經(jīng)常把陰影和反光也算進去。4.2 尺寸計算兩點間歐氏距離與尺度因子有了兩點的三維坐標長寬就是三維空間里的歐氏距離。但如果你已經(jīng)讓物體貼著基準平面放置測量頂面兩個邊緣點之間的距離時需要把這兩個點投影到同一平面上否則因為透視傾斜算出來的距離比真實值偏大。我一般先擬合一個平面到點云數(shù)據(jù)然后把待測點垂直投影到這個平面再算投影后的距離。擬合平面可以用最小二乘OpenCV 沒有直接封裝但可以用np.linalg.lstsqdef fit_plane(points): # points: Nx3 矩陣 centroid points.mean(axis0) centered points - centroid _, _, vt np.linalg.svd(centered) normal vt[-1] d -np.dot(normal, centroid) return normal, d def project_to_plane(point, normal, d): # 點到平面投影 dist np.dot(normal, point) d return point - dist * normal這個函數(shù)可以復用標定板的角點把檢測到的棋盤格角點三維坐標喂進去得到標定板平面方程。測量物體輪廓上的任意點時候先投影到該平面再計算兩點距離能顯著減少相機傾斜帶來的誤差。實際操作中我會在左圖上用鼠標點擊物體的兩個角點然后去三維點云里取這兩個像素坐標對應的 XYZ。4.3 把測量程序封裝成函數(shù)輸入輸出與可視化為了讓代碼看起來像一個完整的“項目源碼”最好把整個流程封裝成一個類或者一組函數(shù)方便期末答辯時演示。下面是一個最小封裝class StereoMeasurer: def __init__(self, mtx_l, dist_l, mtx_r, dist_r, R, T): self.mtx_l mtx_l self.dist_l dist_l self.dist_r dist_r self.R R self.T T self.map1_l, self.map2_l, self.map1_r, self.map2_r, self.Q None, None, None, None, None def rectify(self, image_size, alpha0): self.R1, self.R2, self.P1, self.P2, self.Q, _, _ cv2.stereoRectify( self.mtx_l, self.dist_l, self.mtx_r, self.dist_r, image_size, self.R, self.T, alphaalpha) self.map1_l, self.map2_l cv2.initUndistortRectifyMap( self.mtx_l, self.dist_l, self.R1, self.P1, image_size, cv2.CV_32FC1) self.map1_r, self.map2_r cv2.initUndistortRectifyMap( self.mtx_r, self.dist_r, self.R2, self.P2, image_size, cv2.CV_32FC1) def compute_disparity(self, left, right, sgbm_params): left_rect cv2.remap(left, self.map1_l, self.map2_l, cv2.INTER_LINEAR) right_rect cv2.remap(right, self.map1_r, self.map2_r, cv2.INTER_LINEAR) matcher create_sgbm(**sgbm_params) disp matcher.compute(left_rect, right_rect) return disp def measure_distance(self, left, right, p1, p2, sgbm_params): disp self.compute_disparity(left, right, sgbm_params) _, depth_map compute_depth(disp, self.Q) # p1, p2 是左圖上的像素坐標 d1 depth_map[p1[1], p1[0]] d2 depth_map[p2[1], p2[0]] if d1 0 or d2 0: return None # 根據(jù)深度和相機內(nèi)參計算3D點 pt1 pixel_to_3d(p1, d1, self.mtx_l) pt2 pixel_to_3d(p2, d2, self.mtx_l) return np.linalg.norm(pt1 - pt2)pixel_to_3d函數(shù)就是前面提到的反投影公式??梢暬糠挚梢杂胏v2.imshow把視差圖和深度圖并排顯示再畫上你點擊的測量點和連線。所有這些代碼合在一起就是一個可供答辯演示的“基于 OpenCV 的雙目視覺尺寸測量”項目。5. 雙目測尺寸的常見坑與排查從標定到測量的 5 條血淚經(jīng)驗5.1 重投影誤差看著低測出來卻差一截現(xiàn)象calibrateCamera返回的重投影誤差只有 0.08 像素但測量一個 100 毫米的標準塊結(jié)果偏差超過 10 毫米。原因單目標定的重投影誤差只代表單目內(nèi)參自洽不代表雙目標定里的R、T準確。常見的是左右相機采集棋盤格時兩組圖像沒有嚴格同步或者棋盤格一半被遮擋角點檢測到的位置有偏移。另一個隱藏原因是標定板不平整打印紙貼在彎曲的紙板上角點世界坐標和真實位置有偏差。解決把左右相機固定在一個剛性支架上用外觸發(fā)或者同時拍照每張圖像檢查棋盤格所有內(nèi)角點都被完整檢測到標定板用玻璃貼片或硬塑料板。我習慣把采集的圖像數(shù)量從 15 組增加到 25 組并保證棋盤格在畫面四個角和中心都出現(xiàn)過。5.2 視差圖全是橫紋或者“鬼影”現(xiàn)象SGBM 計算出的視差圖有一條條的水平條紋物體邊緣像帶鋸齒的重影深度圖看起來是臟的色塊。原因左右圖像校正不徹底極線沒有嚴格對齊。stereoRectify之后沒有驗收直接丟給 SGBM。SGBM 的搜索窗口默認只做水平搜索如果極線有哪怕 1-2 個像素的偏差匹配就全亂。解決用cv2.remap校正后在左右圖上畫一條水平線觀察同一個角點是否落在同一條水平線上。如果有偏差檢查stereoRectify的入?yún)⑹遣皇亲笥覂?nèi)參寫反了或者R、T方向不對。另一個常見原因是相機分辨率不小但標定時沒有傳入正確的imageSize導致映射矩陣尺寸和原圖對不上。5.3 純色物體測出來的尺寸忽大忽小現(xiàn)象一個白色紙箱放在淺色桌面上視差圖里紙箱表面有大片空洞邊緣被噪聲覆蓋連續(xù)測量兩次結(jié)果差了 20 毫米。原因SGBM 依賴紋理來匹配左右圖像。純色區(qū)域沒有梯度匹配置信度低OpenCV 只能靠平滑項去猜猜出來的視差自然不穩(wěn)。解決最省事的辦法是在物體表面貼上帶紋理的貼紙或撒一點細小顆粒物如果不想破壞外觀就把blockSize調(diào)大讓平滑窗口覆蓋更大區(qū)域或者用 WLS 濾波把空洞補上。但要記住blockSize也不能無腦大它會把邊緣往里收窄導致測出來的尺寸偏小需要拿標準塊標定一次補償值。5.4 測量時相機被碰一下所有數(shù)據(jù)全廢現(xiàn)象標定和測量都正常但某次測量前相機支架被碰歪了之后測出的尺寸直接飄了。原因雙目測量的前提是兩個相機的相對位姿不變。只要左右相機之間有任何微小的旋轉(zhuǎn)和平移R、T和Q矩陣全部失效視差和深度跟著錯。解決相機支架要用螺絲鎖死不要用夾子或雙面膠。記錄每個標定板角點的三維坐標如果發(fā)現(xiàn)前后兩次標定得到的R、T變化超過 0.1 毫米量級就重新標定。另一個實用方案是做“在線校驗”每次開機拍一張固定位置的棋盤格計算當前的R、T如果和標定結(jié)果偏差大就報錯提醒。5.5 手動點擊測量點時亞像素精度不夠現(xiàn)象用鼠標點擊角點時的像素坐標是整數(shù)取深度時也是取單點像素的值導致兩三次測量重復性差。原因整數(shù)值像素對邊緣而言有 0.5 像素的量化誤差深度圖的單點噪聲又會被放大測出來的距離自然抖。解決測量點不要在 ROI 里取單個像素而是取該點周圍 3×3 或 5×5 窗口的深度中值。如果物體邊緣有清晰的角點用cv2.cornerSubPix先求亞像素角點再測。另外深度圖本身要先做中值濾波cv2.medianBlur(depth, 5)能有效抑制單點噪聲但要注意濾波核太大會把邊緣弄圓。6. 進階用自動標定與單應性簡化測量附驗證方法和驗收習慣如果你的項目時間不夠不想走完整雙目標定流程還有一種適合固定場景的簡化方案把相機固定在一個已知高度的支架上拍攝一個貼著棋盤格的平面然后用單應性矩陣建立像素到真實平面坐標的映射。這種方法只適合物體完全貼合這個平面、且沒有明顯厚度的場景比如測量一張紙的長度、一個 PCB 板的尺寸。它不需要 SGBM直接以棋盤格角點為基準計算單應性矩陣H然后測量任意兩點在平面上的距離。這個方案速度更快精度取決于標定板到相機的距離和棋盤的角點檢測精度通常能達到 0.5 毫米以內(nèi)前提是物體高度差不超過 2 毫米。它的局限是量不了高度量不了圓柱和斜面。驗證測量結(jié)果時不要只測一個標準塊就宣布成功。我建議準備三組參照物硬幣直徑已知 25 毫米、A4 紙寬 210 毫米和一個手機長度可查。每個物體測 10 次記錄每次的像素坐標和計算結(jié)果計算均值和標準差。如果標準差超過 1 毫米說明圖像采集或者 SGBM 的穩(wěn)定性不夠檢查光線是否變化、物體是否反光、相機是否用了自動對焦——自動對焦是測量的大敵必須手動鎖焦。另外每次測量前都先測一次固定位置的棋盤格用重投影誤差作為當日系統(tǒng)的“健康指標”。我最后的習慣是把每一組測量數(shù)據(jù)連同當時的視差圖、深度圖一起存成一個文件夾命名帶上日期和工況。這樣答辯時老師問“這個結(jié)果怎么來的”我能直接調(diào)出原始數(shù)據(jù)復現(xiàn)而不是只給一張截圖。這個習慣幫我挽回過好多次因為環(huán)境光變化導致結(jié)果無法復現(xiàn)的局面。雙目測尺寸這條路真正難的不是算法是你有沒有把所有會導致誤差的細節(jié)都看住。希望這篇筆記能幫你在期末或畢設(shè)里少走幾步彎路。本文還有配套的精品資源點擊獲取