發表文章

目前顯示的是有「scipy」標籤的文章

DSP筆記6_功率頻譜密度 Power Spectral Density(PSD)_Periodogram(週期圖)_用scipy內建的periodogram跟最原始簡單的作法比較

圖片
事實上,在上一篇我們完全不依賴scipy手刻的PSD計算的python程式 它的演算法流程就是所謂的Periodogram(週期圖)最原始簡單的作法。 periodogram(週期圖)是一種用來估計訊號功率頻譜密度 使用單一區段全部資料來計算 PSD 雖然速度快,但具有對雜訊敏感且變異數較大的限制。 顯示訊號的功率如何分布在不同頻率上。 常用於signal processing、vibration analysis、PPG/EEG/ECG 分析 在數學上,對於一個長度為  N  的離散時間訊號  x [ n ] : 會用以下數學式子表示週期圖功率頻譜密度 推導過程 Step1.計算離散傅立葉轉換(實際應用場景中,可用快速傅立葉轉換更有效率做出來。) Step2.計算功率譜,也就是計算「振幅(幅度大小)平方」 Step3.除以樣本數N做正規化 原始periodogram功率頻譜密度 提供 每個樣本的功率估計值 。 原始 periodogram就是 最初版本、最簡單的 PSD 估計方法。 在實務上,通常使用 FFT 來有效率地進行計算。 原始periodogram功率頻譜密度特性 變異數 : 高;即使增加 \(N\),變異數也不會下降,因此結果通常會比較多雜訊干擾。 偏差(Bias)、頻譜洩漏(Spectral Leakage): 在有限長度訊號中的不連續現象,會使功率擴散到鄰近的頻率。 解析度(Resolution) Δ f = f s N ;較長的訊號可以提升解析度。 一致性(Consistency): 原始 periodogram是不一致的估計量 原始periodogram功率頻譜密度限制 High variance : 峰值會產生波動 Spectral leakage : 有限長度資料會造成頻譜能量向周圍頻率擴散。 Poor consistency : N→∞時,原始 periodogram 不會收斂。 Trade-off between bias and resolution : 加窗(Windowing)可以降低頻譜洩漏,但會使頻譜峰值變寬。 常見改善方法 加窗(Windowing): Hann、Hamming、Blackman 視窗可降低 頻譜洩漏(spectral leakage) 。 Welch 方法(Welch'...

Python透過Scipy的convolve實踐Sliding Window Detrend

圖片
  一般數位訊號如果出現某種逐漸遞增、遞減的趨勢 通常都需要做一個所謂去趨勢化(detrend)的前置處理。 scipy內建的detrend函數(scipy.signal.detrend) https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.detrend.html 是採用「簡單迴歸法」(最小平方法的線性迴歸)的移除趨勢方法 從時間序列資料中移除趨勢成分的函數,透過執行線性迴歸(嚴格來說是簡單迴歸)來移除趨勢。 演算法步驟 步驟 1:計算線性趨勢 針對資料使用最小平方法執行線性迴歸,也就是以直線近似資料的趨勢。 透過線性迴歸,可取得表示資料趨勢之直線的斜率與截距。 步驟 2:移除趨勢 將計算出的線性趨勢(直線)從原始資料中扣除。 如此一來,便可從資料中移除長期變動成分,僅保留雜訊成分。 和這次要實作的sliding window 方法不同 以下是藉由scipy.signal內建的convolve函數實作的滑動視窗去趨勢法 https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve.html#scipy.signal.convolve import numpy as np import matplotlib.pyplot as plt from scipy.signal import convolve # ========================================== # 1. 產生模擬訊號 (弦波 + 向上飄移的趨勢 + 雜訊) # ========================================== t = np.linspace( 0 , 10 , 150 ) original_trend = 0.5 * t # 緩慢向上的線性趨勢 signal_data = np.sin( 2 * np.pi * 1.0 * t) + original_trend + np.random.normal( 0 , 0.2 , 150 ) # 2. 執行滑動視窗去趨勢 (使用卷積法) # ==================...

rPPG訊號(脈搏波)獲取測試程式_透過臉部影片額頭部位亮度變化_來擷取生理訊號以測量心率

圖片
  脈搏波是隨心臟跳動而變化的血流量。回憶過去若曾去過醫院做健檢,你應該有看過類似感測器夾在手指上,測量出像山峰一般的波形,那就是脈搏波。脈搏波是利用血液中的血紅素會大量吸收綠光的特性。 市面上很多運動手錶,如今也已涵蓋心律、血氧測量等諸多身體指數量測,多半採用到所謂脈搏感測技術,常見的rPPG藉由反射行脈波測量手段。 用綠光的原因在於能被淺層靜脈中的血紅素部分吸收,剩餘沒被吸收的綠光則會反射回來,有利於被手錶感測器量測。 至於紅光部分則穿透能力較強,能反射回來被感測器分析的比例較少,而不利於運動時全程心率量測。 運動手錶主要就是利用血紅素密度變化,去間接推斷人體心率變化。每當人體心臟收縮跟舒張,血管中的血紅素密度就會有密度起伏。若經過手錶等感測裝置的血紅素密度高,被偵測到的綠光就少。反之,若經過的血紅素密度低,則被偵測到的綠光就多。 而從視訊或是影片中測量脈搏波的原理也是一樣的。一般電腦中視訊、影片有分為RGB三種顏色通道不同的光線強度,以 0 到 255 個階度的亮度值進行記錄。 我們可以拍攝或擷取皮膚表面ROI所得視訊影像中的綠色成分光線強度,根據心臟跳動引起的血紅素變化量而產生變化。 同理可得知,拍攝皮膚表面的視訊影像中,綠色成分的變動即為脈搏波。 為了讓血紅素增加時訊號隨之變大,脈搏波訊號會使用從最大亮度值(255)來減去綠色亮度值後所得的數值。透過計算一分鐘內出現多少次脈搏波,也就是測量一分鐘內心臟跳動的次數,就能從視訊影像中測量出心率。 拿一個10秒的公開測試影片作測試 Stage1.先定位額頭部位ROI import cv2 import numpy as np from scipy import signal import matplotlib.pyplot as plt movie = "face.mp4" video_path = ( "C:/img/{}" .format(movie)) cap = cv2.VideoCapture(video_path) cap.set(cv2.CAP_PROP_POS_FRAMES, 0 ) roi = ( 147 , 69 , 340 , 178 ) ret, frame_bgr = cap.read() #先只讀取第一frame i...