Harris köşe algılamasını kullanarak OpenGL ES 2.0'da böyle bir şey uyguluyordum ve tamamen bitmemişken, şimdiye kadar sahip olduğum gölgelendirici tabanlı uygulamayı paylaşacağımı düşündüm. Bunu iOS tabanlı açık kaynak çerçevesinin bir parçası olarak yaptım , böylece belirli bir adımın nasıl çalıştığını merak ediyorsanız kodu kontrol edebilirsiniz.
Bunu yapmak için aşağıdaki adımları kullanıyorum:
- Vektörle (0.2125, 0.7154, 0.0721) RGB değerlerinin bir nokta ürününü kullanarak görüntüyü parlaklık değerlerine düşürün.
Geçerli kanalın solunda, sağında ve üstünde ve altındaki piksellerden kırmızı kanal değerlerini çıkararak X ve Y türevlerini hesaplayın. Daha sonra kırmızı kanalda bulunan x türevini, yeşil kanalda bulunan Y türevini ve mavi kanalda X ve Y türevlerinin ürününü saklarım. Bunun için parça gölgelendirici aşağıdaki gibi görünür:
precision highp float;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 bottomTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
float verticalDerivative = abs(-topIntensity + bottomIntensity);
float horizontalDerivative = abs(-leftIntensity + rightIntensity);
gl_FragColor = vec4(horizontalDerivative * horizontalDerivative, verticalDerivative * verticalDerivative, verticalDerivative * horizontalDerivative, 1.0);
}
Burada varyasyonlar her yöndeki ofset doku koordinatlarıdır. Bu mobil GPU'larda kötü bir şekilde yavaş olan bağımlı doku okumalarını ortadan kaldırmak için tepe gölgeleyicisinde bunları önceden hesaplıyorum.
Bu türev görüntüye bir Gauss bulanıklığı uygulayın. Ayrılmış bir yatay ve dikey bulanıklık kullandım ve her geçişte yalnızca beş doku okuması ile dokuz vuruşlu bir bulanıklık yapmak için donanım doku filtrelemesinden faydalandım. Bu gölgelendiriciyi bu Stack Overflow yanıtında açıklıyorum .
Bulanık giriş türevi değerlerini kullanarak gerçek Harris köşe algılama hesaplamasını çalıştırın. Bu durumda, aslında Alison Noble tarafından Ph.D. tez "Görüntü Yüzeylerinin Tanımları". Bunu işleyen gölgelendirici aşağıdaki gibi görünür:
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
const mediump float harrisConstant = 0.04;
void main()
{
mediump vec3 derivativeElements = texture2D(inputImageTexture, textureCoordinate).rgb;
mediump float derivativeSum = derivativeElements.x + derivativeElements.y;
// This is the Noble variant on the Harris detector, from
// Alison Noble, "Descriptions of Image Surfaces", PhD thesis, Department of Engineering Science, Oxford University 1989, p45.
mediump float harrisIntensity = (derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z)) / (derivativeSum);
// Original Harris detector
// highp float harrisIntensity = derivativeElements.x * derivativeElements.y - (derivativeElements.z * derivativeElements.z) - harrisConstant * derivativeSum * derivativeSum;
gl_FragColor = vec4(vec3(harrisIntensity * 10.0), 1.0);
}
Yerel maksimum olmayan baskılama gerçekleştirin ve geçen pikselleri vurgulamak için bir eşik uygulayın. Merkezi bir pikselin mahallesindeki sekiz pikseli örneklemek ve bu gruplamada maksimum olup olmadığını belirlemek için aşağıdaki parça gölgelendiriciyi kullanıyorum:
uniform sampler2D inputImageTexture;
varying highp vec2 textureCoordinate;
varying highp vec2 leftTextureCoordinate;
varying highp vec2 rightTextureCoordinate;
varying highp vec2 topTextureCoordinate;
varying highp vec2 topLeftTextureCoordinate;
varying highp vec2 topRightTextureCoordinate;
varying highp vec2 bottomTextureCoordinate;
varying highp vec2 bottomLeftTextureCoordinate;
varying highp vec2 bottomRightTextureCoordinate;
void main()
{
lowp float bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).r;
lowp float bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
lowp float bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
lowp vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
lowp float leftColor = texture2D(inputImageTexture, leftTextureCoordinate).r;
lowp float rightColor = texture2D(inputImageTexture, rightTextureCoordinate).r;
lowp float topColor = texture2D(inputImageTexture, topTextureCoordinate).r;
lowp float topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).r;
lowp float topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
// Use a tiebreaker for pixels to the left and immediately above this one
lowp float multiplier = 1.0 - step(centerColor.r, topColor);
multiplier = multiplier * 1.0 - step(centerColor.r, topLeftColor);
multiplier = multiplier * 1.0 - step(centerColor.r, leftColor);
multiplier = multiplier * 1.0 - step(centerColor.r, bottomLeftColor);
lowp float maxValue = max(centerColor.r, bottomColor);
maxValue = max(maxValue, bottomRightColor);
maxValue = max(maxValue, rightColor);
maxValue = max(maxValue, topRightColor);
gl_FragColor = vec4((centerColor.rgb * step(maxValue, centerColor.r) * multiplier), 1.0);
}
Bu işlem, nesnelerinizden şöyle görünen bir mısır haritası oluşturur:
Aşağıdaki noktalar, maksimum olmayan bastırma ve eşiklemeye dayalı köşeler olarak tanımlanır:
Bu filtre için uygun eşikler ayarlandığında, köşeleri nesnenin gerçek kenarlarının içine piksel veya benzeri yerleştirme eğiliminde olmasına rağmen, bu görüntüdeki 16 köşenin tümünü tanımlayabilir.
Bir iPhone 4'te, bu köşe algılama, kameradan gelen 640x480 video karelerinde 20 FPS'de çalıştırılabilir ve bir iPhone 4S, bu boyuttaki videoları 60+ FPS'de kolayca işleyebilir. Bu gibi bir görev için CPU'ya bağlı işlemeden daha hızlı olmalı, ancak şu anda noktaları okuma işlemi CPU'ya bağlı ve olması gerekenden biraz daha yavaş.
Bunu eylemde görmek istiyorsanız, çerçevem için kodu alabilir ve onunla birlikte gelen FilterShowcase örneğini çalıştırabilirsiniz. Harris köşe algılama örneği, cihaz kamerasından canlı videoda çalışıyor, ancak bahsettiğim gibi, şu anda CPU'da köşe noktalarının okunması gerçekten yavaşlıyor. Bunun için de GPU tabanlı bir sürece geçiyorum.