目前有幾個方案,在下面:
1.電極式眼動追蹤:這種技術通過在眼球周圍放置電極來測量眼睛的運動。它可以提供非常高的準確性和分辨率,但需要接觸眼球,因此不太適合長時間使用或需要無接觸測量的應用場景。2.紅外線眼動追蹤:這種技術使用紅外線攝像機來觀察眼睛的位置和運動。由于它不需要接觸眼球,因此非常適合長時間使用和需要無接觸測量的應用場景。它的準確性和分辨率通常比電極式眼動追蹤低。3.磁共振眼動追蹤:這種技術使用磁共振成像來測量眼球的位置和運動。它可以提供非常高的空間分辨率,但時間分辨率較低,因此不太適合研究快速眼動的過程。4.可穿戴式眼動追蹤:這種技術使用小型傳感器或攝像頭,可以放置在眼鏡或頭盔上,可以隨身攜帶,適用于移動應用場景。但是由于可穿戴設備的尺寸和重量限制,其準確性和分辨率通常較低。5.視網膜追蹤:這種技術利用視網膜圖像來跟蹤眼球的位置和運動。它可以提供非常高的準確性和分辨率,但只能在特定的實驗條件下使用,例如黑暗環境下觀察單一的點光源。以我目前念的這個書,我還是用視覺方案來實現:
1.特征提取:選擇適當的特征來描述眼睛的形狀、顏色、紋理等信息。例如,可以使用Haar級聯檢測器來提取眼睛的輪廓特征,或者使用顏色分布模型來提取眼球的顏色特征。這步主要是傳統的2.目標檢測:使用機器學習或計算機視覺技術來檢測眼睛的位置和方向。因為直接目標檢測是識別不準的,現實太復雜了。可以使用級聯分類器或支持向量機(SVM)來識別眼睛的位置和方向,或者使用卷積神經網絡(CNN)來分類眼動類型。3.跟蹤和估計:根據檢測結果,使用跟蹤和估計算法來跟蹤眼睛的位置和運動軌跡。在捕捉的基礎上開始進行跟蹤,持續的來捕獲。使用卡爾曼濾波器或粒子濾波器來估計眼睛的位置和速度,或者使用光流算法來估計眼球的運動軌跡。4.數據分析:根據眼動追蹤的結果,進行數據分析和可視化??梢杂嬎阕⒁朁c的位置、持續時間和注視次數等統計信息,或者使用熱力圖和軌跡圖來可視化眼動數據。這個也是這次要寫的一個點。我們在這里主要是直接給出ROI的區域減少算力。
在預處理步驟中,使用了高斯平滑和邊緣檢測來增強圖像特征
在特征提取步驟中,使用了霍夫圓變換來檢測圓形區域
在目標檢測步驟中,找到最大的圓形區域作為眼球,并在圖像中標記出來
太簡單了家人們!
但是這個程序太簡單了,就是一個找特征啥的,有點傻。這次換個庫:
Dlib是一個C++編寫的機器學習庫,提供了用于人臉檢測、關鍵點檢測、姿態估計等任務的算法,其中也包括用于眼動追蹤的算法。Dlib同樣也提供了Python接口,可以在Python中使用Dlib的算法實現眼動追蹤。dlib提供一個方法可將人臉圖片數據映射到128維度的空間向量,如果兩張圖片來源于同一個人,那么兩個圖片所映射的空間向量距離就很近,否則就會很遠。因此,可以通過提取圖片并映射到128維空間向量再度量它們的歐氏距離(Euclidean distance)是否足夠小來判定是否為同一個人。我不要人我就要眼睛。
上次覺得CMake礙眼,卸載了
稍等不知道多久,反正我吃了個橘子
python.exe -m pip install --upgrade pip
更新一下
安裝成功了
這個就是里面的dat文件,68個關鍵點
先找臉,再找眼,合理!
簡單的轉下顏色,然后直接找
dlib 庫提供了兩個用于人臉檢測的功能。
第一個是HOG+線性SVM人臉檢測器,另一個是深度學習MMOD CNN人臉檢測器。
反正就是找一下面部的區域:
這些代碼是再找眼部的位置
在范圍之內就可以了
有極值坐標嘎嘎算
接著進一步給出瞳孔的坐標
2.0~8.0mm之間瞳孔大小是指虹膜中央的一圓孔的直徑,受光線、年齡、人種、屈光狀態、目標遠近和情緒等因素影響,正常范圍在2.0~8.0mm之間。瞳孔在強光下縮小,在黑暗下擴大,這是人體的正常生理反應。瞳孔大小不一致或對光反應異??赡苁悄X部或眼部疾病的征兆。
我考你,你遇到這種情況怎么寫?
先給外圈的大圓套上
再處理瞳孔
多數情況下,我們是要實時的檢測的:
來一段從攝像頭捕獲的代碼
祖傳代碼不能丟
更實用性的是兩個攝像頭來捕捉眼動:
這個寫的比較呆逼,不過我在后面會有進行封裝
現在是彈出兩個框來輸出圖像,趕緊不好看捏!我們來讓他并排排列!
使用OpenCV中的cv2.hconcat()函數將兩個視頻幀水平合并在一起,并使用cv2.imshow()函數將合并后的視頻幀顯示出來。
就很簡單,其實這里就變成一個合并橫向排列的視頻組,但是在處理流程上面有問題,應該先單一處理,最后合并結果。
封裝好啦!(有點傻逼哦~)
繼續封裝,注意視頻流
工程問題的話,上面的代碼還是太慢了,讓我來加一點多線程的魔法!
設計兩個線程分別處理左右眼視頻幀的讀取和合并:
隊列無疑是最合適的數據結構
合并函數也是如此,因為圖像這種處理的方式就適合隊列
這個是提前設置好的
標準的流程
這個就是線程的啟動了,然后一個循環不停的合并
也可以加一個日志的功能,直接寫到最上面就行
現在的程序一點也不裝逼,如果可以加一些文字什么的,就更好啦!
要把視頻流封裝成一個類,然后里面也是多線程處理
在下面調用的時候,就是實例化代碼
這里就顯示一個左眼的FPS信息疊加
代碼中,putText函數用于將幀率信息添加到視頻幀的左上角。其中,cv2.FONT_HERSHEY_SIMPLEX指定了字體類型,1指定了字體大小,(255, 255, 255)指定了字體顏色,2指定了字體線寬。
一方面顯示是可視化,另一方面我們需要保存具體的眼動數據來后處理。可以在程序中添加一個函數來提取圓形框的坐標信息,并將它們保存到一個文件中。
這個是簡單版本
eye_data 是一個包含眼動信息的列表,每個元素都是一個二元組,表示眼睛的坐標。在循環中,將每個元素寫入文件中,每個坐標之間用逗號分隔,每行結束后添加一個換行符。
假設圓形框的半徑為 r,圓心坐標為 (x, y),那么可以使用 OpenCV 中的 circle 函數來繪制圓形框。在繪制圓形框時,同時將圓心坐標和半徑信息保存到一個列表中:在每次繪制圓形框時,將圓心坐標和半徑信息添加到 eye_data 列表中。最后,可以將 eye_data 中的信息保存到一個文本文件中:
現在就是一個較為完善的函數了
再讓我封裝一下:
在視頻幀上繪制眼球圓形框,并返回圓形框的坐標信息
這個是信息保存的函數
目前實現的功能挺多的了,現在來寫一個GUI吧!
就兩個線程就行
初始化是捕獲線程,在run函數里面進行了顏色的轉換
使用定時器來更新幀率信息
這些都簡單
都比較簡單吧?
完整代碼我放在Github上面了。
我們拿到了保存的數據,想重新把他們展示出來。假設眼動數據文件是一個文本文件,每行包含兩個數字,分別代表左右眼的坐標。
使用matplotlib庫中的plot函數來繪制左右眼的坐標。下面是一個簡單的示例代碼,繪制左眼的x坐標和y坐標:
來封裝一下
好啦!
再實現一個功能吧!
在播放的時候點按鼠標就可以捕捉當前播放的數據而且在圖片上面標注時間戳。
程序應該這樣寫:
1.讀取眼動數據文本文件,將數據存儲到一個列表中。2打開視頻文件,并讀取第一幀。3.在窗口上顯示第一幀圖像。4.進入循環,依次讀取眼動數據列表中的每個數據。5.當用戶按下鼠標時,記錄當前的時間戳,并在圖像上繪制一個圓形或者其他標記,標記當前時間戳。6.在窗口上顯示標記后的圖像。
讀取
后面的功能分開寫不好,這里合在一起寫。
先讀取視頻幀,然后就是獲取幀率,創建一個窗口
能看懂吧?
這個就是繪制標記
許久不用Python,然后壞了,各種運行出錯,VSCode都撲街了,哭死,不知道咋辦了。
解決不了
重新安裝就好啦!
嚶嚶嚶,沒看上
c:/Users/yunswj/AppData/Local/Programs/Python/Python310/python.exe -m
pip install ipykernel -U --user --force-reinstall
pip install opencv-python
https://cmake.org/download/
import cv2
import threading
class VideoStream:
def __init__(self, src=0, width=640, height=480, fps=30):
self.stream = cv2.VideoCapture(src)
self.stream.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.stream.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
self.stream.set(cv2.CAP_PROP_FPS, fps)
self.width = int(self.stream.get(cv2.CAP_PROP_FRAME_WIDTH))
self.height = int(self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.fps = int(self.stream.get(cv2.CAP_PROP_FPS))
self.status = False
self.frame = None
def start(self):
if self.status:
return None
self.status = True
threading.Thread(target=self.update, args=()).start()
def update(self):
while self.status:
_, self.frame = self.stream.read()
def read(self):
return self.frame
def stop(self):
self.status = False
def main():
# 創建兩個VideoStream對象,用于捕獲左右眼視頻流
left_cam = VideoStream(0)
right_cam = VideoStream(1)
# 開始捕獲視頻流
left_cam.start()
right_cam.start()
# 創建OpenCV窗口用于顯示視頻流
cv2.namedWindow("Video Stream", cv2.WINDOW_NORMAL)
while True:
# 讀取左右眼視頻流
left_frame = left_cam.read()
right_frame = right_cam.read()
# 在視頻流上添加幀率信息
left_fps_text = f"FPS: {left_cam.fps}"
right_fps_text = f"FPS: {right_cam.fps}"
cv2.putText(
left_frame,
left_fps_text,
(10, 30),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(255, 255, 255),
2,
)
cv2.putText(
right_frame,
right_fps_text,
(10, 30),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(255, 255, 255),
2,
)
# 合并左右眼視頻流并顯示
merged_frame = cv2.hconcat([left_frame, right_frame])
cv2.imshow("Video Stream", merged_frame)
# 按'q'鍵退出
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# 停止視頻流捕獲
left_cam.stop()
right_cam.stop()
# 關閉OpenCV窗口
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
審核編輯 :李倩
-
傳感器
+關注
關注
2548文章
50678瀏覽量
752018 -
檢測器
+關注
關注
1文章
860瀏覽量
47651 -
機器學習
+關注
關注
66文章
8377瀏覽量
132410 -
眼動追蹤
+關注
關注
0文章
18瀏覽量
6739
原文標題:開發一個完整的眼動追蹤應用-Python版
文章出處:【微信號:TT1827652464,微信公眾號:云深之無跡】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論