我为Wikitude创建了一个新插件 . 我想将识别的图像发送到另一个API . 首先,我必须得到图像,但我失败了 . 我也在Wikitude论坛上问了这个问题,但没有人回答 . 这是我的插件代码:我正在使用Wikitude 6.0和VisualStudio 2017
public class Plugin02 : Com.Wikitude.Common.Plugins.Plugin
{
public Plugin02(string p0) : base(p0)
{
}
public override void CameraFrameAvailable(Frame p0)
{
try
{
// try 1
BitmapFactory.Options Options = new BitmapFactory.Options { InSampleSize = 1 };
Bitmap bitmap = BitmapFactory.DecodeByteArray(p0.GetData(), 0, p0.GetData().Length, Options);
SaveBitmap(bitmap);
// result : bitmap is always null
//try 2
var yuv = new YuvImage(p0.GetData(), ImageFormatType.Nv21, p0.Size.Width, p0.Size.Height, null);
// var bmp = a.b(currentFrame.GetData(), currentFrame.GetData().Length, currentFrame.Size.Width, currentFrame.Size.Height);
var ms = new MemoryStream();
var quality = 100; // adjust this as needed
yuv.CompressToJpeg(new Rect(0, 0, yuv.Width, yuv.Height), quality, ms);
var jpegData = ms.ToArray();
Bitmap bitmap2 = BitmapFactory.DecodeByteArray(jpegData, 0, jpegData.Length);
SaveBitmap(bitmap2);
// result : image is not clear
}
catch (System.Exception ex) { }
}
void SaveBitmap(Bitmap bitmap)
{
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, DateTime.Now.Millisecond.ToString() + ".jpg");
var stream = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Png, 100, stream);
stream.Close();
}
public override void Update(RecognizedTarget[] p0)
{
}
protected override void Initialize()
{
base.Initialize();
}
protected override void Pause()
{
base.Pause();
}
protected override void Resume(long p0)
{
base.Resume(p0);
}
protected override void Destroy()
{
base.Destroy();
}
}
这是我的新代码:
public class Plugin01 : Com.Wikitude.Common.Plugins.Plugin
{
TesseractApi api;
public Plugin01(string p0) : base(p0)
{
api = new TesseractApi(Application.Context, AssetsDeployment.OncePerVersion);
api.Init("eng");
}
Frame currentFrame = null;
public override void CameraFrameAvailable(Frame p0)
{
try
{
var data = p0.GetData();
currentFrame = p0;
}
catch (System.Exception ex) { }
}
public override void Update(RecognizedTarget[] p0)
{
if (p0 != null)
{
if (currentFrame != null)
{
ConvertYuvToJpeg(currentFrame, p0[0]);
}
}
}
protected override void Initialize()
{
base.Initialize();
}
protected override void Pause()
{
base.Pause();
}
protected override void Resume(long p0)
{
base.Resume(p0);
}
protected override void Destroy()
{
base.Destroy();
}
private void ConvertYuvToJpeg(Frame frame, RecognizedTarget p00)
{
try
{
YuvImage yuvimage = new YuvImage(frame.GetData(), ImageFormatType.Nv21, frame.Size.Width, frame.Size.Height, null);
var outStream = new MemoryStream();
var left = p00.TargetPositionInCameraFrame.Origin.GetY() + 10;
var top = p00.TargetPositionInCameraFrame.Origin.GetX()+20;
var right = left + p00.TargetPositionInCameraFrame.Size.Width;
var bottom = top + p00.TargetPositionInCameraFrame.Size.Height;
Rect rect = new Rect(left, top, right, bottom);
yuvimage.CompressToJpeg(rect, 100, outStream);
Bitmap bmp = BitmapFactory.DecodeByteArray(outStream.ToArray(), 0, outStream.ToArray().Length);
Matrix mtx = new Matrix();
mtx.PreRotate(90);
bmp = Bitmap.CreateBitmap(bmp, 0, 0, bmp.Width, bmp.Height, mtx, false);
var outStream1 = new MemoryStream();
bmp.Compress(Bitmap.CompressFormat.Png, 100, outStream1);
var bmpA = bmp.Copy(Bitmap.Config.Argb8888, true);
api.SetImage(outStream1);
//api.Results(Tesseract.PageIteratorLevel.Block);
if (api.Text != null)
{
}
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, DateTime.Now.Millisecond.ToString() + ".jpg");
var stream = new FileStream(filePath, FileMode.Create);
bmp.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
stream.Close();
}
catch (System.Exception ex) { }
}
}
这是图像样本:
根据什么wikitude support said图像格式为YV12 for Android,我找不到任何方式将其转换为RGB或类似唯一的一种是Nv21格式 .
我已经按照你的说法添加了YUV到RGB转换器,这里是新代码,但是出了点问题 . getData()的长度大于width * height .
public override void Update(RecognizedTarget[] p0)
{
if (p0 != null)
{
if (currentFrame != null)
{
//ConvertYuvToJpeg(currentFrame, p0[0]);
ConvertYuvToRGB(currentFrame, p0[0]);
}
}
}
private void ConvertYuvToRGB(Frame frame, RecognizedTarget p00)
{
try
{
var rgbData = convertYUV420_NV21toARGB8888(frame.GetData(), frame.Size.Width, frame.Size.Height);
var bitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb8888);
// vector is your int[] of ARGB
bitmap.CopyPixelsFromBuffer(Java.Nio.IntBuffer.Wrap(rgbData));
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, DateTime.Now.Millisecond.ToString() + ".jpg");
var stream = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
stream.Close();
}
catch (System.Exception ex) { }
}
public static int[] convertYUV420_NV21toARGB8888(byte[] data, int width, int height)
{
int size = width * height;
int offset = size;
int[] pixels = new int[size];
int u, v, y1, y2, y3, y4;
// i along Y and the final pixels
// k along pixels U and V
for (int i = 0, k = 0; i < size; i += 2, k += 2)
{
y1 = data[i] & 0xff;
y2 = data[i + 1] & 0xff;
y3 = data[width + i] & 0xff;
y4 = data[width + i + 1] & 0xff;
u = data[offset + k] & 0xff;
v = data[offset + k + size / 4] & 0xff;
v = v - 128;
u = u - 128;
pixels[i] = convertYUVtoARGB(y1, u, v);
pixels[i + 1] = convertYUVtoARGB(y2, u, v);
pixels[width + i] = convertYUVtoARGB(y3, u, v);
pixels[width + i + 1] = convertYUVtoARGB(y4, u, v);
if (i != 0 && (i + 2) % width == 0)
i += width;
}
return pixels;
}
private static int convertYUVtoARGB(int y, int u, int v)
{
int r = y + (int)(1.772f * v);
int g = y - (int)(0.344f * v + 0.714f * u);
int b = y + (int)(1.402f * u);
r = r > 255 ? 255 : r < 0 ? 0 : r;
g = g > 255 ? 255 : g < 0 ? 0 : g;
b = b > 255 ? 255 : b < 0 ? 0 : b;
return (int)(4278190080 | ((r + 16) | ((g + 8) | b)));
}