National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 13

攝影機與影像

攝影機模組、拍照與簡單的影像處理概念
Interaction導覽 25 minute(s)

Learning Objectives

  • 說明樹莓派攝影機模組怎麼連接,以及 rpicam-apps 指令與 Picamera2 函式庫的用途
  • 用 Python 把一張影像當成二維的像素陣列來讀取與計算
  • 把彩色像素換成灰階,算出不同解析度下未壓縮影像的資料量
  • 比較前後兩張畫面的差異,判斷有沒有東西在動,並控制 LED
  • 說明在教室使用攝影機時要注意的隱私原則

讓樹莓派「看見」

前面幾課的感測器都只回傳一個數字:溫度幾度、距離幾公分、有沒有人經過。 攝影機一次回傳的是幾百萬個數字,每一個數字代表畫面上一個小點的顏色。 樹莓派是單板電腦(第 01 課),有足夠的記憶體與運算能力處理這麼多資料,這是它和多數微控制器很不一樣的地方。

這一課要回答:

  1. 攝影機模組怎麼接到樹莓派,用什麼指令或函式庫拍照?
  2. 一張照片在程式裡長什麼樣子?
  3. 怎麼用很簡單的計算,從影像裡得到有用的資訊(例如「有沒有東西在動」)?

這個網頁上的模擬器沒有攝影機。拍照的步驟用終端機示範;影像處理的觀念用很小的像素陣列在瀏覽器裡實際執行, 道理和處理真正的照片一樣,只是數字少很多。

攝影機模組與連接方式

樹莓派官方的攝影機模組透過排線接在板子上的 CSI(Camera Serial Interface,攝影機序列介面)接頭,不是 USB。 官方文件列出的接頭有兩種尺寸:

接頭 出現在哪些板子
15 針 CSI Raspberry Pi 5 之前的標準型號(例如 Raspberry Pi 4)
22 針 CSI Raspberry Pi Zero 系列、Compute Module 的 IO 板、Raspberry Pi 5 之後的標準型號

排線兩端的接頭尺寸要和板子對上;買攝影機時先確認板子是哪一種接頭。

常見的官方模組(撰寫時的產品線):

模組 重點
Camera Module 3 1200 萬像素(12MP)的 Sony IMX708 感光元件、自動對焦;有標準與廣角、一般與無紅外線濾鏡(NoIR)等版本
High Quality Camera 約 1230 萬像素,可以換鏡頭(C/CS 接環或 M12 接環),焦距與視角由鏡頭決定

安全與操作:插拔排線前先關機、拔電源;排線的金屬接點朝向要照說明,扣環輕輕拉起、插好再壓下; 不要用手指碰感光元件與鏡頭。

軟體:指令列工具與 Python 函式庫

工具 用途
rpicam-hello、rpicam-still、rpicam-vid 終端機指令:預覽、拍照、錄影(Raspberry Pi OS Bookworm 起改名,舊版叫 libcamera-hello 等)
Picamera2 Python 函式庫,建立在 libcamera 之上;官方建議用 apt 安裝(python3-picamera2),較新的系統通常已預先安裝

舊教材裡的 picamera(沒有 2)與 raspistill 屬於舊的攝影機架構,在新系統上不再適用,看到時要換成上面的工具。

在終端機測試攝影機與拍照

以下是在接好 Camera Module 3 的樹莓派上操作的步驟。輸出經過節錄與簡化,實際的訊息會多很多行。

  1. 1

    確認系統找得到攝影機

    --list-cameras 列出接上的攝影機與它支援的感光元件模式。如果出現「No cameras available」,先關機檢查排線方向與扣環。

  2. 2

    拍一張照片

    rpicam-still 會先開預覽一段時間讓自動曝光與對焦穩定,再拍照存檔;-o 指定檔名。用 ls -lh 看檔案大小。

  3. 3

    錄一段影片

    -t 是錄影時間,單位毫秒;10000 就是 10 秒。輸出是未封裝的 H.264 影像串流。

  4. 4

    用 Python 拍照

    Picamera2 官方手冊裡最短的拍照程式只有三行:

    from picamera2 import Picamera2
    
    picam2 = Picamera2()
    picam2.start_and_capture_file("test.jpg")
    

    要在程式裡處理影像,改用 capture_array() 取得一個 NumPy 陣列,形狀是(高, 寬, 顏色通道數)。下一段開始,我們就用小小的陣列練習怎麼處理它。

這段導覽完成了

影像就是一個二維陣列

數位影像由一格一格的像素(pixel)組成。灰階影像的每個像素用一個 0~255 的整數表示亮度(8 位元), 所以一張灰階影像在 Python 裡可以寫成「串列的串列」:外層每一個元素是一列,內層每一個數字是一個像素。

img[列][行]      ← 先列(y,往下)再行(x,往右)
img[0][0]        左上角
img[1][2]        第 2 列、第 3 個像素(索引從 0 開始)

Picamera2 的 capture_array() 回傳的 NumPy 陣列也是這個順序:高度在前、寬度在後,彩色影像再多一個顏色通道的維度。 下面的範例是一張 5×5 的小影像,看程式怎麼算平均亮度,再用一個門檻把它變成只有黑白兩種的圖。

逐步看:讀像素、算平均、門檻化

右邊變數區的 img 是一個 5×5 的串列。注意第 15 行每執行一次,total 就加上一整列的亮度;第 21 行把每個像素換成 #(亮)或 .(暗)。

彩色、灰階與資料量

彩色影像最常見的表示法是 RGB:每個像素有紅、綠、藍三個 0~255 的數字,各佔 1 個位元組,合起來 3 個位元組(24 位元)。

很多影像處理(偵測移動、找邊緣、辨識形狀)只需要亮度,先把彩色換成灰階可以讓資料量變成三分之一。 換算時三個顏色的權重不一樣,因為人眼對綠色最敏感、對藍色最不敏感。下面的範例用一組常見的權重(ITU-R BT.601):

灰階 = 0.299 × 紅 + 0.587 × 綠 + 0.114 × 藍

未壓縮的資料量 = 寬 × 高 × 每個像素的位元組數。拍成 JPEG 檔時會壓縮得小很多,但程式拿到陣列處理時,記憶體裡是未壓縮的大小。

逐步看:RGB 轉灰階與資料量

第 9 行的 for r, g, b in row 一次把一個像素的三個數字拆開。看純紅、純綠、純藍三個像素換成灰階後亮度差多少。

互動練習:解析度與色彩深度

左邊的圖由程式即時算出。調整解析度(N×N 個像素)與每個顏色通道的位元數,看畫質與未壓縮大小怎麼變。照任務操作:想一想攝影機傳給程式的每一張畫面,解析度與色彩深度各要多少才夠用。

小測驗:攝影機與像素

1.

一張 1920 × 1080、每個像素 3 個位元組(RGB)的影像,未壓縮時大約多大?

2.

下面的程式會印出什麼?

img = [[10, 200, 30], [220, 40, 250]]
count = 0
for row in img:
    for v in row:
        if v > 128:
            count += 1
print(len(img), len(img[0]), count)
3.

在新版 Raspberry Pi OS 上,要用終端機列出接上的攝影機,應該用哪一個指令?

第 1 次作答

用畫面差異偵測移動

要知道畫面裡「有沒有東西在動」,最簡單的方法不需要人工智慧:拿這一張和上一張比。

  1. 逐一比較同一個位置的兩個像素,亮度差的絕對值超過門檻,就算這個像素「變了」。
  2. 數一數有幾個像素變了;超過一定數量,就判斷有東西在動。

兩個門檻都很重要:攝影機的畫面本來就有細微的雜訊(同一個場景,連續兩張的亮度也會差一兩個單位), 第一個門檻擋掉雜訊;第二個門檻擋掉零星幾個像素的變化(例如光線閃一下)。

下一個範例把三張小畫面寫在程式裡(模擬器沒有攝影機),比較的結果用來控制 GPIO17 上的 LED。

逐步看:畫面差異與警示燈

上方的電路畫面只有一顆 LED。第一次比較時畫面幾乎沒變(只有雜訊),第二次右上角變亮了,看 LED 什麼時候亮起來。

在教室使用攝影機:先想隱私

攝影機拍到的是人。在教室、宿舍、實驗室裝攝影機之前,先回答這幾個問題:

  • 真的需要影像嗎? 只想知道「有沒有人」,第 12 課的人體感測器(PIR)就夠了,不會留下任何人的長相。
  • 讓被拍到的人知道。 事先說明拍什麼、為什麼、存多久,取得同意;在現場貼出告示。
  • 能在樹莓派上算完就不要傳出去。 像上一個範例,只保留「有幾個像素變了」這個數字,畫面處理完就丟掉。
  • 不要存不需要的東西。 需要存影像時設定保存期限、限制誰能看,網路傳輸要加密。

樹莓派讓「在裝置上就把影像處理完」變得容易,這是保護隱私很實用的設計方式。

小測驗:影像處理與隱私

1.

畫面差異偵測裡,「亮度差超過 30 才算變化」這個門檻主要是為了什麼?

2.

下面的程式會印出什麼?

a = [[50, 52], [49, 51]]
b = [[51, 200], [48, 210]]
changed = 0
for y in range(2):
    for x in range(2):
        if abs(b[y][x] - a[y][x]) > 30:
            changed += 1
print(changed)
3.

想在自習室統計「現在有沒有人在使用」,下面哪一種做法最符合隱私原則?

第 1 次作答

重點整理

  • 官方攝影機模組接在 CSI 接頭(15 針或 22 針,依板子而定);終端機用 rpicam-hello、rpicam-still、rpicam-vid,Python 用 Picamera2。
  • 影像在程式裡是二維陣列:img[列][行],高度在前、寬度在後;灰階每個像素 1 個位元組,RGB 3 個位元組。
  • 未壓縮的資料量=寬 × 高 × 每個像素的位元組數;彩色轉灰階用加權平均,資料量變成三分之一。
  • 門檻化把灰階變黑白;比較前後兩張畫面、數變化的像素,就能偵測移動,兩個門檻分別擋掉雜訊與零星變化。
  • 攝影機拍的是人:能不用影像就不用,要用就事先告知、在裝置上處理、只保留需要的結果。

下一課把感測器的數值定時寫進檔案與資料庫,讓資料可以留下來分析。

這一課完成了!
Next lesson:記錄感測資料:CSV 與 SQLite
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。