我的应用程序从YUV中的相机抓取预览帧并将其发送到服务器。我正在尝试更改它,因此它只会将部分图像(裁剪)发送到服务器。但是我想循环遍历字节数组并直接将裁剪后的图像发送到服务器,而不是创建一个Bitmap类并以这种方式裁剪它。
我的目标是尽可能高效。
有没有人有一些伪代码(甚至更好的实际代码)来裁剪YUV图像?
我希望代码可以像这样工作:
OutputStream out = clientSocket.getOutputStream();
byte[] preview = getCameraPreview();
//Crop half of the image
int x = (int)(getX()/2);
int y = (int)(getY()/2);
//Send the width, height, and image size to the server
out.write(intToByteArray(x));
out.write(intToByteArray(y));
out.write(intToByteArray((int)(x*y)));
//Start sending the picture to the server
for(int i = 0; i < y; i++)
for(int j = 0; j < x; j++)
out.write(preview[i+j]);
我知道代码根本不起作用,但希望你能够了解我正在尝试做的事情。
任何帮助将不胜感激。
答案 0 :(得分:2)
这是一个C代码片段,用于在YUV420帧上进行就地裁剪 请注意,裁剪矩形的宽度和高度以及左侧和顶部应均匀
// original frame
unsigned char mYUVFrame[frameSize];
// crop position
int lo_x, lo_y, hi_x, hi_y;
// original size of frame
int width, height;
int new_width = (hi_x-lo_x)+1;
int new_height = (hi_y-lo_y)+1;
unsigned char *orig_pos, *new_pos;
// Y
orig_pos = mYUVFrame + lo_y*width + lo_x;
new_pos = mYUVFrame;
for (int i=0; i<new_height; i++)
{
memmove(new_pos, orig_pos, new_width);
orig_pos += width;
new_pos += new_width;
}
// Cb
orig_pos = mYUVFrame + width*height + lo_x/2 + lo_y*width/4;
new_pos = mYUVFrame+new_width*new_height;
for (int i=0; i<new_height/2; i++)
{
memmove(new_pos, orig_pos, new_width/2);
orig_pos += width/2;
new_pos += new_width/2;
}
// Cr
orig_pos = mYUVFrame + (width*height*5)/4 + lo_x/2 + lo_y*width/4;
new_pos = mYUVFrame + (new_width*new_height*5)/4;
for (int i=0; i<new_height/2; i++)
{
memmove(new_pos, orig_pos, new_width/2);
orig_pos += width/2;
new_pos += new_width/2;
}
与java或任何其他语言的对话相当容易,类似的aproach应该适用于不同的pix格式(yuv422,yuv444,...)
答案 1 :(得分:0)
在android中查看YuvImage。这提供了YUV图像裁剪的简单实现,但它以jpeg格式生成输出。
希望这有帮助。
答案 2 :(得分:0)
你可以试试这个: 此示例将相机帧发送到服务器
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
try {
byte[] baos = convertYuvToJpeg(data, camera);
StringBuilder dataBuilder = new StringBuilder();
dataBuilder.append("data:image/jpeg;base64,").append(Base64.encodeToString(baos, Base64.DEFAULT));
mSocket.emit("newFrame", dataBuilder.toString());
} catch (Exception e) {
Log.d("########", "ERROR");
}
}
};
public byte[] convertYuvToJpeg(byte[] data, Camera camera) {
YuvImage image = new YuvImage(data, ImageFormat.NV21,
camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 20; //set quality
image.compressToJpeg(new Rect(0, 0, camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height), quality, baos);//this line you can crop the image quality
return baos.toByteArray();
}
或者在方法surfaceChanged中,你可以这样:
for(Camera.Size size: mCamera.getParameters().getSupportedPreviewSizes()){
Log.d("123###########", String.valueOf(size.width)+" x "+String.valueOf(size.height)); //Size preview
}
Camera.Parameters mParameters = mCamera.getParameters();
mParameters.setPreviewSize(720, 480);////set Size preview available
mCamera.setParameters(mParameters);