2016-03-20 2 views
20

Ich versuche, die Eckpunkte von einem Standbild mit GPUImageHarrisCornerDetectionFilter zu bekommen.Wie bekomme ich Ecken mit GPUImageHarrisCornerDetectionFilter

Ich habe am Beispielcode aus dem Projekt sah, habe ich in der Dokumentation sah, und ich habe auf diesem Posten sah, die über die gleiche Sache ist: GPUImage Harris Corner Detection on an existing UIImage gives a black screen output

Aber ich kann es nicht machen - und es fällt mir schwer zu verstehen, wie das mit Standbildern funktionieren soll.

Was ich an dieser Stelle haben, ist dies:

func harrisCorners() -> [CGPoint] { 
    var points = [CGPoint]() 

    let stillImageSource: GPUImagePicture = GPUImagePicture(image: self.image) 
    let filter = GPUImageHarrisCornerDetectionFilter() 

    filter.cornersDetectedBlock = { (cornerArray:UnsafeMutablePointer<GLfloat>, cornersDetected:UInt, frameTime:CMTime) in 
     for index in 0..<Int(cornersDetected) { 
      points.append(CGPoint(x:CGFloat(cornerArray[index * 2]), y:CGFloat(cornerArray[(index * 2) + 1]))) 
     } 
    } 

    filter.forceProcessingAtSize(self.image.size) 
    stillImageSource.addTarget(filter) 
    stillImageSource.processImage() 

    return points 
} 

Diese Funktion gibt immer [] so ist es offensichtlich nicht funktioniert.

Ein interessantes Detail - ich habe das FilterShowcaseSwift-Projekt aus GPUImage-Beispielen zusammengestellt, und der Filter findet keine klaren Ecken, wie auf einem Blatt Papier auf schwarzem Hintergrund.

+1

Da es keine klaren Ecken gibt, ist der Harris-Eckendetektor nicht skaleninvariant. Je höher die Auflösung des Bildes, desto schärfer wird es aussehen. Die 'blurRadiusInPixels',' sensitivity' und 'threshold' können mit einer bestimmten Auflösung optimiert werden, um mehr oder weniger Ecken herauszuziehen. Sie können aber auch experimentieren, indem Sie die Auflösung der Bilder verringern, damit sie größer werden. Ecken skalieren. Die aktuelle Implementierung ist ebenfalls auf maximal 256 Ecken beschränkt. Wenn also alle oben links im Bild erkannt werden, wird nichts mehr gemeldet. –

Antwort

4
filter.cornersDetectedBlock = { (cornerArray:UnsafeMutablePointer<GLfloat>, cornersDetected:UInt, frameTime:CMTime) in 
    for index in 0..<Int(cornersDetected) { 
     points.append(CGPoint(x:CGFloat(cornerArray[index * 2]), y:CGFloat(cornerArray[(index * 2) + 1]))) 
    } 
} 

Dieser Code, den Sie hier haben, setzt einen Block, der jedes Bild aufgerufen wird.

Dies ist ein asynchroner Prozess, also wenn Ihre Funktion zurückgibt, wurde noch nie aufgerufen und Ihr Array sollte immer leer sein. Es sollte aufgerufen werden, nachdem der Rahmen die Verarbeitung beendet hat.

Um dies zu überprüfen, setzen Sie einen Haltepunkt in diesem Block und sehen, ob er aufgerufen wird.

von Brad Larson Warning (Schöpfer von GPUImage) in den Kommentaren:

Die GPUImage Sie schaffen hier stillImageSource wird nach dieser Funktion beendet freigegeben werden und stürzt in diesem Fall führen kann.

+0

Ja, das stimmt. Ich habe tatsächlich versucht, die Punkte innerhalb der for-Schleife an einem Punkt zu drucken, aber der Filter erkennt keine Ecken in dem Testbild, das ich benutzt habe, also habe ich das übersehen. – henrikstroem

+1

Technisch wird dies nach jedem verarbeiteten Frame aufgerufen, ob Ecken erkannt wurden oder nicht. Sie haben Recht, dass die -processImage-Methode von GPUImagePicture einen Verarbeitungsjob in einer Hintergrund-Dispatch-Warteschlange auslöst, der höchstwahrscheinlich nicht beendet wird, bevor diese Funktion beendet wird. Das bedeutet auch, dass das GPUImagePicture, das lokal in dieser Funktion definiert ist, vor dem Abschluss der Verarbeitung freigegeben wird, was zu Abstürzen führen kann, wenn Sie nicht vorsichtig sind. Ich hatte einmal eine synchrone Version dieser Operation, kann mich aber nicht erinnern, warum ich sie entfernt habe. Deadlocks, vielleicht? –

+0

Vielen Dank für einen Blick auf @BradLarson! Ich habe einige Informationen aktualisiert, die Sie angegeben haben. :] – Jack

Verwandte Themen