安卓中的Sobel边缘检测

9
作为我正在开发的Android应用程序的一部分,我想向用户展示他们拍摄的图像的边缘检测版本(类似于下面的示例)。为了实现这一点,我一直在研究Sobel算子以及如何在Java中实现它。然而,我找到的许多示例都使用了AWT中的对象和方法(例如此示例),而AWT不是Android的一部分。因此,我的问题是,Android是否提供了上述示例中使用的AWT功能的替代方案?如果我们只使用Android内置的库来重新编写该示例,该怎么做呢?

你所提供的源代码中并没有与AWT相关的内容。:-/ - ivans
BufferedImage不是在AWT中找到的类吗? - greenie
4个回答

6
这个问题和回答已经有三年了... @reflog的解决方案适用于像边缘检测这样简单的任务,但速度比较慢。我在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,它可以并行访问每个像素并对其进行任何操作。我还没有看到使用该选项构建的图像处理库。

3

由于Android中没有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”函数)

这很棒,但是当我逐像素操作时,Bitmap.getPixel()和Bitmap.setPixel()似乎非常慢。我认为最好在开始时使用Bitmap.getPixels()将位图的值作为整数复制到int[]中。如何对RGB int值数组执行卷积而不是位图? - greenie
你是正确的,获取整个数组更快。 要在数组上执行卷积,只需使用相同类型的for循环进行迭代,并通过使用分离的R、G和B通道或使用Color.rgb(r1,g1,b1)函数从RGB数组中组合像素来获取像素值。 - reflog

1

另一个选择是使用OpenCV,它在Android上有很好的实现。

Imgproc.Sobel()方法接受一个'Mat'类型的图像作为输入,可以轻松地从资源或位图中加载。输入Mat应该是灰度图像,也可以使用opencv创建。 Mat src = Highgui.imread(getClass().getResource( "/SomeGrayScaleImage.jpg").getPath());

然后在其上运行Sobel边缘检测器,并将结果保存在新的Mat中。如果您想保持相同的图像深度,则可以这样做... Mat dst; int ddepth = -1; // 目标深度。-1保留源深度 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


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接