rockchip-linux / rknpu

BSD 3-Clause "New" or "Revised" License
221 stars 62 forks source link

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

Open fengbozs opened 11 months ago

fengbozs commented 11 months ago

是否可以考虑提供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(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(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(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(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();
fengbozs commented 11 months ago

输出信息: root@EASY-EAI-NANO:/userdata/apps/test# dotnet TestConsoleApp.dll librknn_runtime version 1.7.3 (2e55827 build: 2022-08-25 10:45:32 base: 1131) rknn init result:0---4978904 rknn_query_sdk_version success! result:0 drv_version:System.Char[] api_version:System.Char[] rknn_query_in_out_num success! result:0 input_num:1 output_num:3 0Input------ images_283 RKNN_TENSOR_UINT8 RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 0Output------ Conv_Conv_279/out0_0 RKNN_TENSOR_UINT8 RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 1Output------ Conv_Conv_280/out0_1 RKNN_TENSOR_UINT8 RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC 2Output------ Conv_Conv_281/out0_2 RKNN_TENSOR_UINT8 RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC model is NCHW input fmt model input height=640, width=640, channel=3 rknn_inputs_set result:0 rknn_run success! 111111111111111111 Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. at TestConsoleApp.Program.Main(String[] args) in D:\BRCodes\AvaloniaApplication\TestConsoleApp\Program.cs:line 174 Aborted root@EASY-EAI-NANO:/userdata/apps/test#

eRaul commented 8 months ago

没有这样的计划