2010-05-30 16 views
8

Dans le cadre d'une application que je développe pour Android, j'aimerais montrer à l'utilisateur une version détectée par les bords d'une image qu'ils ont prise (quelque chose de similaire à l'exemple ci-dessous).Sobel Edge Detection dans Android

alt text

Pour atteindre ce que je cherchais à l'opérateur de Sobel et comment le mettre en œuvre en Java. Cependant, beaucoup des exemples que j'ai trouvés utilisent des objets et des méthodes trouvés dans AWT (like this example) qui ne fait pas partie d'Android.

Ma question est alors vraiment, est-ce que Android fournit des alternatives aux fonctionnalités de AWT qui ont été utilisées dans l'exemple ci-dessus? Si nous devions réécrire cet exemple en utilisant simplement les bibliothèques intégrées à Android, comment procéder?

+0

Il n'y a vraiment rien AWT précis sur le code source vous avez accédé à: -/ – ivans

+0

Is not BufferedImage une classe trouvé dans AWT cependant? – greenie

Répondre

3

puisque vous n'avez pas BufferedImage dans Android, vous pouvez le faire vous-même toutes les opérations de base:

Bitmap b = ... 
width = b.getWidth(); 
height = b.getHeight(); 
stride = b.getRowBytes(); 
for(int x=0;x<b.getWidth();x++) 
    for(int y=0;y<b.getHeight();y++) 
    { 
     int pixel = b.getPixel(x, y); 
     // you have the source pixel, now transform it and write to destination 
    } 

comme vous pouvez le voir, cela couvre presque tout ce dont vous avez besoin pour le portage de cet exemple AWT. (Il suffit de changer la fonction 'convolvePixel')

+0

C'est génial, mais Bitmap.getPixel() et Bitmap.setPixel() semblent être vraiment lents quand je le fais pixel par pixel. J'ai pensé qu'il serait préférable d'utiliser Bitmap.getPixels() au début pour copier les valeurs de l'image en tant qu'entier à un int []. Comment est-ce que j'effectuerais la convolution sur un tableau de valeurs int RVB plutôt que le bitmap? – greenie

+0

Vous avez raison, aller chercher tout le tableau est plus rapide. Pour effectuer des convolutions sur la baie, vous devez simplement utiliser le même type de boucles for et obtenir la valeur de pixel en utilisant des canaux R, G et B séparés ou en composant un pixel à partir de RGB array.) 'Fonction. – reflog

5

La question et la réponse sont 3 ans ... @ solution de reflog fonctionne pour une tâche simple comme la détection de bord, mais il est lent . J'utilise GPUImage sur iOS pour la tâche de détection de contour. Il y a une bibliothèque équivalente sur Android: https://github.com/CyberAgent/android-gpuimage/tree/master

L'accélération matérielle est donc supposée être très rapide. Voici le filtre de détection de bords Sobel: https://github.com/CyberAgent/android-gpuimage/blob/master/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelEdgeDetection.java

Selon le document, vous pouvez simplement faire ceci:

Uri imageUri = ...; 
mGPUImage = new GPUImage(this); 
mGPUImage.setGLSurfaceView((GLSurfaceView) findViewById(R.id.surfaceView)); 
mGPUImage.setImage(imageUri); // this loads image on the current thread, should be run in a thread 
mGPUImage.setFilter(new GPUImageSobelEdgeDetection()); 

// Later when image should be saved saved: 
mGPUImage.saveToPictures("GPUImage", "ImageWithFilter.jpg", null); 

Une autre option utilise renderScript, que vous pouvez accéder à chaque pixel en parallèle et faire ce que vous voulez avec ça. Je ne vois aucune bibliothèque de traitement d'image construite avec ça pour le moment.

0

Une autre option est d'utiliser OpenCV, qui a une excellente implémentation pour Android.

La méthode Imgproc.Sobel() prend une image sous la forme d'un type 'Mat', qui est facilement chargé à partir d'une ressource ou d'un bitmap. L'entrée Mat doit être une image en niveaux de gris, qui peut également être créée avec opencv. Lancez ensuite le détecteur de bord sobel, en enregistrant les résultats dans un nouveau Mat. Si vous voulez garder la même profondeur d'image, alors ça va le faire ... Mat dst; int ddepth = -1; // destination depth. -1 maintains existing depth from source int dx = 1; int dy = 1; Imgproc.Sobel(src, dst, ddepth, dx, dy);

Certains documents de référence est ici: http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html#Sobel(org.opencv.core.Mat,%20org.opencv.core.Mat,%20int,%20int,%20int)

Pour une construction gradle dans Android Studio, vous pouvez tirer dans la bibliothèque OpenCV construit pour Java à partir de différents endroits, mais je également l'hôte d'une construction récente. Dans votre fichier build.gradle, vous pouvez ajouter une dépendance comme ça ... Sinon, c'est un peu compliqué. dependencies { compile 'com.iparse.android:opencv:2.4.8' } Si vous utilisez Eclipse, vous pouvez consulter le site OpenCV pour plus de détails sur l'utilisation OpenCV sur Android: http://opencv.org/platforms/android.html