OpenCV:圖像拼接(SIFT 特征匹配 + 透視變換)

目錄

一、核心技術原理與對應 API 解析

1.1 SIFT 特征檢測與描述(尺度不變特征提取)

1.1.1 灰度圖轉換:cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

1.1.2 SIFT 檢測器初始化:cv2.SIFT_create()

1.1.3 特征點檢測與描述符計算:sift.detectAndCompute(gray, None)

1.1.4 特征點坐標格式轉換:np.float32([kp.pt for kp in kps])

1.2 特征匹配與篩選(BFMatcher+KNN 策略)

1.2.1 暴力匹配器初始化:cv2.BFMatcher()

1.2.2 KNN 匹配:matcher.knnMatch(desB, desA, k=2)

1.2.3 優質匹配對篩選:距離比值法

1.2.4 匹配結果可視化:cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

1.3 透視變換(Homography):統一圖像視角

1.3.1 透視變換矩陣計算:cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 10)

1.3.2 執行透視變換:cv2.warpPerspective(imageB, H, (imageB.shape[1] + imageA.shape[1], imageB.shape[0]))

1.4 圖像融合與保存

1.4.1 圖像拼接融合

1.4.2 圖像保存:cv2.imwrite('stitched_result.jpg', result)

二、完整代碼實現

三、關鍵參數調優與常見問題解決

3.1 核心參數調優建議

3.2 常見問題與解決方案


在計算機視覺領域,圖像拼接是一項重要且實用的技術,它能將多幅存在重疊區域的圖像融合成一幅寬視角的完整圖像,廣泛應用于全景攝影、遙感圖像處理等場景。本文將詳細介紹如何使用 Python 結合 OpenCV 庫,通過 SIFT 特征檢測與匹配、透視變換等核心步驟,實現兩張圖像的自動拼接,并在正文中明確標注各步驟對應的 OpenCV API 及參數含義。


一、核心技術原理與對應 API 解析

圖像拼接的核心流程可拆解為 “特征提取→特征匹配→透視變換→圖像融合” 四個步驟,每個步驟均依賴 OpenCV 的關鍵 API 實現,以下詳細說明原理與 API 的對應關系。

1.1 SIFT 特征檢測與描述(尺度不變特征提取)

SIFT(Scale-Invariant Feature Transform)是一種能在不同尺度、旋轉、光照條件下穩定提取圖像特征的算法,其核心是通過檢測圖像中的 “穩定特征點” 并生成 “特征描述符”,為后續匹配提供依據。在 OpenCV 中,SIFT 的實現依賴以下 API:

1.1.1 灰度圖轉換:cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

  • 功能:將彩色圖像(BGR 格式,OpenCV 默認讀取格式)轉換為灰度圖。SIFT 算法僅需在灰度圖上提取特征,可減少計算量并避免色彩干擾。
  • 參數說明
    • image:輸入的彩色圖像(NumPy 數組格式);
    • cv2.COLOR_BGR2GRAY:顏色空間轉換標志,指定從 BGR 彩色空間轉為灰度空間。

1.1.2 SIFT 檢測器初始化:cv2.SIFT_create()

  • 功能:創建 SIFT 特征檢測器實例,用于后續的特征點檢測與描述符計算。
  • 注意事項:OpenCV 4.x 版本中,SIFT 功能移至opencv-contrib-python庫,需安裝該庫(pip install opencv-contrib-python)才能使用,避免因專利問題導致的 API 調用失敗。

1.1.3 特征點檢測與描述符計算:sift.detectAndCompute(gray, None)

  • 功能:一次性完成 “特征點檢測” 和 “特征描述符計算”,是 SIFT 流程的核心 API。
  • 參數說明
    • gray:輸入的灰度圖像;
    • None:掩模(mask)參數,設為None表示對全圖進行特征檢測,若需指定感興趣區域(ROI),可傳入與圖像尺寸一致的二值掩模。
  • 返回值
    • kps:特征點對象列表,每個對象包含特征點的坐標(kp.pt)、尺度(kp.size)、方向(kp.angle)等信息;
    • des:128 維特征描述符矩陣,形狀為(特征點數量, 128),用于描述每個特征點的局部紋理信息,是特征匹配的核心依據。

1.1.4 特征點坐標格式轉換:np.float32([kp.pt for kp in kps])

  • 功能:將kps對象中的坐標(kp.pt,元組格式)轉換為 NumPy 浮點數數組,便于后續透視變換時的矩陣計算(OpenCV 數值計算需 NumPy 數組格式)。

1.2 特征匹配與篩選(BFMatcher+KNN 策略)

特征匹配的目的是找到兩張圖像中 “語義相同” 的特征點(如同一物體的邊緣、角點),但原始匹配結果中會存在錯誤匹配,需通過篩選策略保留優質匹配對。該步驟依賴的 API 如下:

1.2.1 暴力匹配器初始化:cv2.BFMatcher()

  • 功能:創建暴力匹配器(Brute-Force Matcher)實例,原理是 “對查詢圖像的每個特征描述符,遍歷訓練圖像的所有描述符,計算歐式距離并找到最相似的匹配”。
  • 適用場景:適用于特征點數量較少的場景(如本文兩張圖像拼接),若需處理大量特征點(如多圖全景拼接),可替換為cv2.FlannBasedMatcher(更快的近鄰匹配算法)。

1.2.2 KNN 匹配:matcher.knnMatch(desB, desA, k=2)

  • 功能:采用 K 近鄰(K-Nearest Neighbor)策略進行匹配,為每個查詢特征點返回前 K 個最相似的訓練特征點,本文設k=2(獲取每個特征點的 “最近匹配” 和 “次近匹配”)。
  • 參數說明
    • desB:查詢圖像(待拼接圖像,如本文的imageB)的特征描述符;
    • desA:訓練圖像(目標圖像,如本文的imageA)的特征描述符;
    • k=2:指定返回的近鄰數量,固定為 2 以執行后續的 “距離比值篩選”。
  • 返回值rawMatches,每個元素是包含k個匹配對象的列表,匹配對象包含distance(歐式距離,越小表示匹配越優)、queryIdx(查詢描述符的索引)、trainIdx(訓練描述符的索引)。

1.2.3 優質匹配對篩選:距離比值法

  • 篩選邏輯:對每個k=2的匹配結果,若 “最近匹配距離” 與 “次近匹配距離” 的比值小于閾值(本文設為 0.65),則保留該匹配對。該策略的核心是 “優質匹配的最近距離應遠小于次近距離”,可有效剔除錯誤匹配。
  • 無單獨 API:通過 Python 循環實現,核心代碼邏輯為:

    python

    運行

    if len(m) == 2 and m[0].distance < 0.65 * m[1].distance:good.append(m)  # 保留優質匹配對
    

1.2.4 匹配結果可視化:cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

  • 功能:繪制優質匹配對的可視化結果,直觀展示兩張圖像的特征對應關系。
  • 參數說明
    • imageB/imageA:查詢圖像與訓練圖像;
    • kpsB/kpsA:兩張圖像的特征點對象列表;
    • good:篩選后的優質匹配對列表;
    • None:輸出圖像,設為None表示由 API 自動創建;
    • flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:繪制標志,指定 “顯示特征點的大小、方向”,而非僅繪制匹配線,便于觀察特征點的細節。

1.3 透視變換(Homography):統一圖像視角

透視變換用于將待拼接圖像(imageB)從其原始視角 “映射” 到目標圖像(imageA)的視角,實現兩張圖像的坐標系統一,是拼接的核心步驟。該步驟依賴的 API 如下:

1.3.1 透視變換矩陣計算:cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 10)

  • 功能:計算兩個平面(imageBimageA的匹配點平面)之間的透視變換矩陣H(3×3 矩陣),并通過 RANSAC 算法剔除錯誤匹配點(外點),保證矩陣的魯棒性。
  • 參數說明
    • ptsB:查詢圖像(imageB)的匹配點坐標數組(浮點數格式,需通過matches索引從kps_floatB中提取);
    • ptsA:訓練圖像(imageA)的匹配點坐標數組(同理從kps_floatA中提取);
    • cv2.RANSAC:魯棒估計方法,通過隨機采樣和內點計數,剔除外點(錯誤匹配點)的干擾;
    • 10:重投影誤差閾值,僅在method=cv2.RANSAC時生效。若匹配點經過H變換后的 “重投影位置” 與實際位置的距離超過 10,則視為外點。
  • 返回值
    • H:3×3 的透視變換矩陣,后續通過該矩陣將imageB映射到imageA的坐標系;
    • mask:內點掩模數組(0 表示外點,1 表示內點),可用于后續分析匹配質量。

1.3.2 執行透視變換:cv2.warpPerspective(imageB, H, (imageB.shape[1] + imageA.shape[1], imageB.shape[0]))

  • 功能:根據透視變換矩陣H,將待拼接圖像imageB轉換為與imageA視角一致的圖像,為最終拼接做準備。
  • 參數說明
    • imageB:待變換的圖像;
    • H:之前計算的透視變換矩陣;
    • (imageB.shape[1] + imageA.shape[1], imageB.shape[0]):輸出圖像的尺寸。本文設寬度為 “兩張圖像寬度之和”(確保imageB變換后不被裁剪),高度與imageB一致(若兩張圖像高度差異大,需先通過cv2.resize()統一高度)。

1.4 圖像融合與保存

1.4.1 圖像拼接融合

  • 核心邏輯:將目標圖像imageA直接覆蓋到 “imageB透視變換后的圖像(result)” 的左上角區域,實現重疊區域的初步融合。核心代碼為:

    python

    運行

    result[0:imageA.shape[0], 0:imageA.shape[1]] = imageA
    
  • 原理resultimageB變換后的圖像,其左上角區域與imageA的重疊部分會被imageA覆蓋,非重疊部分保留imageB的內容,從而形成完整的拼接圖像。若需優化重疊區域過渡效果,可后續通過cv2.addWeighted()實現加權融合(避免拼接痕跡)。

1.4.2 圖像保存:cv2.imwrite('stitched_result.jpg', result)

  • 功能:將拼接后的圖像保存到本地文件,支持 jpg、png 等常見格式。
  • 參數說明
    • 'stitched_result.jpg':保存的文件名(可指定路徑,如'./output/result.jpg');
    • result:待保存的拼接圖像數組。

二、完整代碼實現

以下是整合上述原理的完整代碼,代碼中保留關鍵注釋,便于結合前文 API 解析理解:

1.jpg
2.jpg
import cv2
import numpy as np
import sysdef cv_show(name, img):"""自定義圖像顯示函數:簡化OpenCV圖像顯示流程"""cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()  # 關閉窗口,避免內存殘留def detectAndDescribe(image):"""封裝SIFT特征提取:返回特征點對象、坐標數組、描述符"""# 1. 彩色圖轉灰度圖(SIFT需灰度圖輸入)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 2. 初始化SIFT檢測器sift = cv2.SIFT_create()# 3. 檢測特征點并計算描述符(kps, des) = sift.detectAndCompute(gray, None)# 4. 特征點坐標轉為NumPy浮點數數組kps_float = np.float32([kp.pt for kp in kps])return (kps, kps_float, des)if __name__ == "__main__":# 1. 讀取待拼接圖像(需確保路徑正確)imageA = cv2.imread("1.jpg")  # 目標圖像(拼接后左半部分)imageB = cv2.imread("2.jpg")  # 待拼接圖像(拼接后右半部分)# 檢查圖像是否成功讀取if imageA is None or imageB is None:print("Error:無法讀取圖像,請檢查路徑!")sys.exit()# 顯示原始圖像cv_show('Original Image A', imageA)cv_show('Original Image B', imageB)# 2. 提取兩張圖像的SIFT特征(kpsA, kps_floatA, desA) = detectAndDescribe(imageA)(kpsB, kps_floatB, desB) = detectAndDescribe(imageB)# 3. 特征匹配與篩選matcher = cv2.BFMatcher()  # 初始化暴力匹配器rawMatches = matcher.knnMatch(desB, desA, k=2)  # KNN匹配(k=2)# 篩選優質匹配對(距離比值法)good = []matches = []for m in rawMatches:if len(m) == 2 and m[0].distance < 0.65 * m[1].distance:good.append(m)matches.append((m[0].queryIdx, m[0].trainIdx))  # 記錄匹配點索引# 輸出匹配結果并可視化print(f"優質匹配對數量:{len(good)}")vis_matches = cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)cv_show('Keypoint Matches', vis_matches)# 4. 計算透視變換矩陣(需至少4對匹配點)if len(matches) > 4:# 提取匹配點坐標ptsA = np.float32([kps_floatA[i] for (_, i) in matches])ptsB = np.float32([kps_floatB[i] for (i, _) in matches])# 計算H矩陣(RANSAC剔除外點)(H, mask) = cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 10)print(f"透視變換矩陣H:\n{H}")else:print("Error:匹配點不足4個,無法拼接!")sys.exit()# 5. 執行透視變換(將imageB映射到imageA視角)result_size = (imageB.shape[1] + imageA.shape[1], imageB.shape[0])result = cv2.warpPerspective(imageB, H, result_size)cv_show('Transformed Image B', result)# 6. 拼接圖像(將imageA覆蓋到result左上角)result[0:imageA.shape[0], 0:imageA.shape[1]] = imageA# 7. 顯示并保存最終結果cv_show('Final Stitched Image', result)cv2.imwrite('stitched_result.jpg', result)print("拼接完成!結果已保存為 stitched_result.jpg")
stitched_result.jpg

三、關鍵參數調優與常見問題解決

3.1 核心參數調優建議

參數類型默認值調優場景與方法
匹配閾值(距離比值)0.65匹配對過少→降低至 0.7;錯誤匹配多→提高至 0.6
RANSAC 重投影誤差閾值10拼接錯位→減小至 5~8;匹配點過少→增大至 12~15
輸出圖像尺寸寬求和圖像高度差異大→先通過cv2.resize(image, (new_w, new_h))統一兩張圖像高度

3.2 常見問題與解決方案

  • 問題 1:SIFT API 調用失敗
    原因:未安裝opencv-contrib-python,或 OpenCV 版本過低。
    解決:執行pip uninstall opencv-python后,重新安裝pip install opencv-contrib-python

  • 問題 2:圖像無法讀取
    原因:路徑錯誤(如中文路徑、相對路徑與代碼文件不同目錄),或圖像損壞。
    解決:使用絕對路徑(如"C:/images/1.jpg"),或檢查圖像格式(確保為 jpg/png)。

  • 問題 3:拼接結果錯位嚴重
    原因:透視變換矩陣不準確,可能是外點過多或重投影誤差閾值設置不當。
    解決:降低匹配閾值以增加優質匹配對,或調整 RANSAC 重投影誤差閾值(如從 10 改為 8)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/923473.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/923473.shtml
英文地址,請注明出處:http://en.pswp.cn/news/923473.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

日語學習-日語知識點小記-進階-JLPT-N1階段藍寶書,共120語法(10):91-100語法+考え方13

日語學習-日語知識點小記-進階-JLPT-N1階段藍寶書&#xff0c;共120語法&#xff08;10&#xff09;&#xff1a;91-100語法1、前言&#xff08;1&#xff09;情況說明&#xff08;2&#xff09;工程師的信仰&#xff08;3&#xff09;高級語法N1語法和難點2、知識點-語法&…

繼承與組合:C++面向對象的核心

C 繼承&#xff1a;從基礎到實戰&#xff0c;徹底搞懂面向對象的 “代碼復用術” 在面向對象編程&#xff08;OOP&#xff09;的世界里&#xff0c;“繼承” 是實現代碼復用的核心機制 —— 就像現實中孩子會繼承父母的特征&#xff0c;C 的子類也能 “繼承” 父類的成員&#…

Matplotlib定制:精解顏色、字體、線型與標記

Matplotlib定制&#xff1a;精解顏色、字體、線型與標記導語 Matplotlib 是 Python 數據可視化領域的基石。雖然它的默認樣式足以滿足快速分析的需求&#xff0c;但要創作出具有專業水準、信息清晰、視覺美觀的圖表&#xff0c;就必須掌握其強大的定制功能。本文將深入探討 Mat…

Qt開發經驗 --- Qt監聽文件/文件夾改變(17)

文章目錄[toc]1 概述2 演示效果3 簡單使用示例4 帶界面的使用示例5 源代碼地址更多精彩內容&#x1f449;內容導航 &#x1f448;&#x1f449;Qt開發經驗 &#x1f448;1 概述 QT實現實時監控文件的創建、修改、刪除操作 跟蹤文件夾內容的增刪改變化 可用于文件發生變化時自…

數據分析:合并一

&#x1f537; DA37&#xff1a;統計運動會項目報名人數&#xff08;僅輸出有人報名的項目&#xff09;? 題目描述給定兩個 CSV 文件&#xff1a;items.csv&#xff1a;包含項目信息&#xff08;item_id, item_name, location&#xff09;signup.csv&#xff1a;包含員工報名信…

WWW‘25一通讀 |圖Anomaly/OOD檢測相關文章(1)

寫在前面&#xff1a;進入新一輪學習階段&#xff0c;從閱讀開始。 本文分享的是WWW2025收錄的與作者研究相近的graph-based xx相關paper的閱讀筆記&#xff0c;含個人理解&#xff0c;僅供參考&#x1f604; 0x01 HEI&#xff1a;利用不變性原理實現異配圖結構分布偏移學習 J…

static_cast:C++類型系統的“正經翻譯官”

1. 背景與核心概念 1.1 C的“類型安全”哲學 想象一下&#xff0c;你所在的世界突然失去了所有規則&#xff1a;文字可以隨意變成數字&#xff0c;人可以瞬間變成椅子&#xff0c;汽車能飛上天變成飛機… 這聽起來像是瘋狂的夢境&#xff0c;但對于早期C語言來說&#xff0c;這…

【嵌入式原理系列-第八篇】USART從原理到配置全解析

目錄 一.通信領域基礎知識介紹 1.1 串行和并行通信 1.2 同步和異步傳輸 1.3 串口和COM口 1.4 通信協議標準以及物理層定義 1.5 物理層協議之TTL / RS-232 / RS-485 二.USART介紹 2.1 USART特點介紹 2.2 UART和TTL / RS-232 / RS-485 2.3 USART硬線流控介紹 2.4 USAR…

MariaDB介紹和MariaDB包安裝

文章目錄MariaDB介紹和安裝1.MariaDB介紹1.1 起源與背景1.2 核心特性1.2.1 高度兼容 MySQL1.2.2 優化的存儲引擎1.2.3 企業級功能增強1.2.4 性能優化1.2.5 安全增強1.3 社區與生態1.4 應用場景1.5 總結2.MariaDB安裝2.1 主機初始化2.1.1 設置網卡名2.1.2 設置ip地址2.1.3 配置鏡…

雙指針與滑動窗口算法精講:從原理到高頻面試題實戰

引言&#xff1a;算法選擇的十字路口 在算法面試中&#xff0c;雙指針和滑動窗口如同兩把瑞士軍刀&#xff0c;能高效解決80%以上的數組和字符串問題。本文將深入解析這兩種技術的核心差異&#xff0c;結合力扣高頻題目&#xff0c;提供可直接復用的代碼。 一、算法核心思想解析…

蘋果MAC、MacBook air和pro安裝windows雙系統與iOS分發

文章目錄1. main1.1 準備工作1.2 啟動轉換助理1.3 Windows安裝1.4 蘋果電腦安裝Windows雙系統切換2. 蘋果(iOS)分發/上架2.1 上架App Store2.2 上架TestFlight2.3 webClip免簽上架2.4 超級簽名2.5 企業證書2.6 app分發系統Reference1. main 蘋果電腦安裝windows雙系統 https:…

ArcGIS定向影像(1)——非傳統影像輕量級解決方案

常常聽到這樣的需求&#xff0c;ArcGIS能讓用戶自己低成本的做出谷歌街景嗎&#xff1f;現在 _ArcGIS Pro 3.2 和 ArcGIS Enterprise 11.2 _能夠讓用戶不使用任何插件和擴展的情況下完成街景數據集的構建&#xff0c;數據管理&#xff0c;發布服務和調用的完整解決方案。非常體…

uni-app 網絡之封裝實戰HTTP請求框架

前言在uniapp開發中&#xff0c;網絡請求是每個應用都必不可少的功能模塊。一個優秀的網絡請求封裝不僅能提高開發效率&#xff0c;還能增強代碼的可維護性和可擴展性。本文將基于實際項目經驗&#xff0c;詳細介紹如何封裝一個高效、可維護的Uniapp網絡請求框架&#xff0c;并…

架構師成長之路-架構方法論

文章目錄前言一、先搞懂&#xff1a;架構師不僅僅是“技術大佬”&#xff0c;更是“問題解決者”1.1 架構師的分類&#xff1a;不止“開發架構師”一種1.2 架構師要關注什么&#xff1f;別只盯著技術1.3 架構師解決問題的4步心法&#xff1a;從定義到落地1.4 架構師的成長攻略&…

uniapp在微信小程序中實現 SSE 流式響應

前言 最近需要使用uniapp開發一個智能對話頁面&#xff0c;其中就需要使用SSE進行通信。 本文介紹下在uniapp中如何基于uni.request實現SSE流式處理。 在線體驗 #小程序:yinuosnowball SSE傳輸格式 返回輸出的流式塊: Content-Type為text/event-stream 每個流式塊均為 d…

STM32N6AI資料匯總

文章目錄前言一、STM32N6硬件資源1.1 NUCLEO-N657X0-Q1.2 STM32N6570-DK1.3 正點原子STM32N647二、STM32N6軟件資源2.1 STM32CubeN6例程資源包2.2 STM32圖像信號處理器&#xff08;ISP&#xff09;調優軟件2.3 正點原子N6開發板配套軟件三、AI軟件資源3.1 STM32N6 AI軟件包總結…

Flask學習筆記(一)

1、環境準備pip install Flask使用Flask開發第1個入門程序&#xff1a;from flask import Flask app Flask(__name__) app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run()Flask構造函數將當前模塊的名稱(__name__)作為參數。2、route函數ap…

CSP認證練習題目推薦(4)

思維、貪心、綜合 排隊打水 這道題目不算難&#xff0c;但是不注意還是會出現很多錯誤&#xff0c;比如結構體的書寫。以及自定義結構體排序。還有這里做的優化&#xff0c;使用前綴和記錄打水的等待時間&#xff0c;但是這里很容易出錯的點在于等待時間是應該是記錄的前一個…

MySQL 視圖的更新與刪除:從操作規范到風險防控

MySQL 視圖的更新與刪除&#xff1a;從操作規范到風險防控 視圖作為 “虛擬表”&#xff0c;其更新與刪除操作常常讓開發者困惑 ——“為什么更新視圖會報錯&#xff1f;”“刪除視圖會不會弄丟數據&#xff1f;” 實際上&#xff0c;80% 的視圖操作問題都源于對 “視圖依賴基表…

C 語言實現 I.MX6ULL 點燈(續上一篇)、SDK、deep及bsp工程管理

目錄 一、匯編點燈轉 C 語言實現 1. 關鍵字&#xff1a;volatile 2. 寄存器地址定義&#xff08;兩種方式&#xff09; &#xff08;1&#xff09;直接宏定義地址 &#xff08;2&#xff09;結構體封裝寄存器&#xff08;優化訪問&#xff09; 3. 核心功能代碼 &#xff…