代码之家  ›  专栏  ›  技术社区  ›  greenie

Android中的Sobel边缘检测

  •  8
  • greenie  · 技术社区  · 15 年前

    作为我为Android开发的应用程序的一部分,我想向用户展示他们所拍摄的图像的边缘检测版本(类似于下面的示例)。

    为了实现这一点,我一直在研究Sobel算子以及如何在Java中实现它。但是,我发现的许多示例都使用了awt中的对象和方法( 像这个例子 )那不是android的一部分。

    我的问题是,真的,Android是否提供了上述例子中使用的awt功能的任何替代方案?如果我们仅仅使用安卓系统内置的库来重写这个例子,我们会怎么做呢?

    alt text

    为了实现这一点,我一直在研究Sobel算子以及如何在Java中实现它。然而,我发现的许多示例都使用了awt中的对象和方法。( like this example )这不是Android的一部分。

    我的问题是,真的,Android是否提供了上述例子中使用的awt功能的任何替代方案?如果我们仅仅使用安卓系统内置的库来重写这个例子,我们会怎么做呢?

    4 回复  |  直到 10 年前
        1
  •  3
  •   reflog    15 年前

    由于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示例所需的所有内容。(只需更改“卷积像素”函数)

        2
  •  6
  •   X.Y.    12 年前

    问题和答案是3岁…@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
  •  0
  •   flanglet    12 年前

    在这里检查Java实现:

    http://code.google.com/p/kanzi/source/browse/java/src/kanzi/filter/SobelFilter.java

    不依赖Swing/AWT或任何其他库。它直接作用于图像像素,而且速度很快。

    结果可以在这里看到(向下滚动):

    http://code.google.com/p/kanzi/wiki/Overview

        4
  •  0
  •   Buddhisthead    10 年前

    另一种选择是使用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工作室中的Gealle构建,您可以从不同的地方拉入针对Java构建的OpenCV库,但我也主持最近的构建。在build.gradle文件中,可以添加类似这样的依赖项…否则,这有点棘手。 dependencies { compile 'com.iparse.android:opencv:2.4.8' } 如果您使用Eclipse,您可以查看OpenCV网站,了解有关在Android上使用OpenCV的详细信息: http://opencv.org/platforms/android.html