# 🧪 影像濾波實驗報告
---
## 🌊 一、低通濾波(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
將結果丟入中心(新的遮罩的相同位置中心)
---
### 📈 流程圖

---
### 💻 程式碼
```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;
}
```
---
### 🖼️ 結果圖
| 原始圖像 | 低通濾波 |
|----------|------------------|
|
---
## 🔪 二、高通濾波(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 ]
---
### 📈 流程圖

---
### 💻 程式碼
```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;
}
```
---
### 🖼️ 結果圖
| 原始圖像 | 高通濾波 |
|----------|------------------|
|
---
## 🧼 三、中值濾波(Median Filter)
### 🧮 中值濾波運算原理說明
中值濾波是一種非線性濾波器,適用於**去除椒鹽雜訊**,同時能保留邊緣細節。其運算步驟如下:
---
#### 📌 運算流程:
1. 將一個 3×3 遮罩放置在影像上,以當前像素為中心取 3×3 鄰域像素。
2. 將遮罩範圍內的 **9 個像素值放入一維陣列**。
3. 對此陣列內的值 **進行排序(由小到大)**。
4. 取陣列中的 **中位數(第 5 個數值)**。
5. 將此中位數結果 **填入對應的中心位置**。
6. 重複操作,**對整張圖像每個像素進行處理**。

---
### 📈 流程圖

---
### 💻 程式碼
```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;
}
```
---
### 🖼️ 結果圖
| 原始圖像 | 中值濾波 |
|----------|------------------|
|