【发布时间】:2010-12-23 20:00:04
【问题描述】:
我有这个矩阵 A,表示图像像素强度的相似性。例如:考虑一个10 x 10 图像。在这种情况下,矩阵 A 的维度为 100 x 100,元素 A(i,j) 的值在 0 到 1 之间,表示像素 i 与 j 在强度方面的相似性。
我正在使用 OpenCV 进行图像处理,开发环境是 Linux 上的 C。
目标是计算矩阵 A 的特征向量,我使用了以下方法:
static CvMat mat, *eigenVec, *eigenVal;
static double A[100][100]={}, Ain1D[10000]={};
int cnt=0;
//Converting matrix A into a one dimensional array
//Reason: That is how cvMat requires it
for(i = 0;i < affnDim;i++){
for(j = 0;j < affnDim;j++){
Ain1D[cnt++] = A[i][j];
}
}
mat = cvMat(100, 100, CV_32FC1, Ain1D);
cvEigenVV(&mat, eigenVec, eigenVal, 1e-300);
for(i=0;i < 100;i++){
val1 = cvmGet(eigenVal,i,0); //Fetching Eigen Value
for(j=0;j < 100;j++){
matX[i][j] = cvmGet(eigenVec,i,j); //Fetching each component of Eigenvector i
}
}
问题: 执行后,所有特征向量的几乎所有分量都为零。我尝试了不同的图像,还尝试使用 0 到 1 之间的随机值填充 A,但结果相同。
返回的几个顶级特征值如下所示:
9805401476911479666115491135488.000000
-9805401476911479666115491135488.000000
-89222871725331592641813413888.000000
89222862280598626902522986496.000000
5255391142666987110400.000000
我现在正在考虑使用cvSVD() 的方法,它执行实浮点矩阵的奇异值分解,并可能产生特征向量。但在那之前,我想在这里问。我目前的方法有什么荒谬的吗?我是否使用了正确的 API,即 cvEigenVV() 用于正确的输入矩阵(我的矩阵 A 是浮点矩阵)?
干杯
【问题讨论】:
-
在openCV中没有真正使用过eig/svd但是返回的特征值不是应该排序的吗?
-
是的,没错。我刚刚提出了返回的前 5 个特征值,它们的大小是按顺序排列的(从大到小)。就符号而言,它们不是。但是这个符号只是表示向量的方向,所以我认为特征值是可以的。只关心特征向量。
-
哦忘了这个标志!根据文档,epsilon 值 1e-15 就足够了(您使用的是 eps=1e-300)。这会导致问题吗?同样,我们通常可以期望只有前几个最大的特征向量占数据方差的大部分,这不是真的吗?
-
好吧,我很想这样做,但显然我不知道 MATLAB。我正在使用高斯内核来计算相似度并参考 Andrew Ng 的光谱聚类算法。请在这里eprints.kfupm.edu.sa/54643/1/54643.pdf 找到它。第 2 页有算法。该算法的第 1 步提到了用于计算两个像素之间相似度的高斯核。我使用了 Si、Sj 的像素强度和分母的标准差,即 sigma^2。我在计算 sigma 时排除了像素 i 和 j 的强度。
-
我对openCV一无所知,但看起来你正在将两个未初始化的指针(eigenVec 和 eigenVal)传递给 cvEigenVV()。但也许你为了简短而跳过了初始化代码。
标签: c image-processing opencv eigenvector