---
# System prepended metadata

title: 電腦視覺

---

<center><font size="10">電腦視覺1.0</font></center>

[toc]

:::info
:bulb: 名詞解釋只挑幾個並簡短敘述
:::

# 作業一

## 數位影像處理技術

**影像擷取**:由實體擷取影像，`可使用數位相機、掃描器、CT、雷達`
**影像增強**:針對數位影像進行運算處理，符合特定需求的技術，`如增加對比度、去雜訊。`
**影像還原**:目標是從受損或退化的圖象中，恢復出原始的、高品質的版本。
**影像壓縮**:把不必要的或多餘的資訊去除，保留重要資訊，藉以節省資料量的技術。

## 數位視訊處理技術

**視訊擷取**:由實體擷取連續的影像，這些影像依照一定速率播放，就形成視訊。
**取樣率轉換**:改變信號的取樣頻率或速率。`如音樂的96khz轉成44.1khz。`
**運動估測**:分析視訊中物體或場景的運動。
**視訊壓縮**:將體量巨大的視訊數據進行大比例壓縮，從而實現高校傳輸和存儲的技術。
**視訊增強**:一種處理視訊素材以提高其質量、清晰度、對比度和視覺效果的技術。
**運動偵測**:一種視覺技術，旨在檢測和識別視訊中的運動或動態物體。

# 作業二

## 色彩模式

**RGB**:分別代表紅綠藍，一種加性模型，混合紅綠藍可以產生其他顏色。
**HSV**:表色相、飽和度、明度。
**YCbCr**:表亮度、藍色差、紅色差。

## 數位影像格式

**GIF**:無損壓縮的格式，8位元色彩深度
**PNG**:無損壓縮的格式，旨在取代GIF，支援更多顏色，更好的壓縮效率。
**JPEG**:有損壓縮的格式，所以檔案更小。
**BMP**:不壓縮的格式，因為不壓縮，所以文件大小較大。

## 隱像術

原影像為
|   7    |   5    |
|:------:|:------:|
| **17** | **51** |

隱藏下列浮水印

|   0   |   1   |
|:-----:|:-----:|
| **1** | **0** |

原影像轉成2進位
7 = 111
5 = 101
17 = 10001
51 = 110011

把每格2進位的最後一位改成矩陣中的值

7 = 11<font color="blue">1</font> -> 11<font color="red">0</font> = ||6||

5 = 10<font color="blue">1</font> -> 10<font color="red">1</font> = ||5||

17 = 1000<font color="blue">1</font> -> 1000<font color="red">1</font> = ||17||

51 = 11001<font color="blue">1</font> -> 11001<font color="red">0</font> = ||50||
:::spoiler 答
|   6    |   5    |
|:------:|:------:|
| **17** | **50** |
:::


# 作業三

原影像為
面罩為3x3

| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | 101 | 120 | 200 | 110 |
| 101 | 105 | 210 | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

## 平滑法

:::spoiler 點我顯示python程式碼 修改自chatgpt
```python=
# 原始矩陣A
matrix_A = [
    [101, 105, 106, 110, 200],
    [103, 101, 120, 200, 110],
    [101, 105, 210, 101, 105],
    [108, 200, 125, 250, 111],
    [200, 122, 120, 111, 101]
]

# 初始化矩陣B，與矩陣A相同
matrix_B = [[num for num in row] for row in matrix_A]

# 定義中值法函數
def apply_median_filter(matrix):
    for i in range(1, 4):
        for j in range(1, 4):
            # 取得9個數字
            sub_matrix = [
                matrix[i-1][j-1], matrix[i-1][j], matrix[i-1][j+1],
                matrix[i][j-1], matrix[i][j], matrix[i][j+1],
                matrix[i+1][j-1], matrix[i+1][j], matrix[i+1][j+1]
            ]
            # 將9個數字相加除9
            sum_matrix = round(sum(sub_matrix)/9)
            # 將數字覆蓋到B矩陣的相對應位置
            matrix_B[i][j] = sum_matrix
    return matrix_B

matrix_B = apply_median_filter(matrix_A)

# 輸出矩陣B
print("處理後的矩陣B：")
for row in matrix_B:
    print(" ".join(map(str, row)))
```
:::
<br>

平滑法方法:
計算面罩內的數字平均值，替代面罩中心點。
| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">106</font> | 110 | 200 |
|:-----------------------------:|:-----------------------------:|:-----------------------------:|:---:|:---:|
| <font color="blue">103</font> | <font color="blue">101</font> | <font color="blue">120</font> | 200 | 110 |
| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">210</font> | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

(101+105+106+103+101+120+101+105+210)/9≈117

| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">117</font> | 120 | 200 | 110 |
| 101 | 105 | 210 | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

跑過全圖。==都使用原影像進行計算==。
:::spoiler 答
| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">117</font> | <font color="red">129</font> | <font color="red">140</font> | 110 |
| 101 | <font color="red">130</font> | <font color="red">157</font> | <font color="red">148</font> | 105 |
| 108 | <font color="red">143</font> | <font color="red">149</font> | <font color="red">137</font> | 111 |
| 200 | 122 | 120 | 111 | 101 |
:::   

    
## 中值法

:::spoiler 點我顯示python程式碼 修改自chatgpt
```python=
# 原始矩陣A
matrix_A = [
    [101, 105, 106, 110, 200],
    [103, 101, 120, 200, 110],
    [101, 105, 210, 101, 105],
    [108, 200, 125, 250, 111],
    [200, 122, 120, 111, 101]
]

# 初始化矩陣B，與矩陣A相同
matrix_B = [[num for num in row] for row in matrix_A]

# 定義中值法函數
def apply_median_filter(matrix):
    for i in range(1, 4):
        for j in range(1, 4):
            # 取得9個數字
            sub_matrix = [
                matrix[i-1][j-1], matrix[i-1][j], matrix[i-1][j+1],
                matrix[i][j-1], matrix[i][j], matrix[i][j+1],
                matrix[i+1][j-1], matrix[i+1][j], matrix[i+1][j+1]
            ]
            # 將9個數字排序
            sub_matrix.sort()
            # 將排序後的第5個數字覆蓋到B矩陣的相對應位置
            matrix_B[i][j] = sub_matrix[4]
    return matrix_B

matrix_B = apply_median_filter(matrix_A)

# 輸出矩陣B
print("處理後的矩陣B：")
for row in matrix_B:
    print(" ".join(map(str, row)))
```
:::
<br>

中值法方法:

對面罩內排序，序列中位數替代面罩中心點。

| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">106</font> | 110 | 200 |
|:-----------------------------:|:-----------------------------:|:-----------------------------:|:---:|:---:|
| <font color="blue">103</font> | <font color="blue">101</font> | <font color="blue">120</font> | 200 | 110 |
| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">210</font> | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

序列為[101, 101, 101, 103, <font color="red">105</font>, 105, 106, 120, 210]

| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">105</font> | 120 | 200 | 110 |
| 101 | 105 | 210 | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

跑過全圖。==都使用原影像進行計算==。
:::spoiler 答
| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">105</font> | <font color="red">106</font> | <font color="red">110</font> | 110 |
| 101 | <font color="red">108</font> | <font color="red">125</font> | <font color="red">120</font> | 105 |
| 108 | <font color="red">122</font> | <font color="red">122</font> | <font color="red">111</font> | 111 |
| 200 | 122 | 120 | 111 | 101 |
:::


## 中央加權中值法

:::spoiler 點我顯示python程式碼 修改自chatgpt
```python=
# 原始矩陣A
matrix_A = [
    [101, 105, 106, 110, 200],
    [103, 101, 120, 200, 110],
    [101, 105, 210, 101, 105],
    [108, 200, 125, 250, 111],
    [200, 122, 120, 111, 101]
]

# 初始化矩陣B，與矩陣A相同
matrix_B = [[num for num in row] for row in matrix_A]
# 加權值
W = 5
Wvalue = W-1
# 定義中值法函數
def apply_median_filter(matrix):
    for i in range(1, 4):
        for j in range(1, 4):
            # 取得9個數字 
            sub_matrix = [
                matrix[i-1][j-1], matrix[i-1][j], matrix[i-1][j+1],
                matrix[i][j-1], matrix[i][j], matrix[i][j+1],
                matrix[i+1][j-1], matrix[i+1][j], matrix[i+1][j+1]
            ]
            # 多算加權值的次數
            sub_matrix.extend([matrix[i][j]] * Wvalue)
            # 排序
            sub_matrix.sort()
            # 將數字覆蓋到B矩陣的相對應位置
            matrix_B[i][j] = sub_matrix[6]
    return matrix_B

matrix_B = apply_median_filter(matrix_A)

# 輸出矩陣B
print("處理後的矩陣B：")
for row in matrix_B:
    print(" ".join(map(str, row)))
```
:::

<br>

中央加權中值法方法:
對面罩內排序，再將中心點複製`加權值-1`次，序列中位數替代面罩中心點。

| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">106</font> | 110 | 200 |
|:-----------------------------:|:-----------------------------:|:-----------------------------:|:---:|:---:|
| <font color="blue">103</font> | <font color="blue">101</font> | <font color="blue">120</font> | 200 | 110 |
| <font color="blue">101</font> | <font color="blue">105</font> | <font color="blue">210</font> | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

101, 101, 101, 101, 101, 101, <font color="red">101</font>, 103, 105, 105, 106, 120, 210

:::info
有`加權值`個101是中心點的數
:::
| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">101</font> | 120 | 200 | 110 |
| 101 | 105 | 210 | 101 | 105 |
| 108 | 200 | 125 | 250 | 111 |
| 200 | 122 | 120 | 111 | 101 |

跑過全圖。==都使用原影像進行計算==。
:::spoiler 答
| 101 | 105 | 106 | 110 | 200 |
|:---:|:---:|:---:|:---:|:---:|
| 103 | <font color="red">101</font> | <font color="red">120</font> | <font color="red">200</font> | 110 |
| 101 | <font color="red">105</font> | <font color="red">200</font> | <font color="red">110</font> | 105 |
| 108 | <font color="red">200</font> | <font color="red">125</font> | <font color="red">125</font> | 111 |
| 200 | 122 | 120 | 111 | 101 |
:::


# 作業四

## RGB轉YIQ

|  (30,50,80)  |  (40,60,70)   |
|:------------:|:-------------:|
| (50,100,150) |  (60,90,160)  |
| (10,20,120)  | (250,200,110) |

:::info
:bulb: 公式為:
Y=0.299R+0.587G+0.114B

I=0.596R-0.274G-0.322B

Q=0.211R-0.523G+0.312B
:::


:::spoiler 點我顯示python程式碼 修改自chatgpt
```python=
def rgb_to_yiq(r, g, b):
    y = 0.299 * r + 0.587 * g + 0.114 * b
    i = 0.596 * r - 0.274 * g - 0.322 * b
    q = 0.211 * r - 0.523 * g + 0.312 * b
    return y, i, q

# 從控制台輸入RGB值，用空格分隔
rgb_input = input("請輸入RGB值（以空格分隔）: ")
r, g, b = map(int, rgb_input.split())

# 轉換為YIQ顏色空間
y, i, q = rgb_to_yiq(r, g, b)

# 輸出結果
print("Y: {:.2f}".format(y))
print("I: {:.2f}".format(i))
print("Q: {:.2f}".format(q))
```
:::

<br>

:::spoiler 答
| (47.4 , -21.6 , 5.1)  | (55.2 , -15.1 , -1.1)  |
|:---------------------:|:----------------------:|
| (90.8 , -45.9 , 5.0)  |  (89 , -40.4 , 15.5)   |
| (28.4 , -38.2 , 29.1) | (204.7 , 58.8 , -17.5) |
:::


## MSE,PSNR

有2張8位元灰階影像:

1.
| 135 | 140 | 133 |
|:---:|:---:|:---:|
| 132 | 134 | 132 |
| 136 | 136 | 150 |

2.
| 138 | 146 | 143 |
|:---:|:---:|:---:|
| 140 | 135 | 137 |
| 141 | 146 | 162 |

計算MSE(Mean Square Error)和PSNR(Peak signal-to-noise ratio)

:::spoiler 點我顯示python程式碼 修改自chatgpt
```python=
import math        

# 兩個圖像的像素值（以二維列表形式表示）
image1 = [
    [135, 140, 133],
    [132, 134, 132],
    [136, 136, 150]
]

image2 = [
    [138, 146, 143],
    [140, 135, 137],
    [141, 146, 162]
]

# 計算均方誤差（MSE）
def calculate_mse(image1, image2):
    mse = 0
    total_pixels = 0
    for i in range(len(image1)):
        for j in range(len(image1[0])):
            mse += (image1[i][j] - image2[i][j]) ** 2
            total_pixels += 1
    mse /= total_pixels
    return mse

# 計算峰值信噪比（PSNR）
def calculate_psnr(mse):
    MAX = 255  # 8位元圖像的最大像素值
    psnr = round(10 * (math.log10(MAX**2) - math.log10(mse)),2)
    return psnr

# 呼叫函數計算MSE
mse_value = calculate_mse(image1, image2)
# 計算PSNR
psnr_value = calculate_psnr(mse_value)

print("MSE:", mse_value)
print("PSNR:", psnr_value)
```
:::

<br>

:::success
MSE
<details>
  <summary>答</summary>
  MSE = 56
</details>

方法為:
計算每個像素點的差的平方的平均
`每個位置的點互減然後平方再全部總合算平均`
$$
MSE = \frac{1}{N} \sum_{i=1}^{N} (I_{1i} - I_{2i})^2
$$

:::
:::success
PSNR
<details>
  <summary>答</summary>
  PSNR = 30.65 dB
</details>

方法為:
10乘log(MAX平方除MSE)
`MAX為像素最大值(8位元為255)`
$$
PSNR = 10 \cdot \log_{10} \left( \frac{{\text{{MAX}}^2}}{{\text{{MSE}}}} \right)
$$

:::

# 作業五

## 直方圖等化

原圖為:

|  0  |  0  |  4  |  5  |  4  |  2  |
|:---:|:---:|:---:|:---:|:---:|:---:|
|  0  |  2  |  0  |  4  |  5  |  1  |
|  0  |  1  |  1  |  4  |  5  |  0  |
|  0  |  5  |  4  |  6  |  6  |  0  |
|  0  |  6  |  6  |  5  |  6  |  0  |
|  5  |  6  |  5  |  4  |  5  |  4  |

依照原圖畫出表格:

$r_k$=灰度級別
$n_k$=出現幾次
$P_r$($r_k$)=該像素占比(nk除總像素量)
$s_k$=等化後的灰度級別(計算方式為0到$r_k$的$P_r$累積乘上最大灰度)
| $r_k$ | $n_k$ |  $P_r$($r_k$)   |            $s_k$ 計算             | $s_k$結果(四捨五入) |
| ----- |:-----:|:---------------:|:---------------------------------:|:-------------------:|
| 0     |  10   | $\frac{10}{36}$ | $\frac{10}{36}\times6\approx1.67$ |          2          |
| 1     |   3   | $\frac{3}{36}$  | $\frac{13}{36}\times6\approx2.17$ |          2          |
| 2     |   2   | $\frac{2}{36}$  | $\frac{15}{36}\times6\approx2.5$  |          3          |
| 4     |   7   | $\frac{7}{36}$  | $\frac{22}{36}\times6\approx3.67$ |          4          |
| 5     |   8   | $\frac{8}{36}$  |  $\frac{30}{36}\times6\approx5$   |          5          |
| 6     |   6   | $\frac{6}{36}$  |  $\frac{36}{36}\times6\approx6$   |          6          |

在將圖片依照$s_k$結果改掉
:::spoiler 答
|  2  |  2  |  4  |  5  |  4  |  3  |
|:---:|:---:|:---:|:---:|:---:|:---:|
|  2  |  3  |  2  |  4  |  5  |  2  |
|  2  |  2  |  2  |  4  |  5  |  2  |
|  2  |  5  |  4  |  6  |  6  |  2  |
|  2  |  6  |  6  |  5  |  6  |  2  |
|  5  |  6  |  5  |  4  |  5  |  4  |
:::


## 空間上的冗餘

指的是圖像中的像素值或結構中存在重複、不必要的信息。

# 作業六

## 視訊編碼流程
**有錯 懶得改**
捕捉 --> 預處理 --> 分幀 --> 移除冗餘資訊 --> 壓縮 --> 建立預測 --> 編碼 --> 壓縮位元流 --> 儲存或傳輸 --> 解碼和顯示

## 區塊比對搜尋範圍方式
![image.png](https://hackmd.io/_uploads/B1LNSPwmp.png)
[圖取自台師大機構典藏系統](http://rportal.lib.ntnu.edu.tw:8080/server/api/core/bitstreams/272c8606-e420-4994-8482-1c0dbb9998bd/content)

## 全面搜尋演算法(Full Search Alogorithm)優缺點

優點:
- 確保找到最優解
- 簡單易懂
- 通用性強

缺點:
- 計算複雜度高
- 不適合大規模

## 大部分關於減少搜尋點數的快速演算法，都是依據哪些重要的假設條件所設計?

空間相關性、低運動量、均勻性、局部性

## 三步搜尋演算法(Three-Step Search Alogorithm:TSS)的步驟?

![image.png](https://hackmd.io/_uploads/ryO5uwP7a.png)

[圖取自國立陽明交通大學機構典藏](https://ir.nctu.edu.tw/bitstream/11536/68124/1/251601.pdf)

1. 以原點、和最外圍8點為搜尋點，找區域最佳點。
2. 第一步找到的區域最佳點為中心，縮小搜尋範圍，並新增8個點，找區域最佳點。
3. 第二步找到的區域最佳點為中心，縮小搜尋範圍，並新增8個點，找區域最佳點，此點為全域最佳點。


# 版本歷史紀錄

|    日期    | 版次 | 修改原因 | 備註 |
|:----------:|:----:|:--------:|:----:|
| 2023/11/07 | 1.0  | 初版完成 |      |
|            |      |          |      |
