Android, управляйте кадрами предварительного просмотра камеры - PullRequest
6 голосов
/ 23 июня 2011

Я хочу создать приложение для Android, которое использует камеру и применяет фильтры обработки изображений к кадрам предварительного просмотра.

package alex.filter;

import java.io.IOException;

import android.content.Context;
import android.graphics.Canvas;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class Preview extends SurfaceView implements SurfaceHolder.Callback {

    SurfaceHolder mHolder;
    public Camera camera;

    Preview(Context context) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {        
        camera = Camera.open();        

        try {
            camera.setPreviewDisplay(holder);

            camera.setPreviewCallback(new PreviewCallback() {
                public void onPreviewFrame(byte[] data, Camera arg1) {                    
                    for( int i = 0 ; i < data.length ; i ++ ){
                        data[ i] = 0; // or some sirius filter
                    }                                                            
                    Preview.this.invalidate();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        }

    public void surfaceDestroyed(SurfaceHolder holder) {        
        camera.stopPreview();        
        camera = null;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {        
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(w, h);
        camera.setParameters(parameters);
        camera.startPreview();
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);        
    }
}

Однако я не вижу изменений в эмуляторе, независимо от того, что я делаю в методе onPreviewFrame.

Ответы [ 3 ]

4 голосов
/ 18 июля 2011

Другим вариантом является использование инфраструктуры OpenCV, которая имеет порт Android:

http://opencv.willowgarage.com/wiki/Android2.3.0

Это порт NDK проекта Open Computer Vision с открытым исходным кодом, и он принимает необработанные кадры предварительного просмотра и позволяет обрабатывать их с помощью OpenCV, прежде чем отображать их в SurfaceView. Поскольку он манипулирует кадрами, он не работает с той же частотой кадров, что и непосредственно подключенный в предварительном просмотре с аппаратной оптимизацией, но поскольку большая часть его является нативной, он делает довольно хорошую работу.

В этой версии есть ссылка на приложение OpenCV_Sample, которое скомпилировано в демонстрационное приложение, которое может выполнить большую часть того, что вы ищете. В нем есть пункты меню для включения инвертирования, размытия изображения или определения края в области предварительного просмотра. Даже если это не совсем то, что вам нужно, в исходном коде есть несколько замечательных примеров для изучения.

2 голосов
/ 13 июля 2011

См. эту ссылку , я думаю, это похоже на то, чего вы хотите достичь.

1 голос
/ 13 июля 2011

Ну, это потому, что буферы предварительного просмотра, которые вы получаете в обратном вызове, являются только копией буферов предварительного просмотра, поэтому любые сделанные вами изменения не будут отображаться, так как полученный вами буфер является вашей копией.Упоминается в Android SDK здесь

Я не уверен, как это сделать, но я думал о том, как это сделать, и вот, что я думаю, должно быть сделано -

  • Регистрация для буферов предварительного просмотра
  • Отключение отображения предварительного просмотра по умолчанию
    • Если вы не установите отображение предварительного просмотра на поверхность, то вы не должны получать никакого отображения(но я не уверен, что это будет работать - прочитал это на каком-то форуме и не смог вспомнить источник)но я не мог думать ни о чем другом ..)
  • Уменьшите частоту кадров предварительного просмотра, чтобы мы не были перегружены буферами
  • Теперь для отображения нашегобуферы, мы можем либо использовать функцию рисования растрового изображения по умолчанию, либо использовать opengl для отображения буферов.Но я до сих пор не использовал ни того, ни другого, даже не знаю, возможно ли это, какие-либо мысли о том же?

ОБНОВЛЕНИЕ
Повторное рассмотрение документации SDK Я нашел этоAPI - setPreviewTexture этот API позволяет нам - "захватывать кадры из потока изображений в виде текстуры OpenGL ES".Когда у вас есть изображения с примененной текстурой, вы можете использовать OpenGL для отображения ваших кадров.(Посмотрите ответ @Stephan о том, как это сделать.)

ПРИМЕЧАНИЕ. - setPreviewTexture доступно начиная с уровня API 11 и выше! SDK Link

...