在 numpy 中加速矢量化眼球追踪算法

2024-01-10

我正在尝试实现 Fabian Timm 的眼球追踪算法 [http://www.inb.uni-luebeck.de/publikationen/pdfs/TiBa11b.pdf] http://www.inb.uni-luebeck.de/publikationen/pdfs/TiBa11b.pdf%5D(在这里找到:[http://thume.ca/projects/2012/11/04/simple-accurate-eye-center-tracking-in-opencv/] http://thume.ca/projects/2012/11/04/simple-accurate-eye-center-tracking-in-opencv/%5D)在 numpy 和 OpenCV 中我遇到了障碍。我认为我已经对我的实现进行了足够的矢量化,但它仍然不够快,无法实时运行,而且它检测学生的准确度没有我希望的那么高。这是我第一次使用 numpy,所以我不确定我做错了什么。

def find_pupil(eye):
    eye_len = np.arange(eye.shape[0])
    xx,yy = np.meshgrid(eye_len,eye_len) #coordinates
    XX,YY = np.meshgrid(xx.ravel(),yy.ravel()) #all distance vectors
    Dx,Dy = [YY-XX, YY-XX] #y2-y1, x2-x1 -- simpler this way because YY = XXT
    Dlen = np.sqrt(Dx**2+Dy**2)
    Dx,Dy = [Dx/Dlen, Dy/Dlen] #normalized

    Gx,Gy = np.gradient(eye)
    Gmagn = np.sqrt(Gx**2+Gy**2)

    Gx,Gy = [Gx/Gmagn,Gy/Gmagn] #normalized
    GX,GY = np.meshgrid(Gx.ravel(),Gy.ravel())

    X = (GX*Dx+GY*Dy)**2
    eye = cv2.bitwise_not(cv2.GaussianBlur(eye,(5,5),0.005*eye.shape[1])) #inverting and blurring eye for use as w
    eyem = np.repeat(eye.ravel()[np.newaxis,:],eye.size,0)
    C = (np.nansum(eyem*X, axis=0)/eye.size).reshape(eye.shape)

    return np.unravel_index(C.argmax(), C.shape)

以及其余代码:

def find_eyes(face):
    left_x, left_y = [int(floor(0.5 * face.shape[0])), int(floor(0.2 * face.shape[1]))]
    right_x, right_y = [int(floor(0.1 * face.shape[0])), int(floor(0.2 * face.shape[1]))]
    area = int(floor(0.2 * face.shape[0]))
    left_eye = (left_x, left_y, area, area)
    right_eye = (right_x, right_y, area, area)

    return [left_eye,right_eye]



faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
video_capture = cv2.VideoCapture(0)

while True:
    # Capture frame-by-frame
    ret, frame = video_capture.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags=cv2.CASCADE_SCALE_IMAGE
    )

    # Draw a rectangle around the faces
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
        roi_gray = gray[y:y+h, x:x+w]
        roi_color = frame[y:y+h, x:x+w]
        eyes = find_eyes(roi_gray)
        for (ex,ey,ew,eh) in eyes:
            eye_gray = roi_gray[ey:ey+eh,ex:ex+ew]
            eye_color = roi_color[ey:ey+eh,ex:ex+ew]
            cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(255,0,0),2)
            px,py = find_pupil(eye_gray)
            cv2.rectangle(eye_color,(px,py),(px+1,py+1),(255,0,0),2)

    # Display the resulting frame
    cv2.imshow('Video', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything is done, release the capture
video_capture.release()
cv2.destroyAllWindows()

您可以执行许多保存复制元素的操作,然后通过在创建单例维度后直接执行数学运算来执行一些数学运算,这将允许NumPy broadcasting http://docs.scipy.org/doc/numpy-1.10.1/user/basics.broadcasting.html。因此,有两个好处:即时操作可以节省工作空间内存并提高性能。另外,最后我们可以替换nansum使用简化版本进行计算。因此,考虑到所有这些哲学,这里有一种修改后的方法 -

def find_pupil_v2(face, x, y, w, h):    
    eye = face[x:x+w,y:y+h]
    eye_len = np.arange(eye.shape[0])

    N = eye_len.size**2
    eye_len_diff = eye_len[:,None] - eye_len
    Dlen = np.sqrt(2*((eye_len_diff)**2))
    Dxy0 = eye_len_diff/Dlen 

    Gx0,Gy0 = np.gradient(eye)
    Gmagn = np.sqrt(Gx0**2+Gy0**2)
    Gx,Gy = [Gx0/Gmagn,Gy0/Gmagn] #normalized

    B0 = Gy[:,:,None]*Dxy0[:,None,:]
    C0 = Gx[:,None,:]*Dxy0
    X = ((C0.transpose(1,0,2)[:,None,:,:]+B0[:,:,None,:]).reshape(N,N))**2

    eye1 = cv2.bitwise_not(cv2.GaussianBlur(eye,(5,5),0.005*eye.shape[1]))
    C = (np.nansum(X,0)*eye1.ravel()/eye1.size).reshape(eye1.shape)

    return np.unravel_index(C.argmax(), C.shape)

There's one repeat still left in it at Dxy. It might be possible to avoid that step and Dxy0 could be fed directly into the step that uses Dxy to give us X, but I haven't worked through it. Everything's converted to broadcasting based!

运行时测试和输出验证 -

In [539]: # Inputs with random elements
     ...: face = np.random.randint(0,10,(256,256)).astype('uint8')
     ...: x = 40
     ...: y = 60
     ...: w = 64
     ...: h = 64
     ...: 

In [540]: find_pupil(face,x,y,w,h)
Out[540]: (32, 63)

In [541]: find_pupil_v2(face,x,y,w,h)
Out[541]: (32, 63)

In [542]: %timeit find_pupil(face,x,y,w,h)
1 loops, best of 3: 4.15 s per loop

In [543]: %timeit find_pupil_v2(face,x,y,w,h)
1 loops, best of 3: 529 ms per loop

看来我们正在接近8x加速!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 numpy 中加速矢量化眼球追踪算法 的相关文章

  • 当内存排序放宽时,C++ 延迟会增加

    我在 Windows 7 64 位 VS2013 x64 发行版 上尝试内存排序 我想使用最快的同步来共享对容器的访问 我选择了原子比较和交换 我的程序产生两个线程 写入器推送到向量 读取器检测到这一点 最初我没有指定任何内存顺序 所以我假
  • Scalar(0,255,0) 在 opencv 中没有给出绿色线

    我正在尝试在图像上绘制渐变线 我希望我的线条是绿色的 并且我使用标量 0 255 0 不过 我只得到黑色 对于 Scalar 0 0 0 我也变黑了 对于 Scalar 255 255 255 我得到白色 但任何组合都没有其他颜色 部分代码
  • 为什么 Sleep() 会使后续代码减慢 40 毫秒?

    我最初是在 coderanch com 上询问这个问题的 所以如果您尝试在那里帮助我 谢谢 并且不必重复这个努力 不过 coderanch com 主要是一个 Java 社区 而且 经过一些研究 这似乎确实是一个 Windows 问题 因此
  • 在 pandas 中按范围加入/合并的最佳方式

    我经常使用 pandas 通过范围条件进行合并 连接 例如 如果有 2 个数据框 A A id A 值 B B id B 低 B 高 B 名称 它们很大并且大小大致相同 假设每个有 2M 条记录 我想在 A 和 B 之间进行内部联接 因此
  • 动态规划的复杂组合条件

    我正在探索动态规划设计方法如何与问题的底层组合属性相关 为此 我正在查看的规范实例硬币找零问题 Let S d 1 d 2 d m and n gt 0是请求的金额 我们可以用多少种方式相加n仅使用中的元素S 如果我们遵循一个动态规划如果要
  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • 循环中的递归算法复杂度(运行时间)

    我想了解您对如何检测以下递归算法的 T n 运行时间 的意见 Charm 是一种用于发现事务数据库中频繁闭项集的算法 频繁闭项集列表是在一组交易 tids 中多次出现的频繁项 例如面包和牛奶是经常一起购买的物品 它们是通过将索引为 i 的当
  • 更快地评估从右到左的矩阵乘法

    我注意到以二次形式评估矩阵运算右到左明显快于左到右在 R 中 取决于括号的放置方式 显然它们都执行相同的计算量 我想知道为什么会这样 这与内存分配有什么关系吗 A 5000 5000 B 5000 2 A matrix runif 5000
  • 是否可以强制浮点数的指数或有效数匹配另一个浮点数(Python)?

    这是我前几天试图解决的一个有趣的问题 是否可以强制一个的有效数或指数float与另一个人一样float在Python中 出现这个问题是因为我试图重新调整一些数据 以便最小值和最大值与另一个数据集匹配 然而 我重新调整后的数据略有偏差 大约小
  • 对产品列表进行分类的算法? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个代表或多或少相同的产品的列表 例如 在下面的列表中 它们都是希捷硬盘 希捷硬盘 500Go 适用于笔记本电脑的希捷硬盘 120
  • 缓存感知树的实现

    I have a tree where every node may have 0 to N children 用例是以下查询 给定指向两个节点的指针 这些节点是否位于树的同一分支内 Examples q 2 7 gt true q 5 4
  • 使用 numpy 加速 for 循环

    下一个 for 循环如何使用 numpy 获得加速 我想这里可以使用一些奇特的索引技巧 但我不知道是哪一个 这里可以使用 einsum 吗 a 0 for i in range len b a numpy mean C d e f b i
  • 如何找到给定顶点的所有多边形?

    我有一个顶点列表 并且我知道它们之间的连接 我试图找到顶点的所有多边形形状 这些多边形形状不应重叠 我做了一些研究 我认为如果我可以顺时针 或逆时针 没有区别 遍历顶点 我可以检测多边形形状 因此 我寻找顺时针遍历顶点的解决方案 我发现了一
  • opencv cmake安装的python包路径错误

    我一直在尝试遵循 opencv 安装步骤pyimagesearch com http www pyimagesearch com 2015 06 15 install opencv 3 0 and python 2 7 on osx 与虚拟
  • OpenCV warpPerspective 性能缓慢

    在我的应用程序中 我跟踪一个物体 到达它的地方corners都在这个框架中 我发现它之间的单应性corners从最后一帧开始和 当前帧 使用单应性来做perspectiveTransform on the corners在当前帧中找到 得到
  • 通过保留和复制来复制向量,还是通过创建和交换来复制向量更有效? [复制]

    这个问题在这里已经有答案了 我正在尝试有效地复制向量 我看到两种可能的方法 std vector
  • 在小于 O(N) 的时间内找出点是否位于 N 个(可能重叠)矩形之一内

    我有一个图像 我想在鼠标移动到某些矩形区域时显示工具提示 矩形区域最多可达 1000 个 但是 仅检查每个矩形中是否有点 时间复杂度为 O N 导致移动鼠标时界面无响应 有没有办法在小于 O N 的时间内完成它 我可以预先对矩形进行排序 我
  • 地图与星图的性能?

    我试图对两个序列进行纯Python 没有外部依赖 逐元素比较 我的第一个解决方案是 list map operator eq seq1 seq2 然后我发现starmap函数来自itertools 这看起来和我很相似 但事实证明 在最坏的情
  • 绘图:仅保留最相关的数据

    为了节省带宽并且不用自己生成图片 图表 我计划使用 Google 的图表 API http code google com apis chart http code google com apis chart 它的工作原理是简单地发出一个
  • Cython:为什么 size_t 比 int 快?

    更改某些 Cython 变量的类型int输入size t可以显着减少某些功能的时间 30 但我不明白为什么 例如 cimport numpy as cnp import numpy as np def sum int cnp int64 t

随机推荐

  • 如何将输入值传递到 Angular 6 中表单提交的函数中?

    所以当我按回车键时我的代码就可以工作 它运行performSearch函数成功 但是当我尝试通过点击提交按钮运行该函数时 出现错误 无法读取未定义的属性错误 这是我的代码
  • 如何用 Any 类型来包装价值?使用@Parcelize

    我在尝试将值放入 Any 类型时遇到问题 放入包裹中 我正在使用 kotlinx android parcel 中的 Parcelize Lint 警告我并提示要添加的消息 RawValue 但这没有帮助 我有 android os Bad
  • 表单元素的 action 属性可以为空吗?

    从 HTML5 开始 广泛使用和推荐的action 是无效的 HTML 从规格来看 如果指定了 action 和 formaction 内容属性 则必须具有 一个有效 URL 的值 那么正确的方法是什么action属性指向当前页面 我目前正
  • 在R中快速读取多个文件

    我有超过 10000 个 csv 文件 我需要对每个 csv 文件的每一列进行快速傅里叶变换 我可以访问 1000 个核心 最快的方法应该是什么 目前我有一个 for 循环按顺序读取每个文件并使用apply data 2 FFT 功能 我该
  • 如何确保应用程序只有一份副本在运行? [复制]

    这个问题在这里已经有答案了 可能的重复 防止 Linux 上出现多个进程实例 https stackoverflow com questions 2964391 preventing multiple process instances o
  • 如何在 Spring 中检查 Request Scope 的可用性?

    我正在尝试设置一些代码 如果 spring 的请求范围可用 这些代码将以一种方式运行 如果所述范围不可用 则以另一种方式运行 所涉及的应用程序是一个 Web 应用程序 但有一些 JMX 触发器和计划任务 即 Quartz 也会触发调用 E
  • 如何在 TypeScript 中将项目推送到 [string]

    我想将项目添加到 string 但以下代码在 param push 语句处失败 EDIT declare var sqlitePlugin any var query string SELECT FROM items var param s
  • 请求位置更新的频率超过 5 秒(Android Fused 位置)

    我正在制作一个实时位置监听应用程序 我需要调用位置更新每 3 秒一次 I use Fused https developer android com google play services location html地点 我的间隔设置为
  • 具有多个条件主题的 Firebase API 调用

    我在调用 FCM API 时遇到一个悲惨的问题 简而言之 当我使用以下方式调用 API 时 URL https fcm googleapis com fcm send Content Type application json Author
  • 祖先查询解析错误

    我正在努力让我的祖先查询 https developers google com appengine docs python datastore structuring for strong consistency工作 但我不断收到此错误
  • 如何在 C# 中将 int[] 转换为 byte[]

    如何在 C 中将 int 转换为 byte 一些代码将不胜感激 EDIT 我需要一个函数来执行以下操作 byte FuncName int Input 由于您的问题中的细节很少 我只能猜测您要做什么 假设您想将 2D 整数数组 展平 为 1
  • 后台工作人员:在执行 RunWorkerCompleted 之前确保 ProgressChanged 方法已完成

    假设我正在使用后台工作者并且我有以下方法 private void bw DoWork object sender DoWorkEventArgs e finalData MyWork sender as BackgroundWorker
  • 当调用函数时,堆栈帧真的会被推入堆栈吗?

    我很长一段时间以来所学到的方法是 当我运行程序时 立即进入堆栈的第一件事是 main 方法的堆栈帧 如果我从 main 中调用一个名为 foo 的函数 那么一个堆栈帧 即局部变量 自动对象 的大小 和参数也会被推入堆栈 然而 我遇到了一些与
  • CefSharp获取页面截图

    是否可以使用以下方式获取网页的屏幕截图CefSharp 我找到了有关的信息GetImage 方法 但似乎不再支持 还有其他办法吗 我需要从屏幕外浏览器获取屏幕截图 因此制作显示浏览器的屏幕屏幕截图并不是解决方案 我已经在分叉分支中实现了此功
  • 如何在android中使用openstreetmap通过纬度和经度获取城市名称[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 在我的应用程序中 我使用 osm 而不是谷歌地图 我有纬度和经度 所以从这里我将如何查询从 osm 数据库获取城市名称 请帮助我 我正在使
  • 显示一个句子,一次一个字符

    我想用 jQuery 一次一个字符地显示一个句子 有没有一个插件可以做到这一点或者我怎样才能达到这种效果 你可以写一个小插件来做到这一点 这里有一些可以帮助您入门的东西 远非完美 只是为了给您一个想法 function fn writeTe
  • 可索引类型 - TypeScript

    下面的语法 interface StringArray index number string 指出当StringArray索引为number 它将返回一个string 例如 let myArray StringArray myArray
  • 获取 JSON 格式的 JSDoc 输出

    有没有办法配置 JSDoc 使输出采用 JSON 格式而不是通常的 HMTL 格式 有一个选项 X 解释 它使用已解析的 AST 创建 JSON 文件 jsdoc X mylib gt jsdoc ast json 要理解此 JSON 您可
  • 如何更改引导程序中面板的折叠方向

    我有一个众所周知的基本可折叠面板 其代码如下所述 我通过 css 设置更改了一些属性 例如折叠和折叠高度和宽度 但无法更改折叠方向 我想将其更改为与默认位置相反的顶部 我怎样才能做到这一点 我向你保证 我尝试了多种方法 但无法解决问题 di
  • 在 numpy 中加速矢量化眼球追踪算法

    我正在尝试实现 Fabian Timm 的眼球追踪算法 http www inb uni luebeck de publikationen pdfs TiBa11b pdf http www inb uni luebeck de publi