2010-05-30 126 views
8

作爲我爲Android開發的應用程序的一部分,我想向用戶展示他們拍攝的圖像的邊緣檢測版本(類似於下面的示例)。Android中的索貝爾邊緣檢測

alt text

要做到這一點,我一直在尋找的Sobel算子和如何實現它在Java中。不過,我發現的許多示例都使用了AWT(like this example)中的對象和方法,這些對象和方法不是Android的一部分。

我的問題是,真的,Android是否提供了AWT功能的任何替代品,這些替代品在上面的例子中已經被使用過了?如果我們只是使用Android內置的庫重寫這個例子,我們將如何去做呢?

+0

沒什麼好說的AWT具體談談您鏈接到源代碼: -/ – ivans 2010-05-30 11:45:20

+0

是不是BufferedImage的一類儘管在AWT中找到? – greenie 2010-05-30 12:15:51

回答

3

,因爲你沒有在BufferedImage的機器人,你可以自己做所有的基本操作:

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 
    } 

,你可以看到,這幾乎涵蓋了你需要移植的是AWT例子一切。 (只是改變了 'convolvePixel' 功能)

+0

這很好,但是當我逐像素地進行處理時,Bitmap.getPixel()和Bitmap.setPixel()對我來說似乎非常慢。我認爲最好在開始時使用Bitmap.getPixels()將位圖的值作爲整數複製到int []。我將如何執行一個RGB int值的數組卷積而不是位圖? – greenie 2010-05-31 20:22:47

+0

你是對的,讀取整個數組速度更快。 要對數組執行卷積,只需使用相同類型的for循環迭代並通過使用分離的R,G和B通道或使用Color.rgb(r1,g1,b1)組合RGB像素中的像素來獲取像素值)'功能。 – reflog 2010-06-01 10:10:58

5

的問題和答案是3歲... // @引用日誌的解決方案適用於像邊緣檢測一個簡單的任務,但它的速度慢。

我在iOS上使用GPUImage進行邊緣檢測任務。在Android上有一個等效的庫: https://github.com/CyberAgent/android-gpuimage/tree/master

它的硬件加速,所以它應該是非常快。這裏是Sobel邊緣檢測過濾器: https://github.com/CyberAgent/android-gpuimage/blob/master/library/src/jp/co/cyberagent/android/gpuimage/GPUImageSobelEdgeDetection.java

根據文檔,你可以簡單地這樣做:

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); 

另一種選擇是使用的renderScript,您可以並行訪問每個像素,並做你想做的用它。我還沒有看到任何圖像處理庫。

0

另一種選擇是使用OpenCV,它有很好的Android實施。

Imgproc.Sobel()方法以'Mat'類型的形式獲取圖像,該圖像可以從資源或位圖輕鬆加載。輸入Mat應該是灰度圖像,也可以使用opencv創建。 Mat src = Highgui.imread(getClass().getResource( "/SomeGrayScaleImage.jpg").getPath());

然後運行sobel邊緣檢測器,將結果保存到新的Mat中。如果你想保持相同的圖像深度,那麼這將做到這一點... 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);

一些參考文檔是在這裏: http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html#Sobel(org.opencv.core.Mat,%20org.opencv.core.Mat,%20int,%20int,%20int)

對於Android Studio中的Gradle一個構建,你可以拉從不同的地方建立Java的OpenCV庫,但我也舉辦一個最近的版本。在你的build.gradle文件中,你可以像這樣添加一個依賴項...否則,這有點棘手。 dependencies { compile 'com.iparse.android:opencv:2.4.8' } 如果你使用Eclipse,你可以檢查OpenCV的網站的詳細信息,在Android上使用opencv:http://opencv.org/platforms/android.html