feat: working on adding abstractions
This commit is contained in:
+385
@@ -0,0 +1,385 @@
|
||||
root = true
|
||||
|
||||
# All files
|
||||
[*]
|
||||
indent_style = space
|
||||
|
||||
# Xml files
|
||||
[*.xml]
|
||||
indent_size = 2
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
|
||||
#### Core EditorConfig Options ####
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
|
||||
# New line preferences
|
||||
insert_final_newline = false
|
||||
|
||||
#### .NET Coding Conventions ####
|
||||
[*.{cs,vb}]
|
||||
|
||||
# Organize usings
|
||||
dotnet_separate_import_directive_groups = true
|
||||
dotnet_sort_system_directives_first = true
|
||||
file_header_template = unset
|
||||
|
||||
# this. and Me. preferences
|
||||
dotnet_style_qualification_for_event = false:silent
|
||||
dotnet_style_qualification_for_field = false:silent
|
||||
dotnet_style_qualification_for_method = false:silent
|
||||
dotnet_style_qualification_for_property = false:silent
|
||||
|
||||
# Language keywords vs BCL types preferences
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
|
||||
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_collection_initializer = true:suggestion
|
||||
dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_namespace_match_folder = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_object_initializer = true:suggestion
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
dotnet_style_prefer_auto_properties = true:suggestion
|
||||
dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
|
||||
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
|
||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
|
||||
# Field preferences
|
||||
dotnet_style_readonly_field = true:warning
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all:suggestion
|
||||
|
||||
# Suppression preferences
|
||||
dotnet_remove_unnecessary_suppression_exclusions = none
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
[*.cs]
|
||||
|
||||
# diagnostics
|
||||
dotnet_diagnostic.CA1303.severity = none
|
||||
dotnet_diagnostic.CA1707.severity = none
|
||||
dotnet_diagnostic.IDE0058.severity = none
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
dotnet_diagnostic.CA1515.severity = none
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||
csharp_style_prefer_not_pattern = true:suggestion
|
||||
csharp_style_prefer_pattern_matching = true:silent
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_anonymous_function = true:suggestion
|
||||
csharp_prefer_static_local_function = true:warning
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,file,const,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion
|
||||
csharp_style_prefer_readonly_struct = true:suggestion
|
||||
csharp_style_prefer_readonly_struct_member = true:suggestion
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_prefer_simple_using_statement = true:suggestion
|
||||
csharp_style_namespace_declarations = file_scoped:suggestion
|
||||
csharp_style_prefer_method_group_conversion = true:silent
|
||||
csharp_style_prefer_primary_constructors = true:suggestion
|
||||
csharp_style_prefer_top_level_statements = true:silent
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_prefer_tuple_swap = true:suggestion
|
||||
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:silent
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace:silent
|
||||
|
||||
#### C# Formatting Rules ####
|
||||
|
||||
# New line preferences
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
||||
#### Naming styles ####
|
||||
[*.{cs,vb}]
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces
|
||||
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces
|
||||
dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase
|
||||
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters
|
||||
dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase
|
||||
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods
|
||||
dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties
|
||||
dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.events_should_be_pascalcase.symbols = events
|
||||
dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
|
||||
dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
|
||||
dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
|
||||
dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
|
||||
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
|
||||
dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion
|
||||
dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields
|
||||
dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase
|
||||
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
|
||||
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
|
||||
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
|
||||
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
|
||||
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
|
||||
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
|
||||
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
|
||||
dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
|
||||
dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interfaces.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interfaces.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.enums.applicable_kinds = enum
|
||||
dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.enums.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.events.applicable_kinds = event
|
||||
dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.events.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.methods.applicable_kinds = method
|
||||
dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.methods.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.properties.applicable_kinds = property
|
||||
dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.properties.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.public_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_fields.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_fields.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_static_fields.required_modifiers = static
|
||||
|
||||
dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
|
||||
dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types_and_namespaces.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
|
||||
dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.type_parameters.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.local_variables.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_variables.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.local_variables.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.local_constants.applicable_kinds = local
|
||||
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.local_constants.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.parameters.applicable_kinds = parameter
|
||||
dotnet_naming_symbols.parameters.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.parameters.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_constant_fields.required_modifiers = const
|
||||
|
||||
dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
|
||||
dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
|
||||
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
|
||||
|
||||
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
|
||||
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
|
||||
dotnet_naming_symbols.local_functions.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.pascalcase.required_prefix =
|
||||
dotnet_naming_style.pascalcase.required_suffix =
|
||||
dotnet_naming_style.pascalcase.word_separator =
|
||||
dotnet_naming_style.pascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.ipascalcase.required_prefix = I
|
||||
dotnet_naming_style.ipascalcase.required_suffix =
|
||||
dotnet_naming_style.ipascalcase.word_separator =
|
||||
dotnet_naming_style.ipascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.tpascalcase.required_prefix = T
|
||||
dotnet_naming_style.tpascalcase.required_suffix =
|
||||
dotnet_naming_style.tpascalcase.word_separator =
|
||||
dotnet_naming_style.tpascalcase.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style._camelcase.required_prefix = _
|
||||
dotnet_naming_style._camelcase.required_suffix =
|
||||
dotnet_naming_style._camelcase.word_separator =
|
||||
dotnet_naming_style._camelcase.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.camelcase.required_prefix =
|
||||
dotnet_naming_style.camelcase.required_suffix =
|
||||
dotnet_naming_style.camelcase.word_separator =
|
||||
dotnet_naming_style.camelcase.capitalization = camel_case
|
||||
|
||||
dotnet_naming_style.s_camelcase.required_prefix = s_
|
||||
dotnet_naming_style.s_camelcase.required_suffix =
|
||||
dotnet_naming_style.s_camelcase.word_separator =
|
||||
dotnet_naming_style.s_camelcase.capitalization = camel_case
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.20.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="modnet.onnx" />
|
||||
<EmbeddedResource Include="rmbg.onnx" />
|
||||
<EmbeddedResource Include="u2net.onnx" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,47 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="Shouldly" Version="4.3.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.1">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<CollectCoverage>true</CollectCoverage>
|
||||
<CoverletOutput>./TestResults/coverage/</CoverletOutput>
|
||||
<CoverletOutputFormat>cobertura</CoverletOutputFormat>
|
||||
<Include>[BGR.Console]*</Include>
|
||||
<ExcludeByFile>**/Program.cs</ExcludeByFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="GenerateHtmlCoverageReport" AfterTargets="GenerateCoverageResultAfterTest">
|
||||
<Exec Command="reportgenerator -reports:./TestResults/coverage/*.xml -targetdir:./TestResults/coverage/report/ -reporttypes:Html_Dark" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<Using Include="Shouldly" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BGR.Console\BGR.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace BGR.Console.Tests.Unit;
|
||||
|
||||
public class ResourceManagerTests
|
||||
{
|
||||
private readonly ResourceManager _resourceManager = new();
|
||||
|
||||
[Fact]
|
||||
public void GetResource_WhenResourceExists_ItShouldReturnStream()
|
||||
{
|
||||
var resourceName = "u2net.onnx";
|
||||
|
||||
using var stream = _resourceManager.GetResource(resourceName);
|
||||
|
||||
stream.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetResource_WhenResourceDoesNotExist_ItShouldThrowException()
|
||||
{
|
||||
var resourceName = "nonexistent.onnx";
|
||||
|
||||
var act = () => _resourceManager.GetResource(resourceName);
|
||||
|
||||
act.ShouldThrow<FileNotFoundException>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
namespace BGR.Console.Tests.Unit;
|
||||
|
||||
public class TypeRegistrarTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_WhenCalled_ItShouldNotThrowShould()
|
||||
{
|
||||
var mockBuilder = new Mock<IHostBuilder>();
|
||||
|
||||
Should.NotThrow(() => new TypeRegistrar(mockBuilder.Object));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_WhenCalled_ItShouldReturnResolverAndBuildHost()
|
||||
{
|
||||
var mockHost = new Mock<IHost>();
|
||||
var mockBuilder = new Mock<IHostBuilder>();
|
||||
|
||||
mockBuilder
|
||||
.Setup(static b => b.Build())
|
||||
.Returns(mockHost.Object);
|
||||
|
||||
var registrar = new TypeRegistrar(mockBuilder.Object);
|
||||
|
||||
var resolver = registrar.Build();
|
||||
|
||||
resolver.ShouldBeOfType<TypeResolver>();
|
||||
mockBuilder.Verify(static b => b.Build(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Register_WhenCalledWithType_ItShouldAddToContainer()
|
||||
{
|
||||
var builder = Host.CreateDefaultBuilder();
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
registrar.Register(typeof(IService), typeof(ServiceImplementation));
|
||||
|
||||
using var host = builder.Build();
|
||||
var service = host.Services.GetService<IService>();
|
||||
|
||||
service.ShouldNotBeNull();
|
||||
service.ShouldBeOfType<ServiceImplementation>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RegisterInstance_WhenCalledWithInstance_ItShouldAddToContainer()
|
||||
{
|
||||
var builder = Host.CreateDefaultBuilder();
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
var instance = new ServiceImplementation();
|
||||
registrar.RegisterInstance(typeof(IService), instance);
|
||||
|
||||
using var host = builder.Build();
|
||||
var service = host.Services.GetService<IService>();
|
||||
|
||||
service.ShouldBeSameAs(instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RegisterLazy_WhenCalledWithFunc_ItShouldAddToContainer()
|
||||
{
|
||||
var builder = Host.CreateDefaultBuilder();
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
registrar.RegisterLazy(typeof(IService), static () => new ServiceImplementation());
|
||||
|
||||
using var host = builder.Build();
|
||||
var service = host.Services.GetService<IService>();
|
||||
|
||||
service.ShouldNotBeNull();
|
||||
service.ShouldBeOfType<ServiceImplementation>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RegisterLazy_WhenFuncIsNull_ItShouldThrow()
|
||||
{
|
||||
var builder = Host.CreateDefaultBuilder();
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
|
||||
Should.Throw<ArgumentNullException>(() => registrar.RegisterLazy(typeof(IService), null!));
|
||||
}
|
||||
|
||||
private interface IService { }
|
||||
private sealed class ServiceImplementation : IService { }
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
namespace BGR.Console.Tests.Unit;
|
||||
|
||||
public class TypeResolverTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_WhenCalledWithNullHost_ItShouldThrowArgumentNullException()
|
||||
{
|
||||
Should.Throw<ArgumentNullException>(static () => new TypeResolver(null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_WhenTypeIsNull_ItShouldReturnNull()
|
||||
{
|
||||
var mockHost = new Mock<IHost>();
|
||||
using var resolver = new TypeResolver(mockHost.Object);
|
||||
|
||||
var result = resolver.Resolve(null);
|
||||
|
||||
result.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_WhenCalledWithRegisteredType_ItShouldReturnAnInstance()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton(new TestService());
|
||||
|
||||
var mockHost = new Mock<IHost>();
|
||||
|
||||
mockHost
|
||||
.Setup(static h => h.Services)
|
||||
.Returns(services.BuildServiceProvider());
|
||||
|
||||
using var resolver = new TypeResolver(mockHost.Object);
|
||||
|
||||
var result = resolver.Resolve(typeof(TestService));
|
||||
|
||||
result.ShouldNotBeNull();
|
||||
result.ShouldBeOfType<TestService>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_WhenCalledWithUnregisteredType_ItShouldReturnNull()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var mockHost = new Mock<IHost>();
|
||||
|
||||
mockHost
|
||||
.Setup(static h => h.Services)
|
||||
.Returns(services.BuildServiceProvider());
|
||||
|
||||
using var resolver = new TypeResolver(mockHost.Object);
|
||||
|
||||
var result = resolver.Resolve(typeof(TestService));
|
||||
|
||||
result.ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_WhenCalled_ItShouldAlsoDisposeHost()
|
||||
{
|
||||
var mockHost = new Mock<IHost>();
|
||||
var resolver = new TypeResolver(mockHost.Object);
|
||||
|
||||
resolver.Dispose();
|
||||
|
||||
mockHost.Verify(static h => h.Dispose(), Times.Once);
|
||||
}
|
||||
|
||||
private sealed class TestService { }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
global using BGR.Console.Common;
|
||||
global using BGR.Console.Resources;
|
||||
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
|
||||
global using Moq;
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="$(AssemblyName).Tests" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.1" />
|
||||
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.20.1" />
|
||||
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
|
||||
<PackageReference Include="Spectre.Console" Version="0.49.1" />
|
||||
<PackageReference Include="Spectre.Console.Cli" Version="0.49.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Files\**\*" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace BGR.Console.Common;
|
||||
|
||||
internal static class HostBuilderExtensions
|
||||
{
|
||||
public static CommandApp BuildApp(this IHostBuilder builder)
|
||||
{
|
||||
var registrar = new TypeRegistrar(builder);
|
||||
var app = new CommandApp(registrar);
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace BGR.Console.Common;
|
||||
|
||||
internal class TypeRegistrar(IHostBuilder builder) : ITypeRegistrar
|
||||
{
|
||||
private readonly IHostBuilder _builder = builder;
|
||||
|
||||
public ITypeResolver Build()
|
||||
{
|
||||
return new TypeResolver(_builder.Build());
|
||||
}
|
||||
|
||||
public void Register(Type service, Type implementation)
|
||||
{
|
||||
_builder.ConfigureServices((_, services) => services.AddSingleton(service, implementation));
|
||||
}
|
||||
|
||||
public void RegisterInstance(Type service, object implementation)
|
||||
{
|
||||
_builder.ConfigureServices((_, services) => services.AddSingleton(service, implementation));
|
||||
}
|
||||
|
||||
public void RegisterLazy(Type service, Func<object> func)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(func);
|
||||
|
||||
_builder.ConfigureServices((_, services) => services.AddSingleton(service, _ => func()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace BGR.Console.Common;
|
||||
|
||||
internal class TypeResolver(IHost provider) : ITypeResolver, IDisposable
|
||||
{
|
||||
private readonly IHost _host = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
|
||||
public object? Resolve(Type? type)
|
||||
{
|
||||
return type is not null ? _host.Services.GetService(type) : null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_host.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,40 @@
|
||||
using System.Reflection;
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.File(
|
||||
formatter: new CompactJsonFormatter(),
|
||||
path: Path.Combine(AppContext.BaseDirectory, "logs", "log.jsonl"),
|
||||
rollingInterval: RollingInterval.Day
|
||||
)
|
||||
.Enrich.FromLogContext()
|
||||
.MinimumLevel.Verbose()
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Fatal)
|
||||
.CreateLogger();
|
||||
|
||||
using Microsoft.ML.OnnxRuntime;
|
||||
using Microsoft.ML.OnnxRuntime.Tensors;
|
||||
try
|
||||
{
|
||||
var appName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
Log.Information("Starting {AppName}", appName);
|
||||
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Png;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
await Host.CreateDefaultBuilder()
|
||||
.ConfigureLogging(static logging => logging.ClearProviders())
|
||||
.ConfigureServices(static (_, services) =>
|
||||
{
|
||||
services.AddSerilog();
|
||||
services.AddSingleton<IResourceManager, ResourceManager>();
|
||||
})
|
||||
.BuildApp()
|
||||
.RunAsync(args);
|
||||
|
||||
Log.Information("Stopping {AppName}", appName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Application terminated unexpectedly");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Log.CloseAndFlushAsync();
|
||||
}
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
@@ -21,13 +49,13 @@ var outputImagePath = Path.ChangeExtension(inputImagePath, null) + "_no_bg.png";
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = "BGR.Console.u2net.onnx";
|
||||
var resourceName = "BGR.Console.Resources.Files.rmbg.onnx";
|
||||
|
||||
using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new FileNotFoundException("Model not found in embedded resources.");
|
||||
var modelBytes = new byte[stream.Length];
|
||||
stream.ReadExactly(modelBytes);
|
||||
|
||||
using var image = Image.Load<Rgba32>(inputImagePath);
|
||||
using var image = await Image.LoadAsync<Rgba32>(inputImagePath);
|
||||
var inputTensor = CreateTensorInput(image);
|
||||
|
||||
using var options = new SessionOptions() { LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_ERROR };
|
||||
@@ -46,8 +74,8 @@ try
|
||||
|
||||
var encoder = new PngEncoder { CompressionLevel = PngCompressionLevel.BestCompression };
|
||||
|
||||
mask.Save(maskImagePath, encoder);
|
||||
bgRemoved.Save(outputImagePath, encoder);
|
||||
await mask.SaveAsync(maskImagePath, encoder);
|
||||
await bgRemoved.SaveAsync(outputImagePath, encoder);
|
||||
|
||||
Console.WriteLine($"Background removed and saved to {outputImagePath}");
|
||||
}
|
||||
@@ -57,11 +85,11 @@ catch (Exception ex)
|
||||
throw;
|
||||
}
|
||||
|
||||
static DenseTensor<float> CreateTensorInput(Image<Rgba32> image)
|
||||
static Tensor<float> CreateTensorInput(Image<Rgba32> image)
|
||||
{
|
||||
// U2Net expects input images to be 320x320. This is dependent on the model.
|
||||
const int targetWidth = 320;
|
||||
const int targetHeight = 320;
|
||||
const int targetWidth = 1024;
|
||||
const int targetHeight = 1024;
|
||||
|
||||
// ImageNet normalization parameters
|
||||
// source:
|
||||
@@ -204,4 +232,3 @@ static void WalkImage(int height, int width, Action<int, int> action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace BGR.Console.Removal;
|
||||
|
||||
internal interface IImage
|
||||
{
|
||||
int Width { get; }
|
||||
int Height { get; }
|
||||
void Resize(int width, int height);
|
||||
IPixel GetPixel(int x, int y);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace BGR.Console.Removal;
|
||||
|
||||
internal interface IPixel
|
||||
{
|
||||
float R { get; }
|
||||
float G { get; }
|
||||
float B { get; }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace BGR.Console.Removal;
|
||||
|
||||
internal interface ITensor<T>
|
||||
{
|
||||
int Height { get; }
|
||||
int Width { get; }
|
||||
void SetValue(int batch, int channel, int y, int x, T value);
|
||||
float GetValue(int batch, int channel, int y, int x);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace BGR.Console.Removal;
|
||||
|
||||
internal abstract class ImageProcessor
|
||||
{
|
||||
public abstract Task<ITensor<float>> CreateTensorInputAsync(Stream image, Model model);
|
||||
|
||||
public abstract Task<Stream> GenerateMaskAsync(OnnxTensor maskTensor, int width, int height);
|
||||
|
||||
public abstract Task<Stream> RemoveBackgroundAsync(Stream image, Stream mask);
|
||||
|
||||
protected static void WalkImage(int height, int width, Action<int, int> action)
|
||||
{
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
action(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
namespace BGR.Console.Removal.ImageSharp;
|
||||
|
||||
internal class ImageSharpProcessor : ImageProcessor
|
||||
{
|
||||
public override async Task<ITensor<float>> CreateTensorInputAsync(Stream image, Model model)
|
||||
{
|
||||
using var resized = await Image.LoadAsync<Rgba32>(image);
|
||||
resized.Mutate(x => x.Resize(model.InputWidth, model.InputHeight));
|
||||
|
||||
const int batchSize = 1;
|
||||
const int channels = 3;
|
||||
var tensor = new OnnxTensor(batchSize, channels, model.InputHeight, model.InputWidth);
|
||||
|
||||
WalkImage(resized.Height, resized.Width, (x, y) =>
|
||||
{
|
||||
var pixel = resized[x, y];
|
||||
tensor.SetValue(0, 0, y, x, model.NormalizeRed(pixel.R));
|
||||
tensor.SetValue(0, 1, y, x, model.NormalizeGreen(pixel.G));
|
||||
tensor.SetValue(0, 2, y, x, model.NormalizeBlue(pixel.B));
|
||||
});
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
public override async Task<Stream> GenerateMaskAsync(OnnxTensor maskTensor, int width, int height)
|
||||
{
|
||||
using var mask = new Image<Rgba32>(width, height);
|
||||
|
||||
using Image<Rgba32> tempMask = new(maskTensor.Width, maskTensor.Height);
|
||||
|
||||
const byte opaqueAlpha = 255;
|
||||
|
||||
WalkImage(maskTensor.Height, maskTensor.Width, (x, y) =>
|
||||
{
|
||||
var sigmoidValue = CalculateSigmoid(maskTensor.GetValue(0, 0, y, x));
|
||||
var normalizedValue = Normalize(sigmoidValue);
|
||||
var intensity = ConvertToGreyscale(normalizedValue);
|
||||
|
||||
tempMask[x, y] = new Rgba32(intensity, intensity, intensity, opaqueAlpha);
|
||||
});
|
||||
|
||||
tempMask.Mutate(x => x.Resize(width, height));
|
||||
|
||||
WalkImage(height, width, (x, y) => mask[x, y] = tempMask[x, y]);
|
||||
|
||||
var stream = new MemoryStream();
|
||||
await mask.SaveAsync(stream, new PngEncoder());
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
public override async Task<Stream> RemoveBackgroundAsync(Stream image, Stream mask)
|
||||
{
|
||||
var imageWithBg = await Image.LoadAsync<Rgba32>(image);
|
||||
var maskImage = await Image.LoadAsync<Rgba32>(mask);
|
||||
using var imageWithBgRemoved = new Image<Rgba32>(imageWithBg.Width, imageWithBg.Height);
|
||||
|
||||
const byte alphaThreshold = 20;
|
||||
var transparentPixel = new Rgba32(0, 0, 0, 0);
|
||||
|
||||
WalkImage(imageWithBg.Height, imageWithBg.Width, (x, y) =>
|
||||
{
|
||||
var sourcePixel = imageWithBg[x, y];
|
||||
var maskPixel = maskImage[x, y];
|
||||
|
||||
var alpha = maskPixel.R;
|
||||
|
||||
imageWithBgRemoved[x, y] = alpha > alphaThreshold
|
||||
? new Rgba32(sourcePixel.R, sourcePixel.G, sourcePixel.B, sourcePixel.A)
|
||||
: transparentPixel;
|
||||
});
|
||||
|
||||
var result = new MemoryStream();
|
||||
await imageWithBgRemoved.SaveAsync(result, new PngEncoder());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static float Normalize(float value)
|
||||
{
|
||||
const float binarizationThreshold = 0.5f;
|
||||
const float normalizationFactor = 2f;
|
||||
|
||||
return value > binarizationThreshold
|
||||
? (value - binarizationThreshold) * normalizationFactor
|
||||
: 0f;
|
||||
}
|
||||
|
||||
private static byte ConvertToGreyscale(float value)
|
||||
{
|
||||
const float maxIntensity = 255f;
|
||||
return (byte)(value * maxIntensity);
|
||||
}
|
||||
|
||||
private static float CalculateSigmoid(float x)
|
||||
{
|
||||
const float sigmoidScale = 1f;
|
||||
const float sigmoidShift = 1f;
|
||||
const float sigmoidDivisor = -1f;
|
||||
|
||||
return sigmoidScale / (sigmoidShift + MathF.Exp(sigmoidDivisor * x));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace BGR.Console.Removal.ImageSharp;
|
||||
|
||||
internal class SharpImage(Image<Rgba32> image) : IImage
|
||||
{
|
||||
private readonly Image<Rgba32> _image = image;
|
||||
|
||||
public int Width => _image.Width;
|
||||
public int Height => _image.Height;
|
||||
|
||||
public void Resize(int width, int height)
|
||||
{
|
||||
_image.Mutate(x => x.Resize(width, height));
|
||||
}
|
||||
|
||||
public IPixel GetPixel(int x, int y)
|
||||
{
|
||||
return new SharpPixel(_image[x, y]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace BGR.Console.Removal.ImageSharp;
|
||||
|
||||
internal class SharpPixel(Rgba32 pixel) : IPixel
|
||||
{
|
||||
private readonly Rgba32 _pixel = pixel;
|
||||
|
||||
public float R => _pixel.R;
|
||||
public float G => _pixel.G;
|
||||
public float B => _pixel.B;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace BGR.Console.Removal.Models;
|
||||
|
||||
internal class ModNetModel : Model
|
||||
{
|
||||
public override int InputWidth => 512;
|
||||
public override int InputHeight => 512;
|
||||
public override float RedNormalizationMean => 0.485f;
|
||||
public override float GreenNormalizationMean => 0.456f;
|
||||
public override float BlueNormalizationMean => 0.406f;
|
||||
public override float RedNormalizationStd => 0.229f;
|
||||
public override float GreenNormalizationStd => 0.224f;
|
||||
public override float BlueNormalizationStd => 0.225f;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace BGR.Console.Removal.Models;
|
||||
|
||||
internal abstract class Model
|
||||
{
|
||||
private const float PixelMax = 255f;
|
||||
public abstract int InputWidth { get; }
|
||||
public abstract int InputHeight { get; }
|
||||
public abstract float RedNormalizationMean { get; }
|
||||
public abstract float GreenNormalizationMean { get; }
|
||||
public abstract float BlueNormalizationMean { get; }
|
||||
public abstract float RedNormalizationStd { get; }
|
||||
public abstract float GreenNormalizationStd { get; }
|
||||
public abstract float BlueNormalizationStd { get; }
|
||||
|
||||
public float NormalizeRed(float value)
|
||||
{
|
||||
return Normalize(value, RedNormalizationMean, RedNormalizationStd);
|
||||
}
|
||||
|
||||
public float NormalizeGreen(float value)
|
||||
{
|
||||
return Normalize(value, GreenNormalizationMean, GreenNormalizationStd);
|
||||
}
|
||||
|
||||
public float NormalizeBlue(float value)
|
||||
{
|
||||
return Normalize(value, BlueNormalizationMean, BlueNormalizationStd);
|
||||
}
|
||||
|
||||
private static float Normalize(float value, float mean, float std)
|
||||
{
|
||||
return ((value / PixelMax) - mean) / std;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
namespace BGR.Console.Removal.Models;
|
||||
|
||||
internal class RmbgModel : Model
|
||||
{
|
||||
public override int InputWidth => 1024;
|
||||
public override int InputHeight => 1024;
|
||||
public override float RedNormalizationMean => 0.485f;
|
||||
public override float GreenNormalizationMean => 0.456f;
|
||||
public override float BlueNormalizationMean => 0.406f;
|
||||
public override float RedNormalizationStd => 0.229f;
|
||||
public override float GreenNormalizationStd => 0.224f;
|
||||
public override float BlueNormalizationStd => 0.225f;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace BGR.Console.Removal.Models;
|
||||
|
||||
internal class U2NetModel : Model
|
||||
{
|
||||
public override int InputWidth => 320;
|
||||
public override int InputHeight => 320;
|
||||
public override float RedNormalizationMean => 0.485f;
|
||||
public override float GreenNormalizationMean => 0.456f;
|
||||
public override float BlueNormalizationMean => 0.406f;
|
||||
public override float RedNormalizationStd => 0.229f;
|
||||
public override float GreenNormalizationStd => 0.224f;
|
||||
public override float BlueNormalizationStd => 0.225f;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace BGR.Console.Removal.Onnx;
|
||||
|
||||
public class OnnxTensor(
|
||||
int batchSize,
|
||||
int channels,
|
||||
int height,
|
||||
int width
|
||||
) : ITensor<float>
|
||||
{
|
||||
private readonly DenseTensor<float> _tensor =
|
||||
new([batchSize, channels, height, width]);
|
||||
|
||||
public int Height => _tensor.Dimensions[2];
|
||||
|
||||
public int Width => _tensor.Dimensions[3];
|
||||
|
||||
public void SetValue(
|
||||
int batch,
|
||||
int channel,
|
||||
int y,
|
||||
int x,
|
||||
float value
|
||||
)
|
||||
{
|
||||
_tensor[batch, channel, y, x] = value;
|
||||
}
|
||||
|
||||
public float GetValue(
|
||||
int batch,
|
||||
int channel,
|
||||
int y,
|
||||
int x
|
||||
)
|
||||
{
|
||||
return _tensor[batch, channel, y, x];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace BGR.Console.Resources;
|
||||
|
||||
internal interface IResourceManager
|
||||
{
|
||||
Stream GetResource(string resourceName);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
namespace BGR.Console.Resources;
|
||||
|
||||
internal sealed class ResourceManager : IResourceManager
|
||||
{
|
||||
public Stream GetResource(string resourceName)
|
||||
{
|
||||
var name = $"{nameof(BGR)}.{nameof(Console)}.{nameof(Resources)}.Files.{resourceName}";
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var names = assembly.GetManifestResourceNames();
|
||||
var stream = assembly.GetManifestResourceStream(name);
|
||||
return stream ?? throw new FileNotFoundException("Model not found in embedded resources.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
global using System.Reflection;
|
||||
|
||||
global using BGR.Console.Common;
|
||||
global using BGR.Console.Removal.Models;
|
||||
global using BGR.Console.Removal.Onnx;
|
||||
global using BGR.Console.Resources;
|
||||
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using Microsoft.Extensions.Logging;
|
||||
global using Microsoft.ML.OnnxRuntime;
|
||||
global using Microsoft.ML.OnnxRuntime.Tensors;
|
||||
|
||||
global using Serilog;
|
||||
global using Serilog.Events;
|
||||
global using Serilog.Formatting.Compact;
|
||||
|
||||
global using SixLabors.ImageSharp;
|
||||
global using SixLabors.ImageSharp.Formats.Png;
|
||||
global using SixLabors.ImageSharp.PixelFormats;
|
||||
global using SixLabors.ImageSharp.Processing;
|
||||
|
||||
global using Spectre.Console.Cli;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BGR.Console", "BGR.Console\BGR.Console.csproj", "{2630F4B7-8188-40DF-BFF0-84B2EA8C9994}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BGR.Console.Tests", "BGR.Console.Tests\BGR.Console.Tests.csproj", "{C5F69AD0-2CE5-4961-A74D-194CF6D812CA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2630F4B7-8188-40DF-BFF0-84B2EA8C9994}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2630F4B7-8188-40DF-BFF0-84B2EA8C9994}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2630F4B7-8188-40DF-BFF0-84B2EA8C9994}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2630F4B7-8188-40DF-BFF0-84B2EA8C9994}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C5F69AD0-2CE5-4961-A74D-194CF6D812CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C5F69AD0-2CE5-4961-A74D-194CF6D812CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C5F69AD0-2CE5-4961-A74D-194CF6D812CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C5F69AD0-2CE5-4961-A74D-194CF6D812CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<AnalysisMode>All</AnalysisMode>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user