---
# System prepended metadata

title: 影像濾波

---

# 🧪 影像濾波實驗報告

---

## 🌊 一、低通濾波（Low-pass Filter）

### 📘 原理說明  
低通濾波器用於**保留圖像中的低頻成分**，可去除雜訊與細節，使圖像看起來更平滑。  
常見實作方式如**均值濾波器（Mean Filter）**、**高斯濾波器（Gaussian Filter）**，皆透過遮罩與原圖像做卷積運算來實現。

---

### 🧮 濾波計算步驟說明

1. 將遮罩（Kernel）放置於影像上方，與對應像素值相乘。
2. 將所有乘積加總後除以遮罩內的總和（做正規化）。
3. 把所得結果填入該遮罩中心位置的像素值。
4. 遮罩滑動至下一個位置，持續進行整張影像掃描。

#### 📌 計算舉例：
原始像素值 (3×3)：

[ 21,  19,  17 ]
[ 71,   8,  90 ]
[ 14, 164, 164 ]

遮罩權重 (3×3)：

[-1, -1, -1]
[-1,  8, -1]
[-1, -1, -1]


遮罩總和/9=84.22

將結果丟入中心(新的遮罩的相同位置中心)


---

### 📈 流程圖
![圖片1](https://hackmd.io/_uploads/HyZUEc20ye.png)

---

### 💻 程式碼
```cpp=
#include <iostream>
#include <stdlib.h>
#include "bmp.h"

using namespace std;

int R[MaxBMPSizeX][MaxBMPSizeY]; 
int G[MaxBMPSizeX][MaxBMPSizeY];
int B[MaxBMPSizeX][MaxBMPSizeY];
int r[MaxBMPSizeX][MaxBMPSizeY];
int g[MaxBMPSizeX][MaxBMPSizeY];
int b[MaxBMPSizeX][MaxBMPSizeY];

// 低通濾波函式
void lowPassFilter(int inputR[][MaxBMPSizeY], int inputG[][MaxBMPSizeY], int inputB[][MaxBMPSizeY], int outputR[][MaxBMPSizeY], int outputG[][MaxBMPSizeY], int outputB[][MaxBMPSizeY], int width, int height)
{
    // 定義低通濾波器遮罩
    int mask[3][3] = {
        {1, 2, 1},
        {2, 4, 2},
        {1, 2, 1}
    };

    // 圖像的每個像素
    for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
            int sumR = 0;
            int sumG = 0;
            int sumB = 0;
            int count = 0;

            // 在遮罩範圍內計算像素值總和
            for (int y = -1; y <= 1; y++) {
                for (int x = -1; x <= 1; x++) {
                    sumR += inputR[i + x][j + y] * mask[x + 1][y + 1];
                    sumG += inputG[i + x][j + y] * mask[x + 1][y + 1];
                    sumB += inputB[i + x][j + y] * mask[x + 1][y + 1];
                    count += mask[x + 1][y + 1];
                }
            }

            // 將相加結果除以遮罩內非零數值的個數
            outputR[i][j] = sumR / count;
            outputG[i][j] = sumG / count;
            outputB[i][j] = sumB / count;
        }
    }
}

int main(int argc, char* argv[])
{
    int width, height;
    int i, j;

    // 開啟並讀取全彩(24bits)bmp 影像圖檔
    open_bmp("lena.bmp", R, G, B, width, height);

    // 執行低通濾波處理
    lowPassFilter(R, G, B, r, g, b, width, height);

    // 儲存處理結果至新的圖檔中
    save_bmp("lenna_new1.bmp", r, g, b);

    printf("Job Finished!\n");

    // 關閉 bmp 影像圖檔
    close_bmp();

    system("pause"); 
    return 0;
}
```

---

### 🖼️ 結果圖
| 原始圖像 | 低通濾波 |
|----------|------------------|
![lena](https://hackmd.io/_uploads/HyruNc3Ayx.bmp)|![lenna_filtered](https://hackmd.io/_uploads/SJC_V5nA1e.bmp)

---

## 🔪 二、高通濾波（High-pass Filter）

### 🧮 高通濾波運算原理說明

在高通濾波中，透過一個預定義的遮罩（Kernel）對圖像做卷積操作。其主要步驟如下：

1. **將遮罩覆蓋在圖像上**，以該像素為中心。
2. **遮罩中的每個權重值**乘上對應位置的像素值。
3. **將所有乘積進行加總**，結果即為該中心像素的新值。
4. **與低通濾波不同的是：**
   - **不進行總和正規化（不除以總和）**
   - 遮罩的權重總和通常為 **0**
   - 用來強調高頻變化，例如邊緣與細節

---

#### 📌 常用高通濾波器（3×3）

[ 0 -1 0 ]
[ -1 4 -1 ]
[ 0 -1 0 ]

[ -1 -1 -1 ]
[ -1 8 -1 ]
[ -1 -1 -1 ]

---

### 📈 流程圖
![圖片2](https://hackmd.io/_uploads/SJWSHc3Ake.png)

---

### 💻 程式碼
```cpp=
#include <iostream>
#include <stdlib.h>
#include "bmp.h"

using namespace std;

int R[MaxBMPSizeX][MaxBMPSizeY];
int G[MaxBMPSizeX][MaxBMPSizeY];
int B[MaxBMPSizeX][MaxBMPSizeY];
int r[MaxBMPSizeX][MaxBMPSizeY];
int g[MaxBMPSizeX][MaxBMPSizeY];
int b[MaxBMPSizeX][MaxBMPSizeY];

// 高通濾波函式
void highPassFilter(int inputR[][MaxBMPSizeY], int inputG[][MaxBMPSizeY], int inputB[][MaxBMPSizeY], int outputR[][MaxBMPSizeY], int outputG[][MaxBMPSizeY], int outputB[][MaxBMPSizeY], int width, int height)
{
    //高通濾波器遮罩
    int mask[3][3] = {
        {1, 1, 1},
        {1,-8, 1},
        {1, 1, 1}
    };

    // 圖像的每個像素
    for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
            int sumR = 0;
            int sumG = 0;
            int sumB = 0;

            // 在遮罩範圍內計算像素值總和
            for (int y = -1; y <= 1; y++) {
                for (int x = -1; x <= 1; x++) {
                    sumR += inputR[i + x][j + y] * mask[x + 1][y + 1];
                    sumG += inputG[i + x][j + y] * mask[x + 1][y + 1];
                    sumB += inputB[i + x][j + y] * mask[x + 1][y + 1];
                }
            }

            // 限制顏色值在 0 到 255 的範圍內
            outputR[i][j] = max(0, min(sumR, 255));
            outputG[i][j] = max(0, min(sumG, 255));
            outputB[i][j] = max(0, min(sumB, 255));
        }
    }
}

int main(int argc, char* argv[])
{
    int width, height;
    int i, j;

    // 開啟並讀取全彩bmp 影像圖檔
    open_bmp("lena.bmp", R, G, B, width, height);

    // 執行高通濾波處理
    highPassFilter(R, G, B, r, g, b, width, height);

    // 儲存處理結果至新的圖檔中
    save_bmp("lenna_highpass.bmp", r, g, b);

    printf("Job Finished!\n");

    // 關閉 bmp 影像圖檔
    close_bmp();

    system("pause");
    return 0;
}

```
---

### 🖼️ 結果圖
| 原始圖像 | 高通濾波 |
|----------|------------------|
![lena](https://hackmd.io/_uploads/B1bfI9n0yx.bmp)|![lenna_highpass](https://hackmd.io/_uploads/r1DMU5nAJl.bmp)



---

## 🧼 三、中值濾波（Median Filter）

### 🧮 中值濾波運算原理說明

中值濾波是一種非線性濾波器，適用於**去除椒鹽雜訊**，同時能保留邊緣細節。其運算步驟如下：

---

#### 📌 運算流程：

1. 將一個 3×3 遮罩放置在影像上，以當前像素為中心取 3×3 鄰域像素。
2. 將遮罩範圍內的 **9 個像素值放入一維陣列**。
3. 對此陣列內的值 **進行排序（由小到大）**。
4. 取陣列中的 **中位數（第 5 個數值）**。
5. 將此中位數結果 **填入對應的中心位置**。
6. 重複操作，**對整張圖像每個像素進行處理**。
![圖片3](https://hackmd.io/_uploads/HyFaS93Cye.png)

---

### 📈 流程圖
![圖片4](https://hackmd.io/_uploads/r1JAS93Cyl.png)

---

### 💻 程式碼
```cpp=
#include <iostream>
#include <stdlib.h>
#include "bmp.h"

using namespace std;

int R[MaxBMPSizeX][MaxBMPSizeY];
int G[MaxBMPSizeX][MaxBMPSizeY];
int B[MaxBMPSizeX][MaxBMPSizeY];
int r[MaxBMPSizeX][MaxBMPSizeY];
int g[MaxBMPSizeX][MaxBMPSizeY];
int b[MaxBMPSizeX][MaxBMPSizeY];

// 中值濾波函式
void medianFilter(int inputR[][MaxBMPSizeY], int inputG[][MaxBMPSizeY], int inputB[][MaxBMPSizeY], int outputR[][MaxBMPSizeY], int outputG[][MaxBMPSizeY], int outputB[][MaxBMPSizeY], int width, int height)
{
    // 遮罩大小為 3x3
    const int maskSize = 3;
    const int maskLength = maskSize * maskSize;
    int maskValues[maskLength];

    // 圖像的每個像素
    for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
            int index = 0;

            // 收集遮罩範圍內的像素值
            for (int y = -1; y <= 1; y++) {
                for (int x = -1; x <= 1; x++) {
                    maskValues[index] = inputR[i + x][j + y];
                    index++;
                }
            }

            // 對遮罩內的像素值進行排序
            for (int k = 0; k < maskLength - 1; k++) {
                for (int l = 0; l < maskLength - k - 1; l++) {
                    if (maskValues[l] > maskValues[l + 1]) {
                        int temp = maskValues[l];
                        maskValues[l] = maskValues[l + 1];
                        maskValues[l + 1] = temp;
                    }
                }
            }

            // 將中位數儲存到輸出像素中
            outputR[i][j] = maskValues[maskLength / 2];
            outputG[i][j] = maskValues[maskLength / 2];
            outputB[i][j] = maskValues[maskLength / 2];
        }
    }
}

int main()
{
    int width, height;
    int i, j;

    // 開啟並讀取全彩bmp圖檔
    open_bmp("lena_pepper_and_salt_noise10%.bmp", R, G, B, width, height);

    // 執行中值濾波處理
    medianFilter(R, G, B, r, g, b, width, height);

    // 儲存處理結果至新的圖檔中
    save_bmp("lenna_median.bmp", r, g, b);

    printf("Job Finished!\n");

    // 關閉 bmp 影像圖檔
    close_bmp();

    system("pause");
    return 0;
}

```
---

### 🖼️ 結果圖
| 原始圖像 | 中值濾波 |
|----------|------------------|
![lena_pepper_and_salt_noise10%](https://hackmd.io/_uploads/SyYEIc3Ckx.bmp)|![lenna_median](https://hackmd.io/_uploads/HyRN8chA1g.bmp)
