From c2fa2f7b7add7f94f11fecfcc302a3f5168b3640 Mon Sep 17 00:00:00 2001 From: 5000user5000 Date: Fri, 5 Dec 2025 16:00:46 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=8E=BB=E9=99=A4=20report?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/report.md | 169 -------------------------------------------------- 1 file changed, 169 deletions(-) delete mode 100644 doc/report.md diff --git a/doc/report.md b/doc/report.md deleted file mode 100644 index 1637de1..0000000 --- a/doc/report.md +++ /dev/null @@ -1,169 +0,0 @@ -# Fast JPEG Decoder 實作與效能分析報告 - -**Performance Analysis of JPEG Decoding: C++ (Pybind11) vs. Python (NumPy)** - -## 1\. 專案摘要 (Executive Summary) - -本專案旨在深入探討 JPEG 壓縮標準的底層實作,並比較不同編程語言與優化策略對解碼效能的影響。我們從零實作了兩套完整的 JPEG Baseline 解碼器: - -1. **C++ 版本**:使用 Pybind11 封裝,作為高效能對照組。 -2. **Python 版本**:使用 NumPy 向量化運算,作為高階語言實作代表。 - -**核心成果**: - - * 成功實作了符合 ITU-T T.81 標準的 Baseline DCT 解碼流程。 - * **C++ 版本**展現了卓越的效能,比 NumPy 版本快約 **4.4 倍**。 - * **準確度驗證**:C++ 版本與標準庫 PIL (Pillow) 的 PSNR 高達 **35.20 dB**,證明解碼邏輯正確。 - * **問題修復**:解決了 JPEG 量化表 Zigzag 排列、4:2:0 Upsampling 崩潰等多個關鍵技術難題。 - ------ - -## 2\. 專案動機 (Motivation) - -### 2.1 為什麼要「重造輪子」? - -雖然市面上已有 `libjpeg-turbo` 或 `OpenCV` 等成熟函式庫,但親手實作解碼器是理解視訊壓縮原理的最佳途徑。本專案的學習目標包括: - -1. **解構 JPEG 標準**:從位元流 (Bitstream) 解析、霍夫曼解碼 (Huffman Decoding) 到 IDCT 變換,掌握壓縮的核心數學原理。 -2. **效能瓶頸分析**:親身體驗 Python 直譯器在處理位元級操作時的效能瓶頸,並驗證 C++ 在系統編程上的優勢。 -3. **跨語言整合**:實踐 **Python/C++ 混合編程** (Hybrid Programming),利用 Pybind11 將 C++ 的高效能核心注入 Python 生態系。 - ------ - -## 3\. 系統架構與實作細節 (Implementation) - -專案採用三層式架構,將底層運算與上層應用分離。架構圖如下: - -```text -┌─────────────────────────────┐ -│ 使用者 / Benchmark │ -└──────────────┬──────────────┘ - │ 呼叫 - ▼ -┌─────────────────────────────┐ -│ Python 介面層 │ -│ (run_benchmark.py / API) │ -└──────────────┬──────────────┘ - │ 分流 - ┌───────┴───────┐ - │ │ - ▼ ▼ -┌──────────────┐ ┌──────────────┐ -│ C++ 核心 │ │ NumPy 實作 │ -│ (Fast Path) │ │ (Reference) │ -└──────┬───────┘ └───────┬──────┘ - │ │ - └───────┬─────────┘ - │ 執行解碼流程 - ▼ - ┌───────────────────────┐ - │ 1. Marker Parsing │ - │ 2. Huffman Decoding │ - │ 3. Dequantization │ - │ 4. Inverse DCT │ - │ 5. Chroma Upsampling │ - │ 6. YCbCr to RGB │ - └───────────────────────┘ -``` - -### 3.1 C++ 核心 (Fast Path) - - * **語言標準**:C++17 - * **關鍵技術**: - * **BitStream 優化**:使用 32-bit 緩衝區與位元位移操作,極大化 Huffman 解碼效率。 - * **記憶體管理**:使用 `std::vector` 與指標操作,減少不必要的記憶體拷貝。 - * **Pybind11 整合**:實現 `bytes` 到 `std::vector` 的高效轉換,直接回傳 NumPy Array 給 Python 端。 - -### 3.2 Python NumPy 核心 (Reference Path) - - * **設計理念**:利用 NumPy 的矩陣運算能力來加速 IDCT 與顏色轉換。 - * **技術挑戰**: - * 雖然 IDCT 可以用 `@` 運算子向量化,但 **Huffman 解碼** 具有序列依賴性 (Sequential Dependency),無法向量化,必須在 Python 迴圈中逐位元處理,成為最大效能瓶頸。 - ------ - -## 4\. 關鍵技術難點與解決方案 (Technical Challenges) - -在開發過程中,我們遭遇並解決了數個嚴重影響正確性與穩定性的問題: - -### 🔥 難點 1: 量化表 (DQT) 的 Zigzag 陷阱 - - * **問題現象**:NumPy 版本解碼出的圖片嚴重變暗 (Mean \~85 vs 標準值 128),且細節全毀。 - * **原因分析**:JPEG 文件中的量化表是以 **Zigzag 順序** 儲存的 1D 陣列。初版代碼直接將其 `reshape(8, 8)`,導致高頻量化係數錯位到低頻位置,破壞了頻域數據。 - * **解決方案**:實作 `zigzag_to_2d` 函數,在應用量化表前先將其還原為正確的 8x8 空間排列。 - ```python - # 修正後的代碼 - self.quantization_tables[id] = self.zigzag_to_2d(np.array(values)) - ``` - -### 🔥 難點 2: 4:2:0 Upsampling 崩潰 - - * **問題現象**:解碼非 4:4:4 格式圖片時,程式發生 Segmentation Fault (C++) 或 Index Error (Python)。 - * **原因分析**:原始邏輯假設所有 MCU (最小編碼單元) 都是 8x8 像素。但在 YUV 4:2:0 採樣下,一個 MCU 實際上涵蓋 16x16 像素 (4個 Y Block)。 - * **解決方案**:重寫 Upsampling 邏輯,正確計算 MCU 索引與 Block 偏移量: - ```cpp - int mcu_width = max_h_samp * 8; // 16 for 4:2:0 - int mcu_col = col / mcu_width; // 正確計算所在的 MCU - ``` - -### 🔥 難點 3: 像素級誤差 (Pixel Mismatch) - - * **問題現象**:即便邏輯正確,自製解碼器與 PIL 的結果仍有細微差異 (PSNR 非無限大)。 - * **原因分析**: - 1. **IDCT 精度**:本專案使用標準浮點數 (`double`) 公式,而 PIL 底層 (libjpeg) 使用優化的整數運算,捨入誤差不可避免。 - 2. **Upsampling 算法**:本專案使用 **Nearest Neighbor**,PIL 可能使用 **Bilinear** 插值,導致色度邊緣數值不同。 - * **結論**:PSNR \> 30dB 即代表視覺上無失真,目前的誤差在合理範圍內。 - ------ - -## 5\. 實驗結果與效能分析 (Benchmark Results) - -### 5.1 測試環境 - - * **測試對象**:`lena.jpg` (512x512, YUV 4:4:4), `images.jpeg` (183x275, YUV 4:2:0) - * **Ground Truth**:PIL (Pillow) 9.x 解碼結果 - * **指標**:執行時間 (Time)、峰值訊噪比 (PSNR) - -### 5.2 效能數據 (Performance) - -| 圖片 | C++ Decoder (ms) | NumPy Decoder (ms) | Speedup | -| :--- | :--- | :--- | :--- | -| **Lena (512x512)** | **67.50 ms** | 295.99 ms | **4.38x** | -| **Images (183x275)** | **7.50 ms** | 33.09 ms | **4.41x** | -| **Sample (64x64)** | **0.56 ms** | 2.05 ms | **3.63x** | - -**分析**: - - * **C++ 穩定領先**:在不同尺寸圖片上,C++ 版本均保持約 **4.4 倍** 的速度優勢。 - * **NumPy 的極限**:即使矩陣運算很快,Python `while` 迴圈處理 Huffman 解碼的開銷過大 (佔總時間約 30-40%),這是直譯語言的先天限制。 - -### 5.3 準確度數據 (Quality - PSNR) - -| 解碼器 | vs PIL (Lena) | vs PIL (Images) | 結果判定 | -| :--- | :--- | :--- | :--- | -| **C++ Decoder** | **35.20 dB** | **31.25 dB** | ✅ Pass | -| **NumPy Decoder** | **35.15 dB** | **31.20 dB** | ✅ Pass | - -**分析**: - - * 兩個版本的 PSNR 均超過 30 dB,屬於**高品質還原**。 - * C++ 與 NumPy 的結果極為接近,證明兩者的演算法邏輯一致且正確。 - ------ - -## 6\. 未來優化方向 (Future Work) - -為了進一步挑戰工業級標準 (如 libjpeg-turbo 的 \~5ms),本專案仍有優化空間: - -1. **SIMD 指令集優化 (AVX2)**: - * 目前 IDCT 採用逐個像素計算 (`double` 運算)。改用 AVX2 指令集一次處理 8 個 float,預期可提升 IDCT 效能 4-8 倍。 -2. **整數運算 (Fixed-Point Arithmetic)**: - * 將浮點數運算改為整數移位運算 (Integer Shift),減少 CPU 週期消耗。 -3. **多執行緒平行化 (Multi-threading)**: - * 雖然 Huffman 解碼必須序列執行,但 **IDCT** 與 **Color Conversion** 是 Block 獨立的。可使用 OpenMP 平行處理不同 MCU,充分利用多核心 CPU。 - ------ - -## 7\. 結論 (Conclusion) - -本專案成功驗證了「使用 C++ 優化 Python 關鍵路徑」的有效性。透過 Pybind11,我們將 JPEG 解碼中最耗時的位元流解析與流程控制搬移至 C++ 層,在保持 Python 易用性的同時,獲得了 **4.4 倍** 的效能提升。這不僅是一個圖像解碼器的實作,更是系統效能優化的最佳實踐案例。 \ No newline at end of file From 05fc2d00d2dd6979242596d0e5413cf59f72d4bb Mon Sep 17 00:00:00 2001 From: 5000user5000 Date: Fri, 5 Dec 2025 16:01:03 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E7=A7=BB=E5=8B=95=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BENCHMARK_RESULTS.md | 43 ------------------- 1 file changed, 43 deletions(-) rename BENCHMARK_RESULTS.md => doc/BENCHMARK_RESULTS.md (84%) diff --git a/BENCHMARK_RESULTS.md b/doc/BENCHMARK_RESULTS.md similarity index 84% rename from BENCHMARK_RESULTS.md rename to doc/BENCHMARK_RESULTS.md index 9aef2a0..2eee729 100644 --- a/BENCHMARK_RESULTS.md +++ b/doc/BENCHMARK_RESULTS.md @@ -211,49 +211,6 @@ YCbCr → RGB 轉換 12.3% 數學運算 - 當前 C++ 實現:67.50ms (lena.jpg) - **還有約 13× 的優化空間** -## 結論與建議 - -### 使用建議 - -#### ✅ 推薦使用 C++ 實現 -- **場景**: 性能敏感應用、大規模圖片處理 -- **優勢**: 4.4× 性能提升 + 高品質還原(35+ dB) -- **適用**: 視訊處理、嵌入式系統、即時應用 - -#### ✅ NumPy 實現適用場景 -- **場景**: 學習、原型開發、理解 JPEG 原理 -- **優勢**: 代碼清晰、易於修改、與 C++ 品質相當 -- **限制**: 性能較低,不適合生產環境 - -#### 🚫 生產環境請使用成熟的庫 -- **推薦**: - - `libjpeg-turbo` (C/C++) - 工業標準 - - `PIL/Pillow` (Python) - 功能完整 - - `opencv-python` (Python) - 整合豐富 -- **原因**: - - 完整的 JPEG 格式支援(Progressive, Lossless 等) - - 經過大量測試和優化 - - 持續維護和更新 - -### 專案價值 - -本專案的主要價值在於: - -1. **教學示範** - - 完整實現 JPEG Baseline DCT 解碼流程 - - 修復了多個常見的實現錯誤 - - 提供詳細的技術文檔 - -2. **性能比較研究** - - 實證 C++ vs Python 的性能差異(4.4×) - - 分析瓶頸來源和優化方向 - - 展示 pybind11 的整合實踐 - -3. **品質驗證** - - 使用 PSNR 量化評估解碼品質 - - 證明兩種實現的正確性(35+ dB) - - 提供可靠的參考實現 - ## 已知限制 ### 支援的 JPEG 格式 From c20481077a4e0c1611f6c4b1e97ca5fff2cbd168 Mon Sep 17 00:00:00 2001 From: 5000user5000 Date: Fri, 5 Dec 2025 16:01:11 +0800 Subject: [PATCH 3/3] =?UTF-8?q?README=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c7c0fc8..9e77a83 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,11 @@ **視訊壓縮期末專案** +組員: 周哲瑋 (Wayne),陳冠霖,許詠約 + 高效能 JPEG 解碼器實現,核心使用 C++ 開發並透過 pybind11 提供 Python API。專案包含 C++ 和 NumPy 兩種實現,用於比較不同實現方式的性能差異。 + ## 專案特點 - **⚡ 高效能**: C++ 核心實現,比 NumPy 版本快 **約 4.4 倍** @@ -32,7 +35,7 @@ - NumPy Decoder: **35.15 dB** ✅ (良好) - 兩者均達到視覺無失真標準(> 30 dB) -詳細的 benchmark 結果請參考 [BENCHMARK_RESULTS.md](BENCHMARK_RESULTS.md) +詳細的 benchmark 結果請參考 [BENCHMARK_RESULTS.md](doc/BENCHMARK_RESULTS.md) ## 快速開始 @@ -49,7 +52,7 @@ ```bash # 1. Clone 專案 -git clone https://github.com/yourusername/Fast-Jpeg-Decoder.git +git clone https://github.com/5000user5000/Fast-Jpeg-Decoder.git cd Fast-Jpeg-Decoder # 2. 安裝 Python 依賴 @@ -163,10 +166,9 @@ Fast-Jpeg-Decoder/ ├── benchmarks/ │ └── run_benchmark.py # 性能測試與品質驗證 ├── doc/ -│ └── report.md # 詳細技術報告 +│ └── BENCHMARK_RESULTS.md # Benchmark 結果文檔 ├── output/ # 解碼輸出結果(benchmark 生成) ├── example.py # 使用範例 -├── BENCHMARK_RESULTS.md # Benchmark 結果文檔 ├── Makefile # 建構腳本 ├── setup.py # Python 安裝腳本 └── README.md # 本文件 @@ -252,8 +254,6 @@ JPEG 檔案 解碼完成的圖片 ``` -詳細的技術實現請參考 [doc/report.md](doc/report.md) - ## 技術亮點 ### C++ 實現 @@ -302,8 +302,6 @@ JPEG 檔案 - 多執行緒(OpenMP): 預期提升接近 CPU 核心數 - 查表法(LUT): 預期提升 1.5-2× -詳細分析請參考 [BENCHMARK_RESULTS.md](BENCHMARK_RESULTS.md) - ## 使用建議 ### ✅ 推薦使用場景 @@ -317,13 +315,12 @@ JPEG 檔案 - **生產環境**: 請使用成熟的庫(libjpeg-turbo, PIL/Pillow) - **完整 JPEG 支援**: 本專案僅支援 Baseline DCT -- **關鍵應用**: NumPy 實現存在已知的正確性問題 +- **關鍵應用**: NumPy 實現性能較低(比 C++ 慢 4.4 倍) ## 文檔 - **[README.md](README.md)**: 專案概述和快速開始(本文件) -- **[BENCHMARK_RESULTS.md](BENCHMARK_RESULTS.md)**: 詳細的性能測試結果和正確性驗證 -- **[doc/report.md](doc/report.md)**: 完整的技術報告(包含原理、實現、分析) +- **[BENCHMARK_RESULTS.md](doc/BENCHMARK_RESULTS.md)**: 詳細的性能測試結果和正確性驗證 ### 開發指南 @@ -341,7 +338,6 @@ JPEG 檔案 ### 技術文章 -- [JPEG Decoding Tutorial](https://www.impulseadventure.com/photo/jpeg-decoder.html) - [Fast DCT Algorithms](https://www.nayuki.io/page/fast-discrete-cosine-transform-algorithms) - [Understanding JPEG](https://parametric.press/issue-01/unraveling-the-jpeg/)