播放器系列3——解碼

FFmpeg解碼過程詳解

解碼流程

avformat_open_input
avformat_find_stream_info
avcodec_find_decoder
avcodec_alloc_context3
avcodec_parameters_to_context
avcodec_open2
av_read_frame
avcodec_send_packet
avcodec_receive_frame
處理解碼幀

API文檔

avcodec_find_decoder

AVCodec *avcodec_find_decoder(enum AVCodecID id);
  • 功能: 根據編解碼器ID查找解碼器
  • 參數:
    • id: 編解碼器ID
  • 返回值: 成功返回AVCodec指針,失敗返回NULL
  • 示例:
AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {fprintf(stderr, "未找到H264解碼器\n");return -1;
}

avcodec_alloc_context3

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
  • 功能: 分配并初始化AVCodecContext
  • 參數:
    • codec: 關聯的編解碼器,可以為NULL
  • 返回值: 成功返回AVCodecContext指針,失敗返回NULL
  • 示例:
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {fprintf(stderr, "無法分配編解碼器上下文\n");return -1;
}

avcodec_parameters_to_context

int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
  • 功能: 將AVCodecParameters中的參數填充到AVCodecContext
  • 參數:
    • codec: 目標AVCodecContext
    • par: 源AVCodecParameters
  • 返回值: 成功返回0,失敗返回負值錯誤碼
  • 示例:
if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {fprintf(stderr, "無法填充編解碼器參數\n");return -1;
}

avcodec_open2

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
  • 功能: 使用指定解碼器初始化AVCodecContext
  • 參數:
    • avctx: 要初始化的AVCodecContext
    • codec: 要使用的解碼器
    • options: 額外的選項字典
  • 返回值: 成功返回0,失敗返回負值錯誤碼
  • 示例:
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {fprintf(stderr, "無法打開解碼器\n");return -1;
}

avcodec_send_packet

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
  • 功能: 將數據包發送給解碼器
  • 參數:
    • avctx: AVCodecContext指針
    • avpkt: 要解碼的數據包
  • 返回值: 成功返回0,失敗返回負值錯誤碼
  • 示例:
if (avcodec_send_packet(codec_ctx, &pkt) < 0) {fprintf(stderr, "發送數據包失敗\n");continue;
}

avcodec_receive_frame

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
  • 功能: 從解碼器獲取解碼后的幀
  • 參數:
    • avctx: AVCodecContext指針
    • frame: 用于存儲解碼后的幀
  • 返回值: 成功返回0,失敗返回負值錯誤碼
  • 示例:
AVFrame *frame = av_frame_alloc();
while (avcodec_receive_frame(codec_ctx, frame) >= 0) {// 處理解碼幀
}

Audio編碼格式介紹

1. 音頻編碼格式概述

音頻編碼格式是將音頻數據轉換為可存儲或傳輸的格式的過程。在音頻領域,常見的編碼格式包括PCM(脈沖編碼調制)、MP3、AAC等。每種格式都有其特定的特點和應用場景。

2.常見音頻編碼格式

2.1 PCM(脈沖編碼調制)

PCM(Pulse Code Modulation,脈沖編碼調制)是一種將模擬信號轉換為數字信號的標準方法。其核心過程包括采樣、量化和編碼,最終生成未經壓縮的音頻數據。PCM數據由如下六個參數來描述:

  • 采樣率:每秒鐘采集的樣本數,例如44.1kHz表示每秒采集44100個樣本。
    位深度:每個樣本的量化位數,常見的有8位、16位、24位等。位深度越高,表示的動態范圍越大,音質越好。
  • 聲道數:單聲道或雙聲道等。雙聲道音頻通常采用LRLR或RLRL的方式存儲。
  • 符號性:有符號或無符號。有符號數據可以表示負值,適用于更廣泛的音頻范圍。
  • 字節序:大端模式或小端模式。字節序決定了數據在存儲或傳輸時的排列順序。
  • 數據類型:整型或浮點型。整型數據通常用于存儲離散的量化值,而浮點型數據可能用于某些特殊應用。

PCM數據的存儲方式:

  • 單聲道PCM:采樣數據按時間順序存儲,例如16位單聲道音頻,每個樣本占用2個字節。
  • 雙聲道PCM:采樣數據交錯存儲(Packed)或分開存儲(Planar)。交錯存儲將左右聲道的數據混合在一起,而分開存儲則將左右聲道的數據分別存儲。

2.1.2 PCM數據的操作

在dump pcm數據的時候要關注當前數據是Packed還是Planar。通常pcm文件格式為Packed,那么也就是說如果按照Planar的方式來dump數據,那么dump出來的文件是不可以播放的。下面分別提供兩種格式dump代碼。

void FileDump::WritePcmPlanarData(uint8_t *data[], int size_per_sample) {/**P表示Planar(平面),其數據格式排列方式為 :LLLLLLRRRRRRLLLLLLRRRRRRLLLLLLRRRRRRL...(每個LLLLLLRRRRRR為一個音頻幀)注意planar格式通常是ffmpeg內部使用格式而不帶P的數據格式(即交錯排列)排列方式為:LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLRL...(每個LR為一個音頻樣本)播放范例:   `*/
// 解析出來的是32bit float planar 小端數據for (int i = 0; i < audio_info_.samples; i++) {for (int ch = 0; ch < audio_info_.channels;ch++) // 交錯的方式寫入, 大部分float的格式輸出fwrite(data[ch] + size_per_sample * i, 1, size_per_sample, file_);fflush(file_);}
}
void FileDump::WritePcmData(uint8_t *data[], int pcm_size) {fwrite(data[0], 1, pcm_size, file_);fflush(file_);
}

注意使用avcodec_receive_frame 獲取到的數據是planar的,因此解碼后的數據在dump的時候應該注意。
在使用sox 添加音效時也要注意,輸入給API的數據需要是int32_t類型的planar數據。

2.1.2 PCM文件大小與播放時長的關系

假如一個PCM文件大小為100MB,采樣率為44.1kHz,采樣深度為16位,雙聲道。那么這個PCM文件的時長為:

時長 = 文件大小 / (采樣率 * 采樣深度 * 聲道數 / 8)
時長 = 100MB / (44.1kHz * 16位 * 2聲道 / 8)
2.1.3 PCM sample與播放時長的關系

如果當前解析出來的一段PCM數據sample個數是1024,并且采樣率為44.1kHz,采樣深度為16位,雙聲道。那么這個PCM文件的時長為:

時長 = sample個數 / 采樣率 
時長 = 1024 / 44.1kHz  約等于23ms左右

2.2 AAC

AAC(高級音頻編碼,Advanced Audio Coding)是一種高壓縮比的音頻編碼技術,最初基于MPEG-2標準開發,并在2000年隨著MPEG-4標準的推出進一步發展為MPEG-4 AAC。AAC的設計目標是取代MP3格式,提供更高的音質和更低的比特率。
AAC編碼封裝格式分為兩種:ADTS(Audio Data Transport Stream)和ADIF(Audio Data Interchange Format)。ADTS是一種流式封裝格式,適用于實時傳輸和存儲;ADIF是一種文件封裝格式,適用于存儲。

2.2.1 ADTS格式

在這里插入圖片描述

上圖可以看出以ADTS格式的AAC文件包含了多個adts_frame。
在這里插入圖片描述

解析 ADTS 幀頭:

  • adts_fixed_header():解析 ADTS 幀的固定頭部,包含同步字、幀長度、采樣率等信息。
  • adts_variable_header():解析 ADTS 幀的可變頭部,包含聲道配置、幀類型等信息。
    處理音頻數據塊:
  • adts_error_check():檢查幀頭部的錯誤。
  • raw_data_block():提取并處理音頻數據塊。
    如果 number_of_raw_data_blocks_in_frame == 0,表示幀中只有一個音頻數據塊。
    注意一個adts_frame中包含了1到16個raw_data_block,一個raw_data_block包含了1024個采樣點。

2.2.2 ADIF格式

在這里插入圖片描述

從圖可以看出ADIF格式類型的AAC文件只有一個adif_header。

  • aif_header()
    作用: 定義位于 adif_sequence 開頭的 ADIF 頭。
    描述: 包含音頻數據交換格式的基本信息,如版權標識、比特率類型、比特率等。具體字段包括 adif_id, copyright_id_present, copyright_id, original_copy, home, bitstream_type, bitrate, num_program_config_elements, 和 adif_buffer_fullness。
  • byte_alignment()
    作用: 對齊到頭部的第一個比特。
    描述: 確保數據流在內存中的對齊,以便后續的數據處理更加高效。
  • raw_data_stream()
    作用: 包含實際的音頻數據流。
    描述: 這是音頻數據的核心部分,包含了經過編碼的音頻數據。
    好了,aac我們就介紹這些,畢竟較為復雜,在日常的開發中,解析aac head一般使用開源庫,如果需要自己解析,也是邊看spec邊code.具體的aac格式請參照ISO/IEC
    13818-7 Part 7: Advanced Audio Coding (AAC)

Video 編碼格式介紹

視頻編碼格式是將視頻數據壓縮成更小的數據塊,以便于存儲和傳輸。常見的視頻編碼格式包括H.264、H.265、VP8、VP9等。這些格式在壓縮效率和視頻質量之間取得了平衡。

1.H.264 (AVC)

H.264是一種廣泛使用的視頻編碼格式,由ITU-T和ISO/IEC聯合開發。H.264采用了基于幀的編碼方式,將視頻數據分割成多個幀,并對每個幀進行壓縮。H.264的壓縮算法包括幀內編碼和幀間編碼。

1.H264數據組織形式

在這里插入圖片描述

1.幀的分類

1.1 I幀
  • I幀(Intra Frame)
    定義:I幀采用幀內壓縮技術,不依賴于其他幀進行解碼。I幀通過預測當前幀內的像素差異來減少數據量,通常用于場景切換或圖像變化較大的時刻。
    特點:
    解碼時不需要參考其他幀。
    壓縮率較低(約7%),但提供高質量的畫面。
    在GOP(Group of Picture)中作為起始幀,用于重同步解碼過程。
    應用場景:I幀通常用于關鍵幀的插入,例如在檢測到丟包或需要重新同步時立即插入一個I幀。
1.2 P幀
  • P幀(Predictive Frame)
    定義:P幀是前向參考幀,采用幀間壓縮技術,僅參考前一幀(P幀或I幀)進行解碼。
    特點:
    解碼時需要參考前一幀。
    壓縮率較高(約20%),適合變化較小的場景。
    可以進一步分為P1幀和P2幀,分別依賴前一幀和前兩幀。
    應用場景:P幀常用于連續變化的場景,例如緩慢移動的物體或背景。
1.3 B幀
  • B幀(Bi-Directional Frame)
    定義:B幀是雙向參考幀,采用幀間壓縮技術,同時參考前后兩幀(P幀或I幀)進行解碼。
    特點:
    解碼時需要參考前后兩幀。
    壓縮率最高(約50%),適合快速變化的場景。
    提高了壓縮效率,但增加了解碼復雜度。
    應用場景:B幀更適合運動較平緩的場景、靜態北背景變化
幀大小對比

在這里插入圖片描述

從圖中可以看出I>P>B,而且大小相差很多。

參考鏈接

由于本人對視頻編碼格式不是很了解,因此這里給出一個參考鏈接,供大家學習。
https://www.nxrte.com/jishu/16413.html
注意

特性I 幀IDR 幀
定義獨立編碼的幀,不依賴其他幀特殊的 I 幀,用于重置參考幀列表
參考關系可能被后續 P/B 幀參考之后的所有幀都不能參考之前的幀考
作用提供隨機訪問點提供更強的隨機訪問能力

2.YUV編碼介紹

YUV編碼是一種廣泛應用于數字視頻和圖像處理中的顏色編碼方式,其核心思想是將圖像的顏色信息分解為亮度(Y)和色度(U和V)兩個部分。這種編碼方式基于人類視覺對亮度和色度敏感度的不同,通過減少色度信息的采樣率來降低數據傳輸和存儲的帶寬需求,從而實現高效的視頻壓縮和傳輸。

2.YUV原理

2.1亮度與色度分離:

Y(亮度)表示圖像的明暗程度,是灰度值。

  • U和V(色度)分別表示藍色差分信號和紅色差分信號,用于描述顏色的飽和度和色調。
  • 在YUV編碼中,亮度信息占據主要帶寬,而色度信息則通過采樣率降低來減少存儲空間。
2.2 人眼特性:
  • 人類視覺對亮度變化比對顏色變化更敏感,因此在YUV編碼中,亮度信息被賦予更高的帶寬,而色度信息則通過采樣率降低來減少數據量。
  • 這種設計使得YUV編碼在保持圖像質量的同時,能夠有效減少數據傳輸和存儲的帶寬需求。
    數學表達:
2.3 YUV可以通過以下公式從RGB轉換而來:
2.3.1 YUV 分量定義
  • Y:亮度(Luma)
  • U:藍色色差(Cb)
  • V:紅色色差(Cr)
2.3.2. 轉換公式
  • Y = 0.299 * R + 0.587 * G + 0.114 * B
  • U = -0.14713 * R - 0.28886 * G + 0.436 * B
  • V = 0.615 * R - 0.51499 * G - 0.10001 * B
2.3.3. 公式說明
  • R, G, B 的取值范圍為 [0, 255]
  • Y 的取值范圍為 [0, 255]
  • U 和 V 的取值范圍為 [-128, 127]
2.3.4. 示例

假設 R = 100, G = 150, B = 200:

  • Y = 0.299 * 100 + 0.587 * 150 + 0.114 * 200 ≈ 146.45
  • U = -0.14713 * 100 - 0.28886 * 150 + 0.436 * 200 ≈ 33.565
  • V = 0.615 * 100 - 0.51499 * 150 - 0.10001 * 200 ≈ -10.7485
    其中,R、G、B分別表示紅色、綠色和藍色分量。

2.4 YUV編碼的采樣格式

根據YUV的原理主要是改變UV的個數因此有如下格式
在這里插入圖片描述

舉個例子YUV4:4:4 代表什么意思:

  • 第一個"4"代表4列像素信息
  • 第二個"4"代表第一行像素信息
  • 第三個"4"代表第二行像素信息
    先記住下面這段話,以后提取每個像素的YUV分量會用到。
  • YUV 4:4:4采樣,每一個Y對應一組UV分量。
  • YUV 4:2:2采樣,每兩個Y共用一組UV分量。
  • YUV 4:2:0采樣,每四個Y共用一組UV分量。
    注意YUV存在Packed與Planar的概念,下面給出YUV420P如何dump code.
void FileDump::WriteVideoYUV420PData(AVFrame* videoFrame) {for (int j = 0; j < videoFrame->height; j++)fwrite(videoFrame->data[0] + j * videoFrame->linesize[0], 1, videoFrame->width, file_);for (int j = 0; j < videoFrame->height / 2; j++)fwrite(videoFrame->data[1] + j * videoFrame->linesize[1], 1, videoFrame->width / 2, file_);for (int j = 0; j < videoFrame->height / 2; j++)fwrite(videoFrame->data[2] + j * videoFrame->linesize[2], 1, videoFrame->width / 2, file_);
}

大多數播放器支持PCM packeted 與YUVPlanar ,因此我們在開發的時候也要注意,設置給驅動的format和輸入給驅動的data 要符合驅動的要求。

2.4 YUV編碼的采樣格式

yuv420p原圖
在這里插入圖片描述

Y圖
在這里插入圖片描述

U圖
在這里插入圖片描述

V圖
在這里插入圖片描述

從上面三幅圖片可以看出來,人眼灰度圖片(Y圖)敏感度最高,感官上可以感覺出來Y圖反饋的信息最多

總結

可以看出不論是Audio還是Video,編碼的最終目的都是在盡可能保證原始數據質量的同時,減少冗余信息,提高傳輸效率。

源碼地址

https://github.com/OrangeKitten/VideoPlayer

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

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

相關文章

SimPO算法-Simple Preference Optimizationwith a Reference-Free Reward

偏好優化&#xff08;preference optimization &#xff09;算法大全&#xff1a; 本篇介紹下SimPO SimPO&#xff08;Simple Preference Optimization&#xff09;的設計核心在于簡化偏好優化過程&#xff0c;同時提升模型的表現。其設計主要圍繞兩個關鍵點展開&#xff1a;長…

AIGC時代:如何快速搞定Spring Boot+Vue全棧開發

文章目錄 一、Spring Boot基礎二、Vue.js基礎三、Spring Boot與Vue.js集成四、性能優化與最佳實踐《快速搞定Spring BootVue全棧開發》 內容簡介作者簡介目錄前言/序言本書內容本書特點讀者對象 隨著人工智能生成內容&#xff08;AIGC&#xff09;技術的迅速發展&#xff0c;…

探秘基帶算法:從原理到5G時代的通信變革【六】CRC 校驗

文章目錄 2.5 CRC 校驗2.5.1 前言2.5.2 CRC算法簡介2.5.3 CRC計算的詳細過程2.5.4 CRC校驗的兩種方法詳解**分離比較法****整體運算法****不同位出錯與余數的關系****總結** 2.5.5 CRC計算的C實現及工具介紹**C實現CRC計算****CRC計算工具推薦** **2.5.6 總結&#xff1a;CRC校…

AUTOSAR微控制器抽象層(MCAL)詳解及綜合實例

目錄 1. 微控制器抽象層(MCAL)概述 1.1 MCAL的核心功能 1.2 MCAL的模塊劃分 1.3 MCAL的工作流程 2. MCAL的詳細功能解析 2.1 微控制器驅動 2.1.1 時鐘配置 2.1.2 電源管理 2.1.3 實例:時鐘配置 2.2 通信驅動 2.2.1 CAN驅動 2.2.2 實例:CAN通信的實現 2.3 I/O驅…

探究高空視頻全景AR技術的實現原理

1. 引言 筆者認為現階段AR技術的應用是還是比較坑爹的&#xff0c;大都是噱頭多但是實用的成分少&#xff0c;拿出來做做DEMO是可以&#xff0c;但是難以在實際的項目中落地產生實際的經濟價值。一方面是很難在業務上難以找到合適的應用場景&#xff08;可能管線相關的項目算一…

深度解析 | 2025 AI新突破,物理信息神經網絡(PINN):Nature級頂刊的「科研加速器」,70份源碼論文速取!

&#x1f525; 為什么全球頂尖實驗室都在押注PINN&#xff1f; 過去一年&#xff0c;物理信息神經網絡&#xff08;PINN&#xff0c;Physics-Informed Neural Networks&#xff09;以「現象級」姿態席卷科研圈&#xff1a;不僅在NeurIPS、ICML等頂會橫掃15%相關論文&#xff0c…

0基礎學前端---品優購項目Day14

0基礎學前端—品優購項目Day14 視頻參考&#xff1a;B站Pink老師 本節重點&#xff1a;all 項目鏈接&#xff1a;完整的項目已放到 品優購完整項目 大家可以自行下載 強調內容 這里主要強調兩個知識點&#xff1a; (1) 網站TDK三個標簽SEO優化 (2) logo SEO優化 網站TDK三個…

LeetCode熱題100JS(37/100)第七天|排序鏈表|合并K個升序鏈表|LRU緩存|二叉樹的中序遍歷|二叉樹的最大深度|對稱二叉樹

148. 排序鏈表 題目鏈接&#xff1a;???????148. 排序鏈表 難度&#xff1a;中等 刷題狀態&#xff1a;1刷 新知識&#xff1a; - dic.reduceRight((t,c)>(c.nextt,c),null) 方法從數組的末尾開始執行 解題過程 思考 示例 1&#xff1a; 輸入&#xff1a;head […

課程2. 機器學習方法論

課程2. 機器學習方法論 訓練算法并評估其質量將樣本分成訓練和測試。分層 交叉驗證方法sklearn 接口算法模型訓練模型的應用質量評估 數據預處理標準縮放Violinplot 數據集使用模型Pipeline 在上一講中&#xff0c;我們討論了機器學習專家面臨的挑戰。無論解決的問題類型和解決…

六足仿生機器人地形自適應步態規劃研究

六足仿生機器人地形自適應步態規劃研究 第1章 緒論第2章 機器人系統建模第3章 地形感知與建模第4章 自適應步態生成算法第5章 動力學仿真與實驗第6章 驅動代碼設計與實現源碼&文檔鏈接 第1章 緒論 1.1 研究背景與意義 1.2 國內外研究現狀 1.2.1 多足機器人步態規劃 1.2.2 …

mysql表分區

本文簡述了mysql表分區的作用和特點&#xff0c;又演示了mysql表分區的創建過程&#xff0c;詳細演示了指定不同分區目錄時的處理辦法。由于表分區對crud操作是透明的&#xff0c;對于普通開發同學其實不用過多關注&#xff0c;但是本著學習的態度&#xff0c;在分庫分表等高大…

Nessus安裝

Nessus&#xff1a;https://pan.quark.cn/s/f5fb09b6d4fb 1.軟件安裝 點擊安裝&#xff0c;剩下的下一步即可。 直接下一步安裝即可 2.Web端安裝 會彈出一個web窗口 開始初始化 創建用戶 開始初始化 3.Cracker 會彈一個黑窗口 運行完&#xff0c;回車即可。訪問https://loc…

26-小迪安全-模塊引用,mvc框架,渲染,數據聯動0-rce安全

先創建一個新聞需要的庫 這樣id值可以逐級遞增 然后隨便寫個值&#xff0c;讓他輸出一下看看 模板引入 但是這樣不夠美觀&#xff0c;這就涉及到了引入html模板 模板引入是html有一個的地方值可以通過php代碼去傳入過去&#xff0c;其他的html界面直接調用&#xff0c;這樣頁…

第十三屆藍橋杯大賽軟件賽決賽C/C++ 大學 B 組

A 【2022——暴力DP / 優雅背包】-CSDN博客 B 【鐘表——類日期問題】-CSDN博客 C 【卡牌——二分】-CSDN博客 D 【最大數字——DFS】-CSDN博客 E 【出差——Dijkstra】-CSDN博客 F 【費用報銷——01背包】-CSDN博客 G 【故障——條件概率】-CSDN博客 H 【機房—…

樹莓集團最新現狀更新:南京園區業務的創新與突破

樹莓集團在南京的園區業務呈現出蓬勃發展的態勢&#xff0c;不斷實現創新與突破。 在產業布局方面&#xff0c;南京園區進一步優化了產業結構。除了繼續鞏固數字影像、數字娛樂等傳統優勢領域外&#xff0c;還積極拓展了數字金融、數字教育等新興領域。吸引了一批知名的數字金融…

Linux網絡編程(20250301)

網絡通信&#xff1a;進行不同主機的進程間通信 解決硬件與軟件的互聯互通 主機-->交換機-->路由器-->廣域網-->路由器-->交換機-->主機 IP地址&#xff1a;區分不同主機 MAC地址&#xff1a;計算機硬件地址 端口號&#xff1a;區分主機上的不同進程 1…

【JavaScript】《JavaScript高級程序設計 (第4版) 》筆記-附錄B-嚴格模式

附錄B、嚴格模式 嚴格模式 ECMAScript 5 首次引入嚴格模式的概念。嚴格模式用于選擇以更嚴格的條件檢查 JavaScript 代碼錯誤&#xff0c;可以應用到全局&#xff0c;也可以應用到函數內部。嚴格模式的好處是可以提早發現錯誤&#xff0c;因此可以捕獲某些 ECMAScript 問題導致…

藍橋試題:混境之地(記憶化搜索)

一、問題描述 小藍有一天誤入了一個混境之地。 好消息是&#xff1a;他誤打誤撞拿到了一張地圖&#xff0c;并從中獲取到以下信息&#xff1a; 混境之地是一個n?m 大小的矩陣&#xff0c;其中第 i 行第 j 列的的點 h i j? 表示第 i 行第 j 列的高度。他現在所在位置的坐標…

CC++鏈接數據庫(MySQL)超級詳細指南

C/C鏈接數據庫&#xff08;MySQL&#xff09;超級詳細指南 在C/C編程中&#xff0c;與數據庫進行交互是一項常見的任務。MySQL作為一個廣泛使用的開源關系型數據庫管理系統&#xff0c;提供了豐富的API供C/C開發者使用。本文將詳細介紹如何在C/C程序中鏈接MySQL數據庫&#xf…

基于EM期望最大化算法的GMM參數估計與三維數據分類系統python源碼

目錄 1.算法運行效果圖預覽 2.算法運行軟件版本 3.部分核心程序 4.算法理論概述 4.1 EM算法 E步:期望步 M步:最大化步 4.2 GMM模型 5.算法完整程序工程 1.算法運行效果圖預覽 (完整程序運行后無水印) 2.算法運行軟件版本 程序運行配置環境&#xff1a; 人工智能算法…