1

我正在看一篇名为“使用通用傅里叶描述符的基于形状的图像检索”的论文,但只有傅里叶描述符的基本知识。我正在尝试实现论文第 12 页上的算法,并得到了一些我无法真正理解的结果。

如果我创建一个小图像,计算图像的 FD,并将 FD 与在 x 和 y 方向上由单个像素平移的同一图像进行比较,描述符完全不同,除了第一个条目 -这是完全相同的。首先,一个问题是,这些描述符是否应该在两个图像之间完全相同(因为描述符显然是缩放、旋转和平移不变的)?

其次,在论文中,它提到两个独立图像的描述符通过简单的欧几里德距离进行比较 - 因此,通过取上述两个描述符之间的欧几里德距离,欧几里德距离显然为 0。

我快速整理了一些 Javascript 代码来测试算法,如下所示。

有没有人有任何意见、想法和前进的方法?

谢谢,保罗

				var iShape = [
					0,   0,   0,   0,   0,
					0,   0, 255,   0,   0,
					0, 255, 255, 255,   0,
					0,   0, 255,   0,   0,
					0,   0,   0,   0,   0
				];
				
				var ImageWidth = 5, ImageHeight = 5, MaxRFreq = 5, MaxAFreq = 5;
				
				// Calculate centroid
				var cX = 0, cY = 0, pCount = 0;
				for (x = 0; x < ImageWidth; x++) {
					for (y = 0; y < ImageHeight; y++) {
						if (iShape[y * ImageWidth + x]) {
							cX += x;
							cY += y;
							pCount++;
						}
					}
				}
				
				cX = cX / pCount;
				cY = cY / pCount;
				
				console.log("cX = " + cX + ", cY = " + cY);
				
				// Calculate the maximum radius
				var maxR = 0;
				for (x = 0; x < ImageWidth; x++) {
					for (y = 0; y < ImageHeight; y++) {
						if (iShape[y * ImageWidth + x]) {
							var r = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
							if (r > maxR) {
								maxR = r;
							}
						}
					}
				}
				
				// Initialise real / imaginary table
				var i;
				var FR = [ ];
				var FI = [ ];
				for (r = 0; r < (MaxRFreq); r++) {
					var rRow = [ ];
					FR.push(rRow);
					var aRow = [ ];
					FI.push(aRow);
					for (a = 0; a < (MaxAFreq); a++) {
						rRow.push(0.0);
						aRow.push(0.0);
					}
				}
				
				var rFreq, aFreq, x, y;				
				for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
					for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
						for (x = 0; x < ImageWidth; x++) {
							for (y = 0; y < ImageHeight; y++) {
								var radius = Math.sqrt(Math.pow(x - maxR, 2) +
									Math.pow(y - maxR, 2));
								var theta = Math.atan2(y - maxR, x - maxR);
								if (theta < 0.0) {
									theta += (2 * Math.PI);
								}
								
								var iPixel = iShape[y * ImageWidth + x];
								FR[rFreq][aFreq] += iPixel * Math.cos(2 * Math.PI * rFreq *
									(radius / maxR) + aFreq * theta);
								FI[rFreq][aFreq] -= iPixel * Math.sin(2 * Math.PI * rFreq *
									(radius / maxR) + aFreq * theta);
									
							}
						}
					}
				}
				
				// Initialise fourier descriptor table
				var FD = [ ];
				for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
					FD.push(0.0);
				}
				
				// Calculate the fourier descriptor
				for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
					for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
						if (rFreq == 0 && aFreq == 0) {
							FD[0] = Math.sqrt(Math.pow(FR[0][0], 2) + Math.pow(FR[0][0], 2) /
								(Math.PI * maxR * maxR));
						} else {
							FD[rFreq * MaxAFreq + aFreq] = Math.sqrt(Math.pow(FR[rFreq][aFreq], 2) +
								Math.pow(FI[rFreq][aFreq], 2) / FD[0]);
						}
					}
				}
				
				for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
					console.log(FD[i]);
				}

4

1 回答 1

1

这里应用了三种单独的归一化技术,以使最终描述符对 1) 平移和 2) 缩放 3) 旋转保持不变。

对于平移不变部分,您需要找到形状的质心并计算以质心为原点的每个轮廓点的向量。这是通过分别从每个点的坐标中减去质心的 x 和 y 坐标来完成的。因此,在您的代码中,每个点的半径和 theta 应按如下方式计算:

var radius = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
var theta = Math.atan2(y - cY, x - cX);

对于比例不变部分,您需要找到每个向量的最大幅度(或您所说的半径)(已经针对平移不变性进行了归一化),并将每个点的幅度除以最大幅度值。实现此目的的另一种方法是将每个傅立叶系数除以零频率系数(第一系数),因为在那里表示比例信息。正如我在您的代码和论文中看到的那样,这是根据我描述的第二种方式实现的。

最后,仅通过保持傅立叶系数的大小来实现旋转不变性,如您在论文伪代码的第 6 步中所见。

除了所有这些,请记住,为了将欧几里德距离应用于描述符比较,每个形状的描述符长度必须相同。在 FFT 中,最终系数的数量取决于形状的轮廓点的数量。我发现的解决方案是在点之间进行插值,以便为每个形状达到固定数量的点。

希望我能帮上忙,拉萨罗斯

于 2015-02-23T12:48:17.580 回答