Function to encode image with dlib with c# - c#

I'm trying to make a function with c# with fn project, I did this job with an Dockerized linux containerized API with Visual Studio 2022 and it works great.
The problem is, when I try to make the same with fn on a VM with Centos 9 it doesn't work and I dont know how to view the errors/exceptions. The only message I get is:
{"message": "error receiving function response"}
I modify my Dockerfile like next
FROM fnproject/dotnet:6.0-1.0.9-dev as build-stage
WORKDIR /function
COPY . .
RUN dotnet sln add src/Function/Function.csproj
RUN dotnet build -c Release
RUN dotnet publish src/Function/Function.csproj -c Release -o out
FROM fnproject/dotnet:6.0-1.0.9
WORKDIR /function
COPY --from=build-stage /function/out/ /function/
ENTRYPOINT ["dotnet", "Function.dll"]
CMD ["Function:Encoder:encode"]
And I show my func.yaml
schema_version: 20180708
name: encode-image
version: 0.0.133
runtime: dotnet6.0
build_image: fnproject/dotnet:6.0-1.0.9-dev
run_image: fnproject/dotnet:6.0-1.0.9
cmd: Function:Encoder:encode
entrypoint: dotnet Function.dll
memory: 2048
timeout: 300
triggers:
- name: encode-image
type: http
source: /api/v1/encode-image
And my Function.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<!--Nullable>enable</Nullable-->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fnproject.Fn.Fdk" Version="1.0.9" />
<PackageReference Include="DlibDotNet" Version="19.21.0.20220724" />
<PackageReference Include="DlibDotNet.Extensions" Version="19.18.0.20200428" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="12.2.2" />
<PackageReference Include="Magick.NET.Core" Version="12.2.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\dlib\dlib_face_recognition_resnet_model_v1.dat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Assets\dlib\shape_predictor_5_face_landmarks.dat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
I was trying to focus the code which generates the problem and I think is related with next:
detector = Dlib.GetFrontalFaceDetector();
shapePredictor = ShapePredictor.Deserialize("Assets/dlib/shape_predictor_5_face_landmarks.dat");
net = DlibDotNet.Dnn.LossMetric.Deserialize("Assets/dlib/dlib_face_recognition_resnet_model_v1.dat");
And when I call the function with Postman I get:
Dont know how to discover the problem. I think is realted to the load of .dat files or some time the fn framework waits or I dont know.
At last, my method which is called:
public string encode(string strRequest)
{
// Lets generate basic response
Dictionary<string, object> mapResponse = new Dictionary<string, object>();
//List<string> lstErrors = new List<string>();
try
{
JObject jsonRequest = new JObject();
jsonRequest = JObject.Parse(strRequest);
// Lets validate options from request
Dictionary<string, object> mapRequest = validateParameters(jsonRequest);
// Lets get valid parameters
Dictionary<string, object> mapParameters = (Dictionary<string, object>)mapRequest["parameters"];
// If debug mode is true, then add debug info
if (((bool)mapParameters["debug"]) == true) mapResponse["debugging"] = mapParameters;
// Lets form the response
mapResponse["errors"] = mapRequest["errors"];
mapResponse["result"] = string.Empty;
// If there are not errors with parameters and their values then calculate encoding
if (((List<string>) mapRequest["errors"]).Count == 0)
{
// Thinking in future updates, we are going to use a factory
IEncoder encoder = EncoderFactory.createEncoder((string)mapParameters["algorithm"]);
// Lets add the resulting object to the response
mapResponse["result"] = encoder.Encode(mapParameters);
//if(((Encoder_FaceRecognition) encoder).resourceLoaded==true) return "OK";
//return "NOK";
}
}
catch (System.Exception exception)
{
((List<string>)mapResponse["errors"]).Insert(0, "<ERROR> Some exception has occurred." + exception.StackTrace);
((List<string>)mapResponse["errors"]).Insert(0, "<ERROR> Some exception has occurred." + exception.Message);
}
return "<EXITO>";
//return JsonConvert.SerializeObject( mapResponse );
}

Related

.NET gRPC - File not found, import proto was not found or had errors, enum is not defined

I am quite new to the gRPC world and I can't understand and build the project because it is saying that file is not found and the import is not correct. I want to make the models reusable.
greet.proto file here:
syntax = "proto3";
option csharp_namespace = "DemoAppGrpc";
package greet;
import "Enums/gameType.proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
GameType gameType = 2;
}
message HelloReply {
string message = 1;
}
gameType.proto file type here:
syntax = "proto3";
option csharp_namespace = "DemoAppGrpc";
package greet;
enum GameType {
None = 0;
Open = 1;
Free = 2;
}
My project/folder structure that I want to have:
And my project solution file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<Protobuf Include="Protos\*.proto" GrpcServices="Server">
<GrpcServices>Server</GrpcServices>
<Access>Public</Access>
<ProtoCompile>True</ProtoCompile>
<CompileOutputs>True</CompileOutputs>
<OutputDir>obj\Debug\net6.0\</OutputDir>
<Generator>MSBuild:Compile</Generator>
</Protobuf>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.40.0" />
</ItemGroup>
</Project>
So how can I achieve to import nested files?

Operation returned an invalid status code 'BadRequest' - Microsoft.Azure.Management.ResourceGraph

Whenever var response line executes it will throw an exception that states
Operation returned an invalid status code 'BadRequest'
The same request that I did in Azure Resource Graph Explorer worked as expected. But for some odd reason, when I do it in a .net console application running a .net 6 framework it tells me its a bad request when in fact it is the correct request. However, after displaying that error it says Principal used: IsAuthenticated:True Type:User TenantId: xxxxx UserPrincipalName: xxxx
Packages installed:
<PackageReference Include="Microsoft.Azure.Management.ResourceGraph" Version="2.1.0" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.6.2" />
Program.cs
using Microsoft.Azure.Management.ResourceGraph;
using Microsoft.Azure.Management.ResourceGraph.Models;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Rest;
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
RunResourceGraphQuery(azureServiceTokenProvider).Wait();
if (azureServiceTokenProvider.PrincipalUsed != null)
{
Console.WriteLine($"{Environment.NewLine}Principal used: {azureServiceTokenProvider.PrincipalUsed}");
}
Console.ReadLine();
static async Task RunResourceGraphQuery(AzureServiceTokenProvider azureServiceTokenProvider)
{
Console.WriteLine($"{Environment.NewLine}{Environment.NewLine}Please enter the subscription Id");
var subscriptionId = Console.ReadLine();
List<string> subscriptions = new();
subscriptions.Add(subscriptionId);
try
{
var tokenCredentials = new TokenCredentials(await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/").ConfigureAwait(false));
var resourceGraphClient = new ResourceGraphClient(tokenCredentials);
var userQueryRequest = new QueryRequest(subscriptions: subscriptions, query: "resources | project name, ['type'] | limit 5", null, null);
var response = resourceGraphClient.Resources(userQueryRequest);
Console.WriteLine(response);
}
catch (Exception exp)
{
Console.WriteLine($"Error message: {exp.Message}");
}
}
I have tried in my environment to recreate the above issue ,and i get the same issue as you are getting.
Created a new project using Console app with .net6 and copied your code to my local .
Installed nuget packages :-
Microsoft.Azure.Management.ResourceGraph" Version="2.1.0"
Microsoft.Azure.Services.AppAuthentication" Version="1.6.2"
This is my .csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Management.ResourceGraph" Version="2.1.0" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.6.2" />
</ItemGroup>
</Project>
When i tried with your code i get Operation returned an invalid status code 'BadRequest':
After changing the query parameter type query: "resources | project name, ['type'] | limit 5" to this query: "Resources | project name, type | limit 5"
Program.cs:-
using Microsoft.Azure.Management.ResourceGraph;
using Microsoft.Azure.Management.ResourceGraph.Models;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Rest;
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
RunResourceGraphQuery(azureServiceTokenProvider).Wait();
if (azureServiceTokenProvider.PrincipalUsed != null)
{
Console.WriteLine($"{Environment.NewLine}Principal used: {azureServiceTokenProvider.PrincipalUsed}");
}
Console.ReadLine();
static async Task RunResourceGraphQuery(AzureServiceTokenProvider azureServiceTokenProvider)
{
Console.WriteLine($"{Environment.NewLine}{Environment.NewLine}Please enter the subscription Id");
var subscriptionId = Console.ReadLine();
List<string> subscriptions = new();
subscriptions.Add(subscriptionId);
try
{
var tokenCredentials = new TokenCredentials(await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/").ConfigureAwait(false));
var resourceGraphClient = new ResourceGraphClient(tokenCredentials);
var userQueryRequest = new QueryRequest(subscriptions: subscriptions, query: "Resources | project name, type | limit 5", null, null);
var response = resourceGraphClient.Resources(userQueryRequest);
Console.WriteLine(response);
}
catch (Exception exp)
{
Console.WriteLine($"Error message: {exp.Message}");
}
}
Its working fine at my end:
Still if you are getting the same issue please refer this Microsoft Documentation:Run your first Resource Graph query using .NET Core
For more information refer this MICROSOFT PLAYGROUND : Connecting to the Resource Graph Client via the Resource Graph SDK

ML.NET ImageClassification crash on macOS

I am about to figure out ML.NET and startet with an Microsoft Example which is linked down here:
https://learn.microsoft.com/en-us/dotnet/machine-learning/tutorials/image-classification-api-transfer-learning
I did everything as explained (creating assets-Dir and downloading files etc.) but when I run the Application I always run into a Problem that dotnet crashes away. I can't catch it with "try-catch".
My Code is:
var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../"));
var workspaceRelativePath = Path.Combine(projectDirectory, "workspace");
var assetsRelativePath = Path.Combine(projectDirectory, "assets");
MLContext mlContext = new MLContext();
IEnumerable<ImageData> images = LoadImagesFromDirectory(folder: assetsRelativePath, useFolderNameAsLabel: true);
IDataView imageData = mlContext.Data.LoadFromEnumerable(images);
IDataView shuffledData = mlContext.Data.ShuffleRows(imageData);
var preprocessingPipeline = mlContext.Transforms.Conversion.MapValueToKey(
inputColumnName: "Label",
outputColumnName: "LabelAsKey")
.Append(mlContext.Transforms.LoadRawImageBytes(
outputColumnName: "Image",
imageFolder: assetsRelativePath,
inputColumnName: "ImagePath"));
IDataView preProcessedData = preprocessingPipeline
.Fit(shuffledData)
.Transform(shuffledData);
TrainTestData trainSplit = mlContext.Data.TrainTestSplit(data: preProcessedData, testFraction: 0.3);
TrainTestData validationTestSplit = mlContext.Data.TrainTestSplit(trainSplit.TestSet);
IDataView trainSet = trainSplit.TrainSet;
IDataView validationSet = validationTestSplit.TrainSet;
IDataView testSet = validationTestSplit.TestSet;
var classifierOptions = new ImageClassificationTrainer.Options()
{
FeatureColumnName = "Image",
LabelColumnName = "LabelAsKey",
ValidationSet = validationSet,
Arch = ImageClassificationTrainer.Architecture.ResnetV2101,
MetricsCallback = (metrics) => Console.WriteLine(metrics),
TestOnTrainSet = false,
ReuseTrainSetBottleneckCachedValues = true,
ReuseValidationSetBottleneckCachedValues = true
};
var trainingPipeline = mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions)
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
As soon as I reach the last line:
mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions)
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
The App crash and I don't see any error. If I copy the same code onto my Windows-System it's working fine.
I am working with macOS Monterey on my MacBook Pro M1.
ML-Nuget-Packages are Installed in Version 1.6 with Tensorflow-Redist-Package-Version 2.3.1
Do you guys have any idea what's going on there or how can I troubleshoot it?
UPDATE (.csproj-File):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Remove="Microsoft.ML.Vision" />
<None Remove="Microsoft.ML.ImageAnalytics" />
<None Remove="Microsoft.ML" />
<None Remove="SciSharp.TensorFlow.Redist" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ML.Vision" Version="1.6.0" />
<PackageReference Include="Microsoft.ML.ImageAnalytics" Version="1.6.0" />
<PackageReference Include="Microsoft.ML" Version="1.6.0" />
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.3.1" />
</ItemGroup>
</Project>
UPDATE
with the newly released Visual Studio 2022 for Mac Version it's now possible to catch the Exception:
Unable to load shared library 'tensorflow' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(libtensorflow, 0x0001): tried: 'libtensorflow' (no such file), '/usr/local/lib/libtensorflow' (no such file)
So obviously it cannot find the tensorflowlib. I will try to install the lib by myself now.

How do I replace Database.ExecuteSqlQuery when changing TargetFramework away from.NetCore2.1

I have the following which was working fine in .NetCore2.1 with SDKs
Microsoft.AspNetCore.App(2.1.1)
Microsoft.NetCore.App(2.1.0)
My code is
public static int TransitTime(string postcode, ApiDbContext con)
{
var query = "SELECT top 1 Mins from Transit where postcode = #Postcode order by mins desc;";
var p1 = new SqlParameter("#Postcode",postcode);
var result = 0;
using (var dr = con.Database.ExecuteSqlQuery(query,p1))
{
var reader = dr.DbDataReader;
while (reader.Read()) result = (int)reader[0];
}
return Convert.ToInt32(result);
}
Hovering over the word Database I could see it was in
Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade
I don't see a specific reference to
Microsoft.EntityFrameworkCore.Infrastructure
It is documented as being part of Entity Framework Core 2.1
inside either SDK so I wonder how it is referenced.
However I needed to add a reference to a Framework 4.7.2 dll
So I switched to the following project file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
<ApplicationIcon />
<StartupObject />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\SBD.Common.csproj" />
</ItemGroup>
</Project>
Now I get an error
CS1061 'DatabaseFacade' does not contain a definition for
'ExecuteSqlQuery'
I tried looking form Microsoft.EntityFrameworkCore.Infrastructure in Nuget Manage Packages for Solution but it does not show.
Looking at this question I decided to try using .FromSQl instead.
I found help in the docs but it does not explain how return non entity types.
How do I do that?
After reading the end of this link I am trying
public static int TransitTime(string postcode, ApiDbContext con)
{
var query = "SELECT top 1 Mins from Transit where postcode = #Postcode order by mins desc;";
var p1 = new SqlParameter("#Postcode", postcode);
var result = 0;
using (var command = con.Database.GetDbConnection().CreateCommand())
{
command.CommandText = query;
command.Parameters.Add(p1);
con.Database.OpenConnection();
using (var reader = command.ExecuteReader())
{
while (reader.Read()) result = (int)reader[0];
}
}
return Convert.ToInt32(result);
}
I see that this is using an extension method in Microsoft.EntityFrameworkCore.Infrastructure

Release DLL after creation in BuildManager

I have written an C# WPF Application to compile code during runtime. The application does basically the following steps
click button [Compile stuff]
Create code files via StreamWriter
Build code files using the Microsoft.Build.Execution.BuildManager class
Uses reflection to access the DLL file (Assembly.LoadFrom(filePath))
creates an instanz of the class contained in the dll (assembly.CreateInstance(NamespaceName + "." + ClassName))
I works fine, but only once (I need to restart the application to do it again)
This is what happens during the next execution
click button [Compile stuff]
Create code files via StreamWriter
Build code files using the Microsoft.Build.Execution.BuildManager class
->Produces an error saying that the DLL file is locked.
The process cannot access the file 'DLL\generatedflexform.dll' because
it is being used by another process
The problem doesn't occur when I leave out step 2 because then the code files are the same. Therefore the BuildManager doesn't recreate/copy the dll.
I need to figure out how to release the DLL after the BuildManager has done his job. This is because the code files are likely to change very often and otherwise i have to close and re-open the application for every code change.
EDIT: My first thought was that the BuildManager causes the locking but this is not the case.
I rather think the locking happens when I try to load the DLL. I will try the Shadow Copy think (as mentioned by #granadaCoder).
private Window LoadWindowFromDll(string filePathToDll)
{
var assembly = Assembly.LoadFrom(filePathToDll);
var window = assembly.CreateInstance(NamespaceName + "." + ClassName) as Window;
return window;
}
Solution:
I had to change the LoadWindowFromDllmethod to avoid the DLL locking
private Window LoadWindowFromDll(string filePathToDll)
{
byte[] readAllBytes = File.ReadAllBytes(filePathToDll);
Assembly assembly = Assembly.Load(readAllBytes);
var window = assembly.CreateInstance(NamespaceName + "." + ClassName) as Window;
return window;
}
But somehow the pdb file was locked which causes the build to failed when I try to execute it twice.
I fixed this behavior by adding one line to my build file:
<DebugType>none</DebugType>
Here is the complete build file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<AssemblyName>generatedflexform</AssemblyName>
<OutputPath>DLL\</OutputPath>
<OutputType>Library</OutputType>
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Page Include="MyForm.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="MyForm.xaml.cs">
<DependentUpon>MyForm.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
And here comes the method which does the compile magic>
public Window BuildXamlWindowFromStrings(string xaml, string codeBehind)
{
//Erstellen der Codefiles (XAML und CodeBehind)
this.CreateCodeFile(codeBehind);
this.CreateXamlFile(xaml);
//Erstellen der project file
this.CreateProjectFile();
//Build der DLL
//using (var buildManager = BuildManager.DefaultBuildManager)
using (var buildManager = new BuildManager())
{
var result = buildManager.Build(this.CreateBuildParameters(), this.CreateBuildRequest());
if (result.OverallResult == BuildResultCode.Success)
{
return this.LoadWindowFromDll(FolderPath + DllRelativeFilePath + NamespaceName + DllFileExtension);
}
}
//Error handling
var stringbuilder = new StringBuilder();
using (var reader = new StreamReader(DebuggerLogFileName))
{
stringbuilder.Append(reader.ReadToEnd());
}
throw new CompilerException(stringbuilder.ToString());
}
Helper Methods:
private BuildParameters CreateBuildParameters()
{
var projectCollection = new ProjectCollection();
var buildLogger = new FileLogger { Verbosity = LoggerVerbosity.Detailed, Parameters = "logfile=" + DebuggerLogFileName };
var buildParameters = new BuildParameters(projectCollection) { Loggers = new List<ILogger>() { buildLogger } };
return buildParameters;
}
private BuildRequestData CreateBuildRequest()
{
var globalProperties = new Dictionary<string, string>();
var buildRequest = new BuildRequestData(FolderPath + ProjectFileName, globalProperties, null,
new string[] { "Build" }, null, BuildRequestDataFlags.ReplaceExistingProjectInstance);
return buildRequest;
}
Check out "Shadow Copying".
Shadow copying enables assemblies that are used in an application domain to be updated without unloading the application domain. This is particularly useful for applications that must be available continuously.
http://msdn.microsoft.com/en-us/library/ms404279.aspx
See also:
http://gotchahunter.net/2010/12/net-how-do-you-load-an-assembly-programmatically-and-avoid-a-file-lock/
and
http://blogs.msdn.com/b/junfeng/archive/2004/02/09/69919.aspx

Categories

Resources