--- tags: 偏鄉醫療進度報告 --- # 2022/07/28 偏鄉醫療進度報告 > 林興政、劉彥汝 ## Heartpy相關資料整理 > https://hackmd.io/-TDtPG76T0aWMSs8z5EW2Q?view#Heartpy%E5%A5%97%E4%BB%B6%E4%BB%8B%E7%B4%B9%E5%8F%8A%E6%95%B4%E7%90%86 ### 小結: > 1. 之前了解可以透過移動平均線去標記最高點,但是有些點是並不是需要分析的 > 2. 為了過濾不必要的點,需要將心跳間隔的時間序列用==傅立葉變換==轉換成頻域去分析 > 3. Frequency Domain中的高頻區(HF 0.15-0.40赫茲)反映副交感神經的活性及低頻區(LF 0.04-0.15赫茲)同時受到交感與副交感神經系統的調控 -> 是否能判斷測試者當下的健康狀態? > 4. 預計採用[巴特沃斯濾波器(Butterworth)](https://zh.wikipedia.org/wiki/%E5%B7%B4%E7%89%B9%E6%B2%83%E6%96%AF%E6%BB%A4%E6%B3%A2%E5%99%A8)(目前正在看相關資料)來過濾不必要的peak > 5. 預計接下來要繼續完成最後的步驟與實際套用 ## 心跳分析(前處理) ### 1. 手指按壓在鏡頭上並打開手電筒的影片 -> 可以很明顯觀察到亮暗變化 [影片連結](https://youtu.be/OMMcrgaHm5E) > 1m01s ### 2. 把影片拆成一幀一幀的截圖並轉成灰階照片 -> 較好量化 > 總共有1451張 ```python import numpy as np import cv2 def get_images_from_video(video_name, time_F): video_images = [] vc = cv2.VideoCapture(video_name) c = 1 if vc.isOpened(): #判斷是否開啟影片 rval, video_frame = vc.read() else: rval = False while rval: #擷取影片至結束 rval, video_frame = vc.read() if(c % time_F == 0): #每隔幾幀進行擷取 video_images.append(video_frame) c = c + 1 vc.release() cv2.destroyAllWindows return video_images time_F = 1 # time_F越小,取樣張數越多 video_name = 'blood.mp4' # 影片名稱 video_images = get_images_from_video(video_name, time_F) # 讀取影片並轉成圖片 for i in range(0, len(video_images) - 1): # 顯示出所有擷取之圖片並儲存進screenshot bgr2gray = cv2.cvtColor(video_images[i], cv2.COLOR_BGR2GRAY) # 轉成灰階 -> 較好分析 # cv2.imshow('windows', bgr2gray) cv2.imwrite('./screenshot/output' + str(i + 1) + '.jpg', bgr2gray, [cv2.IMWRITE_JPEG_QUALITY, 100]) cv2.waitKey(1) cv2.destroyAllWindows ``` ![](https://i.imgur.com/UTojnPt.jpg) ### 3. 算出每一張照片的灰階平均值 ```python def average_pixel(blood_img): r, c = blood_img.shape[:2] average = 0 for row in blood_img: for column in row: # print(column) average = average + column average = average / (r * c) * 1.0 average = format(average, '.2f') # print('average = ', average) return average gray_value = [0] * 1452 for i in range(1, 1452): blood_img = cv2.imread('./screenshot/output' + str(i) + '.jpg', cv2.IMREAD_GRAYSCALE) #gray_value[i - 1] = int(float(average_pixel(blood_img))) * 10 gray_value[i - 1] = int(float(average_pixel(blood_img)) * 10) print('gray_value', i-1, ' = ', gray_value[i - 1]) ``` ![](https://i.imgur.com/bQ9adXx.png) ### 4. 利用matplot畫出波形圖,並加入移動平均線 ```python y_set = [0] * 1451 for i in range(1451): y_set[i] = i / 25.0 def plot_MA_curve(gray): # Data plt.figure(figsize = (20, 5), dpi=100,linewidth = 2) plt.plot(y_set, gray[:1451], label="gray") plt.title('Heart Rate Signal (60s)') plt.show() # MA 移動平均線 (15) plt.figure(figsize = (20, 5), dpi=100,linewidth = 2) df = pd.DataFrame(gray[:1451], y_set) MA = df.rolling(15).mean() plt.plot(MA, label="ma", color='red') plt.show() # MA 移動平均線 (50) plt.figure(figsize = (20, 5), dpi=100,linewidth = 2) df = pd.DataFrame(gray[:1451], y_set) MA = df.rolling(50).mean() plt.plot(MA, label="ma", color='orange') plt.show() # combine plt.figure(figsize = (20, 5), dpi=100,linewidth = 2) plt.plot(y_set, gray[:1451], label="gray") plt.title('Heart Rate Signal (60s)') df = pd.DataFrame(gray[:1451], y_set) MA = df.rolling(15).mean() plt.plot(MA, label="ma", color='red') df2 = pd.DataFrame(gray[:1451], y_set) MA2 = df2.rolling(50).mean() plt.plot(MA2, label="ma2", color='orange') plt.show() plot_MA_curve(gray_value) ``` ![](https://i.imgur.com/hC3gNvV.png) ![](https://i.imgur.com/I69CMq5.png) ![](https://i.imgur.com/NQ1HeSc.png) ![](https://i.imgur.com/uBa31Ph.png) ### 5. 設定好區間,選出其中的最高峰,就可以找到peaks了 ```python peaks = [] gap = 23 for i in range(0, 1450, gap): loc = np.where(gray_value[i:i+gap] == np.max(gray_value[i:i+gap])) print(i + int(loc[0][0]), ' : ', gray_value[int(loc[0][0])]) peaks.append(i + int(loc[0][0])) print('peaks: ', len(peaks)) def plot_annotate(gray, peaks): # Data plt.figure(figsize = (20, 5), dpi=100,linewidth = 2) plt.plot(y_set, gray[:1451], label="gray") plt.title('Heart Rate Signal (60s)') for i in range(len(peaks)): plt.plot(y_set[peaks[i]], gray[peaks[i]], 'ks') plt.show() plot_annotate(gray_value, peaks) ``` ![](https://i.imgur.com/gh4z8hc.png) ### 小結: > 1. 目前測試可以發現肉眼可見的明暗變化,轉成灰階並量化也可呈現明確的週期性 > 2. 目前遇到的問題是Heartpy還有很多相關資料還沒看完,目前還不知道如何將數據套入Heartpy > 3. 我們有試過求移動平均線的方法標記peak,不過有些點應該要捨棄 ## 未來方向與規劃 ![](https://i.imgur.com/Eo0Ho0D.png) 如果結果準確可以考慮[透過人臉來量測心跳](https://pdf.hanspub.org/HJBM20190300000_63336771.pdf) ![](https://i.imgur.com/Tf6yvrB.jpg) <br>