当前位置: 首页 > 知识库问答 >
问题:

用于眼睛跟踪的虹膜到屏幕计算

夏侯朝斑
2023-03-14

我目前正在尝试眼动跟踪,我已经成功地使用带有轮廓和霍夫变换的OpenCV构建了虹膜跟踪算法。但是下一步对我来说还不清楚。我想知道我所做的计算是否正确,可以将眼睛的中心转换到屏幕上。用户的头部具有固定位置。

我想要的是一种对所有偏离航线的人都有效的算法。有角度计算吗?所以当用户看起来更右,线性?

我现在做的是:首先,我让用户查看特定点,并使用RANSAC检测虹膜位置,该位置最接近屏幕上的位置。我用屏幕和虹膜上的四个2D点来实现。我使用单应性来得到正确的计算。

void gaussian_elimination(float *input, int n){
// ported to c from pseudocode in
// http://en.wikipedia.org/wiki/Gaussian_elimination

float * A = input;
int i = 0;
int j = 0;
int m = n-1;
while (i < m && j < n){
    // Find pivot in column j, starting in row i:
    int maxi = i;
    for(int k = i+1; k<m; k++){
        if(fabs(A[k*n+j]) > fabs(A[maxi*n+j])){
            maxi = k;
        }
    }
    if (A[maxi*n+j] != 0){
        //swap rows i and maxi, but do not change the value of i
        if(i!=maxi)
            for(int k=0;k<n;k++){
                float aux = A[i*n+k];
                A[i*n+k]=A[maxi*n+k];
                A[maxi*n+k]=aux;
            }
        //Now A[i,j] will contain the old value of A[maxi,j].
        //divide each entry in row i by A[i,j]
        float A_ij=A[i*n+j];
        for(int k=0;k<n;k++){
            A[i*n+k]/=A_ij;
        }
        //Now A[i,j] will have the value 1.
        for(int u = i+1; u< m; u++){
            //subtract A[u,j] * row i from row u
            float A_uj = A[u*n+j];
            for(int k=0;k<n;k++){
                A[u*n+k]-=A_uj*A[i*n+k];
            }
            //Now A[u,j] will be 0, since A[u,j] - A[i,j] * A[u,j] = A[u,j] - 1 * A[u,j] = 0.
        }

        i++;
    }
    j++;
}

//back substitution
for(int i=m-2;i>=0;i--){
    for(int j=i+1;j<n-1;j++){
        A[i*n+m]-=A[i*n+j]*A[j*n+m];
        //A[i*n+j]=0;
    }
}
}



ofMatrix4x4 findHomography(ofPoint src[4], ofPoint dst[4]){
ofMatrix4x4 matrix;

// create the equation system to be solved
//
// from: Multiple View Geometry in Computer Vision 2ed
//       Hartley R. and Zisserman A.
//
// x' = xH
// where H is the homography: a 3 by 3 matrix
// that transformed to inhomogeneous coordinates for each point
// gives the following equations for each point:
//
// x' * (h31*x + h32*y + h33) = h11*x + h12*y + h13
// y' * (h31*x + h32*y + h33) = h21*x + h22*y + h23
//
// as the homography is scale independent we can let h33 be 1 (indeed any of the terms)
// so for 4 points we have 8 equations for 8 terms to solve: h11 - h32
// after ordering the terms it gives the following matrix
// that can be solved with gaussian elimination:

float P[8][9]={
    {-src[0].x, -src[0].y, -1,   0,   0,  0, src[0].x*dst[0].x, src[0].y*dst[0].x, -dst[0].x }, // h11
    {  0,   0,  0, -src[0].x, -src[0].y, -1, src[0].x*dst[0].y, src[0].y*dst[0].y, -dst[0].y }, // h12

    {-src[1].x, -src[1].y, -1,   0,   0,  0, src[1].x*dst[1].x, src[1].y*dst[1].x, -dst[1].x }, // h13
    {  0,   0,  0, -src[1].x, -src[1].y, -1, src[1].x*dst[1].y, src[1].y*dst[1].y, -dst[1].y }, // h21

    {-src[2].x, -src[2].y, -1,   0,   0,  0, src[2].x*dst[2].x, src[2].y*dst[2].x, -dst[2].x }, // h22
    {  0,   0,  0, -src[2].x, -src[2].y, -1, src[2].x*dst[2].y, src[2].y*dst[2].y, -dst[2].y }, // h23

    {-src[3].x, -src[3].y, -1,   0,   0,  0, src[3].x*dst[3].x, src[3].y*dst[3].x, -dst[3].x }, // h31
    {  0,   0,  0, -src[3].x, -src[3].y, -1, src[3].x*dst[3].y, src[3].y*dst[3].y, -dst[3].y }, // h32
};

gaussian_elimination(&P[0][0],9);

matrix(0,0)=P[0][8];
matrix(0,1)=P[1][8];
matrix(0,2)=0;
matrix(0,3)=P[2][8];

matrix(1,0)=P[3][8];
matrix(1,1)=P[4][8];
matrix(1,2)=0;
matrix(1,3)=P[5][8];

matrix(2,0)=0;
matrix(2,1)=0;
matrix(2,2)=0;
matrix(2,3)=0;

matrix(3,0)=P[6][8];
matrix(3,1)=P[7][8];
matrix(3,2)=0;
matrix(3,3)=1;

return matrix;

}

共有2个答案

乐正浩宕
2023-03-14

也许这个链接对你有帮助,祝你好运

cv::Mat computeMatXGradient(const cv::Mat &mat) {
  cv::Mat out(mat.rows,mat.cols,CV_64F);

  for (int y = 0; y < mat.rows; ++y) {
    const uchar *Mr = mat.ptr<uchar>(y);
    double *Or = out.ptr<double>(y);

    Or[0] = Mr[1] - Mr[0];
    for (int x = 1; x < mat.cols - 1; ++x) {
      Or[x] = (Mr[x+1] - Mr[x-1])/2.0;
    }
    Or[mat.cols-1] = Mr[mat.cols-1] - Mr[mat.cols-2];
  }

  return out;
}
苏志
2023-03-14

您应该看看现有的解决方案

  • 用于用眼睛绘画的Eye writer(我测试它只是为了控制鼠标)

Eyewriter.org

眼线笔走查

Github上的眼线笔

  • 眼状瞳孔跟踪

类似眼睛的信息页面(这里讨论的算法类似于您想要的)

Github上的眼状

祝你好运

 类似资料:
  • 在我的例子中,我不需要重写类名并且我发送空值...但我正在等待48小时,我的firebase analytics控制台没有显示关于这个事件的信息,有什么想法吗? 提前道谢!

  • 我看到最后一个android sdk中有一个更新,他们显示,他们记录了每个事件的参数,但是我如何添加屏幕跟踪? 仪表板中有一个用户参与度选项卡,但该选项卡不会展开以提供更多见解。 但是,我在切换活动时看到这样的消息: D/FA:记录事件(FE):_e,束[{_o=auto,_et=4807,_sc=MainActivity,_si=-3289793799694080660}] 这是什么意思?他们在

  • 问题内容: 现在,我正在Xcode 6中使用spritekit(swift)制作游戏。 它必须可在iPhone 4s及更高版本上播放。但据我所知,所有iPhone都来自4s和更高的Retina,所以我可以添加(750 x 1334像素)和@ 2x.png的所有图像。 因此,我不需要添加没有@ 2x的图像。 我对么? 问题答案: 示例:如果您具有512 x 512(1x)图像,并且希望它支持(2x和

  • 当我在学习OpenGL时,我经常偶然发现所谓的眼空间坐标。 如果我是对的,你通常有三个矩阵。模型矩阵、视图矩阵和投影矩阵。虽然我不完全确定这背后的数学是如何工作的,但我知道将坐标转换为世界空间、视图空间和屏幕空间。 但是眼睛空间在哪里,我需要哪些矩阵来将一些东西转换为眼睛空间?

  • 屏幕关闭时无法更新位置。 屏幕关闭后如何运行位置跟踪服务? 开启服务 在onLocationChanged方法中,我尝试Log. e(),但在屏幕关闭时不在logcat中显示纬度和经度 屏幕关闭时帮我介绍一下服务管理。谢谢你。

  • 我正在考虑在使用表存储时为我的应用程序实现一个审计跟踪。 我需要能够记录一个特定客户的所有操作和来自该客户的实体的所有操作。 我的第一个猜测是为每个客户创建一个表(Audits_CustomerXXX),并使用实体id和行键(datetime.max.ticks-datetime.now.ticks).ToString(“D19”)值作为分区键。当我的问题是某个实体发生了什么时,这很有效?例如,购