opencv 手选roi区域_基于opencv的眼动跟踪

本文介绍了如何利用OpenCV库和Python来追踪眼球运动。首先,文章探讨了眼睛的构造,包括瞳孔、虹膜和巩膜。接着,通过选择ROI(感兴趣区域)来限制检测范围。然后,通过灰度转换和阈值处理,突出瞳孔,并找到最大的轮廓以确定瞳孔位置。最终,文章展示了如何绘制瞳孔边界框并在屏幕上显示结果,从而实现眼球运动的检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击上方"蓝色小字"关注我呀

97c957ba3acf8851100f44fc1d44dc4a.png

本文翻译自胡子哥哥博客,原文地址:

https://pysource.com/2019/01/04/eye-motion-tracking-opencv-with-python/#

有视频版本,可以去上面链接看英文版,也可以去B站关注【周旋学opencv】看我搬运的加了中英双字幕的版本。

下面是正文。

了解眼的构造

在进入图像处理的细节之前,让我们稍微研究一下眼睛,让我们想想有什么可能的解决方案。

在下面的图片中我们看到一只眼睛。眼睛由三个主要部分组成:

  • 瞳孔——中间的黑色圆圈

  • 虹膜——更大的圆圈,不同的人可以有不同的颜色

  • 巩膜——它总是白色的

1cf2b461350827f29a2a9a4afa406888.png

现在我们来编写第一部分的代码,在第一部分中我们导入眼睛移动的视频。之后我们会考虑跟踪运动的解决方案。

我们导入Opencv和numpy库,加载视频“eye_recording”。然后我们把它放入一个循环中,这样我们就可以循环视频的帧并处理一幅一幅的图像。

import cv2import numpy as npcap = cv2.VideoCapture("eye_recording.flv")while True:    ret, frame = cap.read()    if ret is False:        break

现在让我们选择一个Roi(感兴趣的区域)。通过这种方法,我们将检测范围限制在瞳孔、虹膜和巩膜上,并切除了所有不必要的东西,如睫毛和眼睛周围的区域。

roi = frame[269: 795, 537: 1416]rows, cols, _ = roi.shapegray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0)

现在我们可以更深入地寻找探测运动的正确方法。让我们看看眼睛可能拥有的所有方向(如下图所示),然后找出它们之间的共同点和不寻常之处。

d0721228f3e276b3d258ea41d47fa27c.png

从这幅图中我们能了解到什么?从左边开始,我们可以看到巩膜覆盖了瞳孔和虹膜指向的另一边。当眼睛直视时,左右两边的巩膜都很平衡。

检测运动

对于检测,我们可以使用不同的方法,聚焦于巩膜、虹膜或瞳孔。我们要用最简单的方法,也可能是最好的解决方案。

我们只关注瞳孔。通过将图像转换为灰度格式,我们将看到瞳孔总是比眼睛的其他部分更暗。不管眼睛在看什么,不管人的巩膜是什么颜色。

我们来做这个。首先进行灰度变换

f17c52b7bbbf39363a2391328722df57.png

然后找到阈值,只提取瞳孔。

    gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)    gray_roi = cv2.GaussianBlur(gray_roi, (7, 7), 0)    _, threshold = cv2.threshold(gray_roi, 3, 255, cv2.THRESH_BINARY_INV)

bd70b26906a72caf714ec15ada9d8f2f.png

从阈值我们找到了轮廓。我们简单地去除所有的噪音,选择面积最大的元素(应该是瞳孔),然后忽略其余的。

   _, contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)    contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)    for cnt in contours:        (x, y, w, h) = cv2.boundingRect(cnt)        #cv2.drawContours(roi, [cnt], -1, (0, 0, 255), 3)        cv2.rectangle(roi, (x, y), (x + w, y + h), (255, 0, 0), 2)        cv2.line(roi, (x + int(w/2), 0), (x + int(w/2), rows), (0, 255, 0), 2)        cv2.line(roi, (0, y + int(h/2)), (cols, y + int(h/2)), (0, 255, 0), 2)        break

最后我们把所有的东西都显示在屏幕上。

    cv2.imshow("Threshold", threshold)    cv2.imshow("gray roi", gray_roi)    cv2.imshow("Roi", roi)    key = cv2.waitKey(30)    if key == 27:        breakcv2.destroyAllWindows()

ce3b249da242629404b3f9448f6a160b.gif

THE  END

今天就到这里啦。点击下方箭头可以去评论交流哈。

cc6fcc624888da1c20e5a11444bfb21e.pnga6b315d02c84107d4785b42c5beafba5.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值