Skip to content

是否可以考虑提供C#的P/Invoke版本 #59

@fengbozs

Description

@fengbozs

是否可以考虑提供C#的P/Invoke版本,我在进行P/Invoke封装时,经过rknn_outputs_get以后,outputs变成了空,也没有额外的输出,不知道怎么解决,以下是我的测试代码:
IntPtr rknn_context = IntPtr.Zero;
var modelBuffer = File.ReadAllBytes("yolov5_pre.rknn");
var result = RKNNAPI.rknn_init(ref rknn_context, modelBuffer, modelBuffer.Length, 0);
Console.WriteLine($"rknn init result:{result}---{rknn_context.ToInt64()}");

#region query
rknn_sdk_version rknn_Sdk_Version = new rknn_sdk_version()
{
api_version = new char[256],
drv_version = new char[256]
};
uint dwSize = (uint)Marshal.SizeOf(rknn_Sdk_Version);
IntPtr sdkVersionIntPtr = Marshal.AllocHGlobal((int)dwSize);
Marshal.StructureToPtr(rknn_Sdk_Version, sdkVersionIntPtr, false);
var cmd = rknn_query_cmd.RKNN_QUERY_SDK_VERSION;
result = RKNNAPI.rknn_query(rknn_context, cmd, sdkVersionIntPtr, dwSize);
if (result < 0)
{
Console.WriteLine($"rknn_query_sdk_version failed! result:{result}");
//return;
}
else
{
rknn_Sdk_Version = Marshal.PtrToStructure<rknn_sdk_version>(sdkVersionIntPtr);
Console.WriteLine($"rknn_query_sdk_version success! result:{result}");
Console.WriteLine($"drv_version:{rknn_Sdk_Version.drv_version} api_version:{rknn_Sdk_Version.api_version}");
}
Marshal.FreeHGlobal(sdkVersionIntPtr);

rknn_input_output_num io_num = new rknn_input_output_num();
dwSize = (uint)Marshal.SizeOf(io_num);
IntPtr inputOutputNumIntPtr = Marshal.AllocHGlobal((int)dwSize);
Marshal.StructureToPtr(io_num, inputOutputNumIntPtr, false);
result = RKNNAPI.rknn_query(rknn_context, rknn_query_cmd.RKNN_QUERY_IN_OUT_NUM, inputOutputNumIntPtr, dwSize);
if (result < 0)
{
Console.WriteLine($"rknn_query_in_out_num failed! result:{result}");
//return;
}
else
{
io_num = Marshal.PtrToStructure<rknn_input_output_num>(inputOutputNumIntPtr);
Console.WriteLine($"rknn_query_in_out_num success! result:{result}");
Console.WriteLine($"input_num:{io_num.n_input} output_num:{io_num.n_output}");
}
Marshal.FreeHGlobal(inputOutputNumIntPtr);

rknn_tensor_attr[] input_attrs = new rknn_tensor_attr[io_num.n_input];
for (int i = 0; i < io_num.n_input; i++)
{
input_attrs[i] = new rknn_tensor_attr()
{
index = (uint)i
};
dwSize = (uint)Marshal.SizeOf(input_attrs[i]);
IntPtr tensorAttrIntPtr = Marshal.AllocHGlobal((int)dwSize);
Marshal.StructureToPtr(input_attrs[i], tensorAttrIntPtr, false);
result = RKNNAPI.rknn_query(rknn_context, rknn_query_cmd.RKNN_QUERY_INPUT_ATTR, tensorAttrIntPtr, dwSize);
if (result < 0)
{
Console.WriteLine(i + $"Input------ rknn_query_input_attr failed! result:{result}");
}
else
{
input_attrs[i] = Marshal.PtrToStructure<rknn_tensor_attr>(tensorAttrIntPtr);
Console.WriteLine(i + $"Input------ {input_attrs[i].name} {input_attrs[i].type} {input_attrs[i].qnt_type}");
}
}

rknn_tensor_attr[] output_attrs = new rknn_tensor_attr[io_num.n_output];
for (int i = 0; i < io_num.n_output; i++)
{
output_attrs[i] = new rknn_tensor_attr()
{
index = (uint)i
};
dwSize = (uint)Marshal.SizeOf(output_attrs[i]);
IntPtr tensorAttrIntPtr = Marshal.AllocHGlobal((int)dwSize);
Marshal.StructureToPtr(output_attrs[i], tensorAttrIntPtr, false);
result = RKNNAPI.rknn_query(rknn_context, rknn_query_cmd.RKNN_QUERY_OUTPUT_ATTR, tensorAttrIntPtr, dwSize);
if (result < 0)
{
Console.WriteLine(i + $"Output------ rknn_query_output_attr failed! result:{result}");
}
else
{
output_attrs[i] = Marshal.PtrToStructure<rknn_tensor_attr>(tensorAttrIntPtr);
Console.WriteLine(i + $"Output------ {output_attrs[i].name} {output_attrs[i].type} {output_attrs[i].qnt_type}");
}
}
#endregion

int channel = 3;
int width = 640;
int height = 480;
if (input_attrs[0].fmt == rknn_tensor_format.RKNN_TENSOR_NCHW)
{
Console.WriteLine("model is NCHW input fmt");
width = (int)input_attrs[0].dims[0];
height = (int)input_attrs[0].dims[1];
}
else
{
Console.WriteLine("model is NHWC input fmt\n");
width = (int)input_attrs[0].dims[1];
height = (int)input_attrs[0].dims[2];
}
Console.WriteLine($"model input height={height}, width={width}, channel={channel}");

var files = Directory.GetFiles("Images");
foreach (var file in files)
{
rknn_input[] inputs = [new rknn_input()];
rknn_output[] outputs = new rknn_output[io_num.n_output];
for (int i = 0; i < io_num.n_output; i++)
{
outputs[i].is_prealloc = 0;
outputs[i].want_float = 0;
}
var image = SixLabors.ImageSharp.Image.Load(file);
int img_width = image.Width;
int img_height = image.Height;
if (image == null)
return;
image.Mutate(x => x.Resize(width, height));

 inputs[0].index = 0;
 inputs[0].type = rknn_tensor_type.RKNN_TENSOR_UINT8;
 inputs[0].size = (uint)(width * height * channel);
 inputs[0].fmt = rknn_tensor_format.RKNN_TENSOR_NHWC;
 inputs[0].pass_through = 0;
 var imageRgb24 = image.CloneAs<Rgb24>();
 byte[] imageBytes = new byte[width * height * channel];
 imageRgb24.CopyPixelDataTo(imageBytes);
 GCHandle hObject = GCHandle.Alloc(imageBytes, GCHandleType.Pinned);
 IntPtr pObject = hObject.AddrOfPinnedObject();
 inputs[0].buf = pObject;
 var inputResult = RKNNAPI.rknn_inputs_set(rknn_context, io_num.n_input, inputs);
 Console.WriteLine($"rknn_inputs_set result:{inputResult}");
 var pResult = RKNNAPI.rknn_run(rknn_context, IntPtr.Zero);
 if (pResult < 0)
 {
     Console.WriteLine($"rknn_run failed! result:{pResult}");
 }
 else
 {
     Console.WriteLine($"rknn_run success!");
     pResult = RKNNAPI.rknn_outputs_get(rknn_context, io_num.n_output, out outputs, IntPtr.Zero);
     if (pResult < 0)
     {
         Console.WriteLine($"rknn_outputs_get failed! result:{pResult}");
     }
     else
     {
         if (outputs == null)
             Console.WriteLine("111111111111111111");
         Console.WriteLine($"rknn_outputs_get success!io_num.n_output:{io_num.n_output} result:{pResult} outputs.Length:{outputs.Length}");
         foreach (var t in outputs)
         {
             Console.WriteLine($"output[{t.index}] t.buf.ToInt64():{t.buf.ToString()} size:{t.size}");
         }
         if (outputs.Length > 0 && outputs[0].buf != IntPtr.Zero)
         {
             float scale_w = (float)width / img_width;
             float scale_h = (float)height / img_height;
             detect_result_group_t detect_result_group = new();
             List<float> out_scales = new List<float>();
             List<uint> out_zps = new List<uint>();
             for (int i = 0; i < io_num.n_output; ++i)
             {
                 out_scales.Add(output_attrs[i].scale);
                 out_zps.Add(output_attrs[i].zp);
             }
             var buf0 = GetBytesFromIntPtr(outputs[0].buf, (int)outputs[0].size);
             var buf1 = GetBytesFromIntPtr(outputs[1].buf, (int)outputs[1].size);
             var buf2 = GetBytesFromIntPtr(outputs[2].buf, (int)outputs[2].size);
             PostProcess(buf0, buf1, buf2, height, width,
 0.5f, 0.6f, scale_w, scale_h, out_zps, out_scales, ref detect_result_group);

             // Draw Objects
             string text;
             Color blue = Color.Blue;
             Color white = Color.White;
             for (int i = 0; i < detect_result_group.count; i++)
             {
                 detect_result_t det_result = detect_result_group.results[i];
                 text = $"{det_result.name} {det_result.prop:F2}";
                 Console.WriteLine($"{det_result.name} @ ({det_result.box.left} {det_result.box.top} {det_result.box.right} {det_result.box.bottom}) {det_result.prop:F2}");
                 int x1 = det_result.box.left;
                 int y1 = det_result.box.top;
                 int x2 = det_result.box.right;
                 int y2 = det_result.box.bottom;
                 //draw box
                 image.Mutate(x =>
                 {
                     x.DrawPolygon(blue, 1, new PointF[] { new PointF(x1, y1), new PointF(x2, y1), new PointF(x2, y2), new PointF(x1, y2) });
                     x.DrawText(text, font, white, new PointF(x1, y1 - 12));
                 });
             }
             image.SaveAsJpeg($"./Images/{Guid.NewGuid()}.jpg");

             var ret = RKNNAPI.rknn_outputs_release(rknn_context, io_num.n_output, outputs);
         }
     }
 }

 if (hObject.IsAllocated)
     hObject.Free();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions