Обнаружение края Sobel в Android

В рамках приложения, которое я разрабатываю для Android, я хотел бы показать пользователю версию изображения с обнаружением границ (что-то похожее на пример ниже).

alt text

Для этого я рассматривал оператор Собеля и способы его реализации на Java. Однако во многих найденных мною примерах используются объекты и методы AWT (как этот пример), который не является частью Android.

Тогда мой вопрос: действительно ли Android предоставляет какие-либо альтернативы функциям AWT, которые использовались в приведенном выше примере? Если бы нам пришлось переписать этот пример, просто используя библиотеки, встроенные в Android, как бы мы это сделали?


person greenie    schedule 30.05.2010    source источник
comment
На самом деле в исходном коде, на который вы ссылаетесь, нет ничего особенного для AWT: -/   -  person ivans    schedule 30.05.2010
comment
Разве BufferedImage не является классом, найденным в AWT?   -  person greenie    schedule 30.05.2010


Ответы (4)


поскольку у вас нет BufferedImage в Android, вы можете выполнять все основные операции самостоятельно:

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)

person reflog    schedule 30.05.2010
comment
Это здорово, но Bitmap.getPixel() и Bitmap.setPixel() кажутся мне очень медленными, когда я делаю это попиксельно. Я подумал, что было бы лучше использовать Bitmap.getPixels() в начале, чтобы скопировать значения растрового изображения как целые числа в int[]. Как мне выполнить свертку для массива значений RGB int, а не для растрового изображения? - person greenie; 01.06.2010
comment
Вы правы, выборка всего массива происходит быстрее. Чтобы выполнить свертки в массиве, вы просто выполняете итерацию, используя тот же тип циклов for, и получаете значение пикселя либо с использованием отдельных каналов R, G и B, либо составляя пиксель из массива RGB с помощью функции Color.rgb(r1,g1,b1). - person reflog; 01.06.2010

Вопросу и ответу 3 года... Решение @reflog работает для простой задачи, такой как обнаружение краев, но оно медленное.

Я использую GPUImage на iOS для задачи обнаружения краев. На Android есть эквивалентная библиотека: https://github.com/CyberAgent/android-gpuimage/tree/master

Это аппаратное ускорение, поэтому оно должно быть очень быстрым. Вот фильтр обнаружения края sobel: ="noreferrer">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, с помощью которого вы можете получить доступ к каждому пикселю параллельно и делать с ним все, что захотите. Я пока не вижу какой-либо библиотеки обработки изображений, созданной с ее помощью.

person X.Y.    schedule 20.06.2013

Другой вариант — использовать OpenCV, у которого отличная реализация для Android.

Метод Imgproc.Sobel() принимает изображение в виде типа «Mat», которое легко загружается из ресурса или растрового изображения. Входной мат должен быть изображением в градациях серого, которое также можно создать с помощью opencv. Mat src = Highgui.imread(getClass().getResource( "/SomeGrayScaleImage.jpg").getPath());

Затем запускаем на нем детектор краев собеля, сохраняя результаты в новый мат. Если вы хотите сохранить ту же глубину изображения, то это подойдет... 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)

Для сборки gradle в Android Studio вы можете использовать библиотеку opencv, созданную для Java, из разных мест, но я также размещаю недавнюю сборку. В вашем файле build.gradle вы можете добавить такую ​​​​зависимость... В противном случае это немного сложно. dependencies { compile 'com.iparse.android:opencv:2.4.8' } Если вы используете Eclipse, вы можете посетить веб-сайт Opencv для получения подробной информации об использовании Opencv на Android: http://opencv.org/platforms/android.html

person Buddhisthead    schedule 24.08.2015

Проверьте реализацию Java здесь:

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

Нет никакой зависимости от Swing/AWT или любой другой библиотеки. Он работает непосредственно с пикселями изображения и работает быстро.

Результаты можно посмотреть здесь (прокрутить вниз):

http://code.google.com/p/kanzi/wiki/Обзор

person flanglet    schedule 26.05.2013