Android,操纵相机预览帧
我想制作一个使用相机并在预览帧上应用图像处理滤镜的 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
方法中执行什么操作,我都看不到模拟器发生任何变化。
I want to make an Android application that uses the camera and applies image processing filters on the preview frames.
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);
}
}
However, I see no changes in the emulator no matter what I do in the onPreviewFrame
method.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
另一种选择是使用 OpenCV 框架,该框架具有 Android 端口:
http://opencv.willowgarage。 com/wiki/Android2.3.0
它是开源开放计算机视觉项目的 NDK 端口,它将获取原始预览帧并允许使用 OpenCV 对其进行处理,然后再将其显示在 SurfaceView 上。因为它操纵帧,所以它运行的帧速率与直接挂钩硬件优化预览的帧速率不同,但因为它的大部分内容是本机的,所以它做得非常好。
上面链接的该版本中有一个 OpenCV_Sample 应用程序,它编译成一个演示应用程序,可以完成您正在寻找的大部分功能。它有菜单选项可以启用反转、模糊图像或在预览区域进行边缘检测。即使这并不完全是您想要的,源代码中也有一些很棒的示例可供学习。
Another option is to use the OpenCV framework, which has an Android port:
http://opencv.willowgarage.com/wiki/Android2.3.0
It's an NDK port of the open source Open Computer Vision project, and it'll take raw preview frames and allow for processing them with OpenCV before displaying them on a SurfaceView. Because it manipulates the frames it doesn't run at quite the same framerate as just a directly hooked in hardware optimized preview, but because so much of it is native it does a pretty good job.
There's an OpenCV_Sample app in that version linked above which compiled into a demo app which can do much of what you're looking for. It has menu options to enable inverse, blur the image, or do edge detection on the preview area. Even if it's not exactly what you want, there are some great samples in the source code to learn from.
那是因为您在回调中获得的预览缓冲区只是预览缓冲区的副本,因此您所做的任何修改都不会显示,因为您获得的缓冲区是您的副本。在android sdk 这里提到< /a>
我不知道如何做到这一点,但我一直在考虑如何解决这个问题,这是我认为应该做的事情 -
更新
重新访问 SDK 文档,我发现了这个 API -
setPreviewTexture
这个 API 允许我们 - “从图像流中捕获帧作为 OpenGL ES 纹理”。一旦获得应用了纹理的图像,您就可以使用 OpenGL 来显示帧。 (看看@Stephan 发布的关于如何执行此操作的答案。)注意 -
setPreviewTexture
从 API 级别 11 开始可用! SDK 链接Well that's because the preview buffers that you are getting in the callback is only a copy of the preview buffers, hence any modifications that you do will not be displayed since the buffer that you get is your copy. Mentioned in the android sdk here
I am not sure how to do this but I have been giving it some thought on how to go about this and here is what I think should be done -
UPDATE
Revisiting the SDK documentation I found this API -
setPreviewTexture
this API allows us to - "captures frames from an image stream as an OpenGL ES texture". Once you have the images with the applied texture you can use OpenGL to display your frames. (Take a look at the answer posted by @Stephan on how to do this.)NOTE -
setPreviewTexture
is available from API level 11 onwards! SDK Link