Android 从SurfaceView显示实时摄像机获取RGB
我正在使用Android 从SurfaceView显示实时摄像机获取RGB,android,colors,camera,rgb,surfaceholder,Android,Colors,Camera,Rgb,Surfaceholder,我正在使用camera.startPreview()在SurfaceView中显示实时摄像头。你知道如何从摄像机上获取实时RGB读数吗 谢谢您可以做类似的事情,如下所示 camera.takePicture(shutterCallback, rawCallback, jpegCallback); jpegCallback = new PictureCallback() { public void onPictureTaken(byte[] data, Camera camera
camera.startPreview()在SurfaceView
中显示实时摄像头代码>。你知道如何从摄像机上获取实时RGB读数吗
谢谢您可以做类似的事情,如下所示
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, offset, length);
int[] pix = new int[picw * pich];
bitmap.getPixels(pix, 0, picw, 0, 0, picw, pich);
int R, G, B,Y;
for (int y = 0; y < pich; y++){
for (int x = 0; x < picw; x++)
{
int index = y * picw + x;
int R = (pix[index] >> 16) & 0xff; //bitwise shifting
int G = (pix[index] >> 8) & 0xff;
int B = pix[index] & 0xff;
pix[index] = 0xff000000 | (R << 16) | (G << 8) | B;
}}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
};
camera.takePicture(shutterCallback、rawCallback、jpeg callback);
jpegCallback=新建PictureCallback(){
公共void onPictureTaken(字节[]数据,摄像头){
FileOutputStream扩展流=null;
试一试{
位图位图=位图工厂.decodeByteArray(数据、偏移量、长度);
int[]pix=新的int[picw*pich];
获取像素(像素,0,像素,0,0,像素,像素);
int R,G,B,Y;
对于(int y=0;y>16)&0xff;//按位移位
int G=(pix[index]>>8)&0xff;
int B=pix[索引]&0xff;
pix[index]=0xff000000 |(R我想我可以从SurfaceView
中转换数据。但最好的使用方法是:
- 将相机的方向设置为90度
- 将输出格式设置为NV21(所有设备都支持该格式)
- 设置为打开闪光灯
- 在
SurfaceView
中开始预览
列表项
camera = Camera.open();
cameraParam = camera.getParameters();
cameraParam.setPreviewFormat(ImageFormat.NV21);
camera.setDisplayOrientation(90);
camera.setParameters(cameraParam);
cameraParam = camera.getParameters();
camera.setPreviewDisplay(surfaceHolder);
cameraParam.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(cameraParam);
camera.startPreview();
然后,我调用setPreviewCallback
和onPreviewFrame
来获取传入帧,并将其转换为RGB像素数组。然后,我可以通过运行for
循环的myPixels数组并选中color.red(myPixels[I])来平均图片中每种颜色的强度
用于每种所需颜色(在预览框架内)
其中找到了decodeYUV420SP
我将此操作的时间定为每帧大约需要200毫秒。有没有更快的方法呢?根据要求,这里有一个使用NDK的快速解码(在快速设备上小于10毫秒):
首先是本地人
#include <jni.h>
#ifndef native_H
#define native_H
extern "C" {
JNIEXPORT jbyteArray JNICALL Com_example_MainActivity_nativeSetIamgeFromCamera(JNIEnv* jenv, jobject obj,jbyteArray array,jint length,jint x,jint y);
};
#endif
有可能重复这个问题几乎是重复的。在你的帖子中,他们要求一个特定的编码,我从一个表面视图中询问任何编码。没有必要无缘无故地抨击我。你又尝试了什么?期待人们为你写代码。这就是为什么我猜你投了反对票。自从它出现以来,我就没有投过反对票dy Answeed.cana此解决方案可用于视频RGB值的快速连续监控吗?可能是的,在这种情况下,您不需要每次都在SD卡上保存捕获的图像,我应该调用哪个代码而不是onPictureTaken
?如果转换发生在camera.setPreviewCallback(new PreviewCallback()){@Override public void on previewframe(byte[]data,Camera-Camera){
您似乎需要在时间间隔Camera.takePicture(shutterCallback,rawCallback,jpegCallback)中调用这一行;原生c/c++ndk在SDK中使用的代码少于15毫秒,而不是ndk:但不要返回数组,因为它比较慢。仅解码V420SP(rgb、数据、帧宽、帧高);E/DEBUG-onPreviewFrame:13毫秒E/DEBUG-onPreviewFrame:11毫秒E/DEBUG-onPreviewFrame:13毫秒E/DEBUG-onPreviewFrame:14毫秒E/DEBUG-onPreviewFrame:11毫秒E/DEBUG-onPreviewFrame:17毫秒E/DEBUG-onPreviewFrame:10毫秒E/DEBUG-onPreviewFrame:11毫秒millisec@matheszabi,您是否希望从3获得完全优化的代码几年前?当我刚开始学习Android编程时?仅供参考,技术已经发生了变化-因此编程风格也发生了变化…我正在尝试实现您的JNI解决方案,但我在ca中遇到了bc。第67行“data_uv”变量未定义。您能帮我找出它可能是什么吗?以下是错误日志:“…错误:“data_uv”未在此范围内声明…”将data_uv替换为data
#include <jni.h>
#ifndef native_H
#define native_H
extern "C" {
JNIEXPORT jbyteArray JNICALL Com_example_MainActivity_nativeSetIamgeFromCamera(JNIEnv* jenv, jobject obj,jbyteArray array,jint length,jint x,jint y);
};
#endif
#include <stdint.h>
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "native.h"
void Resize_and_decodyuv(unsigned char * data,int _width,int _height, unsigned char *out, int newWidth, int newHeight);
JNIEXPORT jbyteArray JNICALL Com_example_MainActivity_nativeSetIamgeFromCamera(JNIEnv* jenv, jobject obj,jbyteArray array,jint length,jint x,jint y)
{
//-----jbyteArray array contain the data from the camera passed by the java function
//-----length represent the size of jbyteArray in byte
//-----x,y respectively resolutionx and resolutiony of the image in jbyteArray array
unsigned char * buffImgCamera=(unsigned char *)malloc(length);
//----- copy the buffer from java array to c/c++ char * buffImgCamera
jenv->GetByteArrayRegion(array, 0, length, (jbyte*)buffImgCamera);
int width=400,height=600;//screen reso of the surface(400,800 is just an example)
unsigned char * buffOut=(unsigned char *)malloc(width*height*4);//prepare the result buffer where 4 represent R G B A(Alpha transparency channel).
//--- to gain time i decode and resize the image to fit the surface screen in one loop
Resize_and_decodyuv(buffImgCamera,x,y,buffOut,width,height);
//---copy the result to a jbytearray and return it to java function
jbyteArray result=env->NewByteArray(width*height*4);
env->SetByteArrayRegion( result, 0, width*height*4, buffOut);
return result;
}
void Resize_and_decodyuv(unsigned char * data,int _width,int _height, unsigned char *out, int newWidth, int newHeight)
{
int Colordeep=4;//RGBA; in the case of Qt Frame Work or Borland just put 3and the code should work;
float scaleWidth = (float)newWidth / (float)_width;
float scaleHeight = (float)newHeight / (float)_height;
for(int cy = 0; cy < newHeight; cy++)
{
for(int cx = 0; cx < newWidth; cx++)
{
int pixel = (cy * (newWidth *Colordeep)) + (cx*Colordeep);
int nearestMatch = ((((int)(cy / scaleHeight)) *_width) + (int)(cx /scaleWidth));
int cxa=cx/scaleWidth;
int cya=cy/scaleHeight; cya/=2;
int nearestMatch1 =(cya *_width) + (int)(cxa);
int y = ( data[nearestMatch]);
int v = data[data_uv+(nearestMatch1)];
int u = data[data_uv+(nearestMatch1)+1];
int r = (int) (1164 * (y - 16) + 1596 * (v - 128));
int g = (int) (1164 * (y - 16) - 813 * (v - 128) - 391 * (u - 128));
int b = (int) (1164 * (y - 16) + 2018 * (u - 128));
r/=1000;
g/=1000;
b/=1000;
r = r < 0 ? 0 : (r > 255 ? 255 : r);
g = g < 0 ? 0 : (g > 255 ? 255 : g);
b = b < 0 ? 0 : (b > 255 ? 255 : b);
out[pixel ] = r;
out[pixel +1 ] = g;
out[pixel + 2] = b;
if(Colordeep==4)out[pixel + 3] = 255;
}
}
}
PreviewCallback previewCallback = new PreviewCallback () {
public void onPreviewFrame(byte[] data, Camera camera) {
//nativeSetIamgeFromCamera return a byte array
nativeSetIamgeFromCamera(data,data.length,camera.getParameters().getPreviewSize().width,camera.getParameters().getPreviewSize().height);
}
};