iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0
AI & Data

AIoT的藍藥丸與紅藥丸,你選哪個?系列 第 47

ASCII密碼:WebCam的解鎖(ASCII Code: WebCam Unlock)

  • 分享至 

  • xImage
  •  

前情提要

  在Day 25:監弒器.WebCam的陰謀中,你的室友們想要潛入女生宿舍送宵夜,還拉你下水,但當室友A──眼鏡仔破解門禁系統時,卻觸發了保護機制,結果你、眼鏡仔、毛帽男三人被困在一個女生房間裡。
  你們發現房間裡有一個盆栽,上面的樹莓正閃爍著紅色LED亮光,裡面還有一條線連接到DHT22溫溼度感測器。你們發現如果溫度跟濕度達到一定的標準,就會觸發繼電器。你們想盡辦法成功觸發繼電器後,發現這個繼電器連接到風扇的插頭,然後風扇開始緩緩轉動。
  你們在風扇後面找到一張紙條,是大漂亮給你們的提示。上面寫著要你們用WebCam攝影機拍照,然後用Python程式把照片轉換成ASCII碼,再用GPIO4接腳控制LED燈,讓它閃爍出ASCII碼。

Step 1:需求分析

輸入 / Input

  • (1) WebCam 攝影機的影像資料
  • (2) 一些 Python 模組,例如 PILnumpycv2

處理 / Process

  • (1) 將影像資料儲存成照片檔
  • (2) 調整大小和灰階化
  • (3) 將灰階圖像轉換成 ASCII碼
  • (4) 拼接成一個字串

輸出 / Output

  • (1) 輸出ASCII圖像,可以在終端機上顯示,也可以儲存成文字檔
  • (2) ASCII圖像是用不同亮度等級的ASCII字元來模擬原始影像的外觀

Step 2:演算法/流程圖

目的

  • 用Python程式碼來把WebCam攝影機的照片轉換成ASCII圖像
  • ASCII圖像是一種用文字符號來表示圖像的方法,就像是用字母和符號來畫出一張臉,例如:
   ,   ,
  (o,o)
   \_/
  -"-"-

Pseudo Code

    1. 安裝一些Python模組,例如PILnumpycv2,可以用pip指令來安裝。
      install PIL, numpy and cv2
    1. cv2模組來開啟WebCam攝影機,並且捕捉一張照片
    • (1) 引入cv2模組
      import cv2, PIL and numpy
    • (2) 建立一個VideoCapture物件,參數0表示使用第一個攝影機
      cap <- VideoCapture(0)
    • (3) 讀取一偵影像,ret是布林值,表示是否成功讀取,frame是影像資料
      ret, frame <- cap.read()
    • (4) 釋放VideoCapture物件
      cap.release()
    • (5) 將frame影像資料儲存成image圖片檔
      write frame to "webcam.jpg"
    1. PIL模組來讀取剛剛儲存的照片,並且調整大小和灰階化。
    • (1) 用PIL模組開啟image圖片檔
      img <- Image.open("webcam.jpg")
    • (2) 調整(縮小)圖片大小
      width, height <- img.size aspect_ratio <- height / width new_width <- 100 new_height <- aspect_ratio * new_width * 0.55 img <- img.resize(new_width, new_height)
    • (3) 將圖片灰階化
      img <- img.convert("L")
    1. numpy模組來將灰階圖像轉換成ASCII碼,用來儲存不同亮度等級的字元
    • (1) 建立一個ASCII 字元列表,從最暗到最亮
      chars <- ["@", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
    • (2) 將圖像的像素值轉換成 numpy 陣列
      pixels <- numpy.array(img)
    • (3) 將每個像素值對應到一個 ASCII 字元
      ascii_pixels <- numpy.array([chars[pixel / 25] for pixel in pixels.flatten()])
    • (4) 將 ASCII 陣列重塑成與圖像形狀相同
      ascii_pixels <- ascii_pixels.reshape(new_height, new_width)
    • (5) 將 ASCII 字元連接成一個字串
      ascii_image <- "\n".join("".join(row) for row in ascii_pixels)
    • (6) 印出 ASCII 圖檔
      print(ascii_image)
    1. 將ASCII圖像儲存成文字檔
      open "ascii_image.txt" as f write ascii_image to f close f

Step 3:程式撰寫

1. 安裝一些Python模組,例如PIL、numpy和cv2,可以用pip指令來安裝

pip install PIL numpy opencv-python
  • Python模組就像一個裡面有很多工具的工具箱,可以幫助使用者完成不同的任務。
  • PIL模組可以協助處理圖片檔案,numpy模組可以協助處理數字和矩陣,cv2模組可以協助使用攝影機和影像處理。
  • pip指令是提供解除安裝套件功能、支援Wheel格式套件。它就像是一個快遞員,可以把工具箱送到使用者的電腦。

2. 用cv2模組來開啟WebCam攝影機,並且捕捉一張照片

# 引入cv2模組
import cv2 
# 建立一個VideoCapture物件,參數0表示使用第一個攝影機
cap = cv2.VideoCapture(0)
# 讀取一偵影像,ret是布林值,表示是否成功讀取,frame是影像資料
ret, frame = cap.read()
# 釋放VideoCapture物件
cap.release()
# 將frame影像資料儲存成image圖片檔
cv2.imwrite("webcam.jpg", frame)
# 用PIL模組來讀取剛剛儲存的照片,並且調整大小和灰階化
from PIL import Image
  • 這個步驟就像是一個攝影師幫使用者拍下想要轉換成ASCII圖像的照片。
  • 引入cv2模組,就像是打開工具箱。
  • 建立一個VideoCapture物件,就像是拿出攝影機。
  • 讀取一偵影像,就像是按下快門。
  • 釋放VideoCapture物件,就像是關掉攝影機。
  • frame影像資料儲存成image圖片檔,就像是把照片洗出來。

3. 用PIL模組開啟image圖片檔

img = Image.open("webcam.jpg")
# 調整 縮小 圖片大小
width, height = img.size
aspect_ratio = height / width
new_width = 100
new_height = int(aspect_ratio * new_width * 0.55)
img = img.resize((new_width, new_height))
#  圖片灰階化
img = img.convert("L")
  • 這個步驟就像是一個厲害的修圖大師,可以幫使用者修照片。
  • PIL模組中引入Image類別,就像是拿出畫筆。
  • 打開image圖片檔,就像是把照片放在畫板上。
  • 調整照片的大小,就像是用剪刀剪掉多餘的部分。
  • 保持照片的長寬比,就像是不讓照片變形。
  • 把照片的寬度設為100像素,高度根據長寬比和一個係數0.55來計算,就像是用尺量出適合的尺寸。
  • 把照片轉換成灰階,就像是用黑白顏料把照片重新塗成灰色調。

4. 用numpy模組來將灰階圖像轉換成ASCII碼

import numpy as np
# 建立一個`ASCII 字元列表`,從最暗到最亮
chars = ["@", "#", "S", "%", "?", "*", "+", ";", ":", ",", "."]
# 將圖像的像素值轉換成 numpy 陣列
pixels = np.array(img)
# 將每個像素值對應到一個 ASCII 字元
ascii_pixels = np.array([chars[pixel // 25] for pixel in pixels.flatten()])
# 將 ASCII 陣列重塑成與圖像形狀相同
ascii_pixels = ascii_pixels.reshape(new_height, new_width)
# 將 ASCII 字元連接成一個字串
ascii_image = "\n".join("".join(row) for row in ascii_pixels)
# 印出 ASCII 圖檔
print(ascii_image)
  • 這段程式碼就像是一個解碼專家,可以幫使用者把灰階圖像轉換成ASCII圖像
  • 引入numpy模組,就像是打開另一個工具箱。
  • 建立一個從最暗到最亮的ASCII字元列表,就像是一個密碼表。
  • 把灰階圖像的每個像素值轉換成一個numpy陣列,就像是把照片切割成很多小方塊。
  • 把每個像素值對應到一個ASCII字元,就像是用密碼表來替換每個小方塊。
  • 用25來除以每個像素值,然後取整數部分,就可以得到一個0到10的索引值,再用這個索引值來選擇ASCII字元列表中的一個字元。
  • ASCII字元的陣列重新整理成跟圖像一樣的形狀,就像是把小方塊重新拼回原來的位置。
  • ASCII字元連接成一個字串,並且印出來,就可以看到ASCII圖像了。

5. 把ASCII圖像儲存成文字檔

with open("ascii_image.txt", "w") as f:
    f.write(ascii_image)
  • 這段程式碼就像是一個行政/文書,可以把ASCII圖像保存下來。
  • open函數來建立一個文字檔案,並且命名為ascii_image.txt。參數"w"表示要以寫入模式打開這個檔案。
  • with語句來管理這個檔案物件f,這樣可以確保檔案在使用完畢後會自動關閉。
  • write方法來將ascii_image字串寫入到f中,就可以把ASCII圖像儲存起來了。

參考資料 Reference


上一篇
Day 25:監弒器.WebCam的陰謀(Eye in the Sky: WebCam Intrigue)
下一篇
Day 26:繼電器的控制悖論(Paradox: Relay Control)
系列文
AIoT的藍藥丸與紅藥丸,你選哪個?62
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言