我试图在WebGL / GLSL中实现Harris角点检测器(较大的CV算法的第一部分)。据我所知,我的高斯和索贝尔算子按预期工作(即它是模糊的,索贝尔给出了我图像强度的导数)。
我遇到的问题是Harris角点探测器对角线边缘的响应太高 - 根据探测器,任何对角线边缘都是角落。当然,这是不正确的,但我不确定为什么。无论我如何调整响应公式,它似乎都有这个问题。
这是我的着色器代码:
precision mediump float;
// the texture I am trying to detect the corners in
// (fed from a live video source)
uniform sampler2D sampler2d;
// the Gaussian / Sobel kernels are precalculated and passed as textures
uniform sampler2D gaussian_x;
uniform sampler2D gaussian_y;
// stdev for the Gaussian
#define sigma (3.0)
#define sigma_ceil (3.0)
// pixel_w and pixel_h represent the size of pixels in tex coords
#define pixel_w (1.0 / 960.0)
#define pixel_h (1.0 / 540.0)
const float offset_start = -(sigma_ceil * 3.0);
const float offset_end = ((sigma_ceil * 3.0) + .5);
const float pixel_gauss = 1.0 / (sigma_ceil * 2.0 + 1.0);
varying vec4 fPosition;
varying vec2 fTexCoord;
void main(){
vec2 texCoord = vec2(fTexCoord.s, fTexCoord.t);
vec3 total_x = vec3(0, 0, 0);
vec3 total_y = vec3(0, 0, 0);
for (float x = offset_start; x < offset_end; x += 1.0){
for (float y = offset_start; y < offset_end; y += 1.0){
total_x += texture2D(sampler2d, vec2(texCoord.s + x * pixel_w, texCoord.y + y * pixel_h)).rgb
* ((texture2D(gaussian_x, vec2((x - offset_start) * pixel_gauss, (y - offset_start) * pixel_gauss)).rgb
- vec3(0.5)) * .1)
* 255.0
;
total_y += texture2D(sampler2d, vec2(texCoord.s + x * pixel_w, texCoord.y + y * pixel_h)).rgb
* ((texture2D(gaussian_y, vec2((x - offset_start) * pixel_gauss, (y - offset_start) * pixel_gauss)).rgb
- vec3(0.5)) * .1)
* 255.0
;
}
}
float total_xf = (total_x.r + total_x.g + total_x.b) / 3.0;
float total_yf = (total_y.r + total_y.g + total_y.b) / 3.0;
float a = (total_xf * total_xf); // Ix2
float b = (total_yf * total_yf); // Iy2
float c = (total_xf * total_yf); // Ixy
float det = (a * b) - c;
float trc = a + b;
float res = det - 0.04 * (trc * trc);
res += .5; // to see when it goes negative
gl_FragColor = vec4(res, res, res, 1);
}
在此之后我会进行非最大限制抑制和阈值处理,但这一步的结果似乎已经错了。两个高斯采样器从这样的纹理中采样:
这些是预先计算的,是我从每个像素中减去.5的原因(因为灰色像素实际上代表0重量)。 .1和255因素使我可以看到图像,我尝试了许多不同的值,但我认为它们不是问题。
我也尝试使用res = det / trc
近似值,但结果似乎更糟。问题依然存在。使用标准棋盘图案,如下所示:
当我将它水平显示到相机时,结果就是这样:
我不确定水平边缘发生了什么,但是垂直边缘是黑色的(正如预期的那样),并且角落显示非常白色的像素,这会在阈值处理时产生预期的结果。但是,当我对角转动图案时:
所有边缘现在都是白色的。我一直在调整各种各样的值,对高斯人使用更高的stdev等,但似乎没有任何东西产生预期的结果。难道只是哈里斯探测器检测到对角线边缘是角落吗?我怀疑,看到其他一些实现。
任何想法可能是什么问题?
(另外,在你建议openCV之前......这是在WebGL中运行的,我想/应该自己实现这个算法。)