2012-06-07 14 views
5

Ich muss einen sphärischen Filter auf ein Bild in Android anwenden, ich habe Eingang und erwartete Ausgabe Bild beigefügt. Das Ausgabebild wird vom quadrierten zentrierten Bereich des Eingabebildes verarbeitet und auf die Kugel abgebildet. Irgendeine Idee, wie man das in Android macht. Muss ich OpenGL dafür verwenden, oder wird 2D-Transformation alleine die Aufgabe übernehmen?Sphärische Filter in android

Input image
Output Image

Antwort

2

den folgenden Code Fish Eye lens für die Sphäre erstellen und einige Änderungen für die Skalierung der Kugel und Hintergrund Generation anwenden, wird es vor allem für quadratische Bilder arbeiten.

0

Dies ist ein Ray-Tracing-Problem. OpenGL wird Ihnen hier wahrscheinlich nicht einmal helfen, da OpenGL kein strahlenbasiertes 3D liefert. Dies ist jedoch möglicherweise das, wonach Sie suchen.

http://www1.cs.columbia.edu/CAVE/publications/pdfs/Garg_TR04.pdf

+0

Ich glaube nicht, dass es ein schwieriges Raytracing-Problem ist, vorausgesetzt, dass der Hintergrund nur eine Textur ist. Sie können die Textur mit einer Art sphärischem Koordinatensystem oder einer Cubemap der Kugel zuordnen. Wenn er eine dynamische 3D-Szene reflektieren würde, würde ich dir zustimmen, aber es ist nicht allzu schwierig, eine Textur zu reflektieren. – Tim

+0

Das nicht-raytracing Beispiel ist, was das Papier, das ich zur Verfügung stellte, ungefähr ist (ich bin ziemlich sicher) !!! Eine andere Möglichkeit, dies zu tun (auch wenn der Hintergrund eine Textur ist), könnte dennoch Ray-Tracing verwenden. – trumpetlicks

+2

"OpenGL bietet kein Ray-basiertes 3D" - das kann man definitiv mit Shadern machen.Ich habe mit einem OpenGL ES 2.0 Shader eine ähnliche Verzerrung gemacht: http://stackoverflow.com/a/9896856/19679 und GLSL definiert sogar eine 'refract()' Funktion für die Lichtbrechung durch Objekte. Lass mich sehen, ob ich einen Shader erstellen kann, um diesen spezifischen Effekt zu replizieren. –

0

ich mit Tim zustimmen. Das Umwandeln einer Bitmap in eine andere erfordert keine 3D-Punkte, noch Ray-Trace, vergiss es überhaupt, es ist einfach 2d. Ich weiß nicht, ob OpenGL etwas eingebaut hat, aber ich habe genug 3D-Erfahrung, um Sie in die richtige Richtung zu weisen. Sie müssen alle Punkte innerhalb des von Ihnen gewählten * Kreisbereichs durchlaufen. Dies ist der Hinweis und die Farbe wird mit der FISH-EYE-Transformation gefunden. Du hast genug im Netz. hoffe das hilft

+0

Das abgebildete Beispiel zeigt Spiegelreflexion, Refraktion und eine echte Kreisbindung an das Wasser/Glas etc ... Auch wenn Sie den Link von Brad Larson (toller Link übrigens +1) an den Kanten betrachten an der kreisförmigen Grenze sind glatte Übergang zurück zum Bild selbst. Es ist ein Effekt, nicht NOTWENDIG, wonach dieser Benutzer fragt. Wenn das obige Bild wirklich das ist, nach dem sie suchen, kann es etwas komplexer sein als die etwas einfacheren Shader-Typ-Funktionen. Haben Sie vom Fragesteller nicht viel über ihre Interpretation erfahren? – trumpetlicks

4

Ich habe gerade eine Implementierung dieses auf iOS 2.0 OpenGL ES mit Arbeits:

Spherical refraction example

Während dies auf iOS, kann das Fragment-Shader habe ich gerade über Android gebracht werden. Der sphärische Brechungsbereich wird dadurch erreicht, den folgenden Fragment-Shader verwendet:

varying highp vec2 textureCoordinate; 

uniform sampler2D inputImageTexture; 

uniform highp vec2 center; 
uniform highp float radius; 
uniform highp float aspectRatio; 
uniform highp float refractiveIndex; 

void main() 
{ 
    highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); 
    highp float distanceFromCenter = distance(center, textureCoordinateToUse); 
    lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius); 

    distanceFromCenter = distanceFromCenter/radius; 

    highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); 
    highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); 

    highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); 

    gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere;  
} 

Die center ist eine normalisierte für den Mittelpunkt der Kugel Koordinate (aus einem Raum von 0,0 bis 1,0 in beiden Dimensionen), die radius der normierte Radius Der refractiveIndex ist der Luft-/Materialindex Ihrer Kugel, und das aspectRatio ist das Seitenverhältnis des Bildes (um sicherzustellen, dass die Kugel im normalisierten Koordinatenraum rund und nicht elliptisch ist).

Dies berechnet die Flächennormalen für eine Kugel mit dem gelieferten Mittelpunkt und Radius und verwendet die Funktion GLSL refract(), um einen eingehenden Vektor zu brechen und Nachschlagekoordinaten in der Bildtextur bereitzustellen.

Der Hintergrund ist verschwommen mit einer trennbaren Gaußschen Unschärfe, die ich in this answer beschreiben.

Dieser Filter ist schnell genug, um Live-Video in Echtzeit auf einem iPhone zu filtern, daher sollte es auf den meisten Android-Geräten ziemlich performant sein. Der Quellcode dafür finden Sie im GPUImageSphereRefractionFilter in meinem Open Source-Framework GPUImage.

+0

Ich habe das in openGL verwendet und es hat perfekt funktioniert. Aber ich habe Probleme, die Mathematik zu verstehen. Bei der Berechnung von y textureCoordinateToUse verstehe ich, warum aspectRatio multipliziert wird, aber warum ist der Rest der Berechnung erforderlich? – tanvi