0%

Prism的核心功能之一就是支持模块化应用程序开发(Modular Application Development),并且在运行时对各个模块进行动态管理。

使用Prism进行模块化开发首先要了解几个概念:

1.Module: Module是一些逻辑上相关的程序集或者资源文件的集合,在Silverlight程序中通常以xap文件为单位存在。而每一个Module中都需要有一个负责进行初始化工作以及与系统进行集成的角色,它需要实现IModule接口。IModule接口中只有一个Initialize方法,一方面这个接口将这个工程标记为一个Module,另一方面你可以在Initialize方法中实现一些逻辑,比如向容器中注册一些Service,或者将视图集成到程序中等等。

2.ModuleInfo: 在创建了一个Module之后,需要通知Prism这个Module的存在,也就是要注册一下。在Prism中,Module是以ModuleInfo的形式存在的。ModuleInfo记录了Module的信息,ModuleName属性是Module的标识符,相当于Module的ID;ModuleType是Module的AssemblyQualifiedName;DependsOn属性是该Module依赖的其它Module的ModuleName的集合,在加载该Module时,如果有依赖项没有加载的话,会先将依赖项加载;InitializationMode,有两种情况——WhenAvailable和OnDemand,当选择了WhenAvailable时,该Module会在程序启动时自动加载,如果选择了OnDemand,则会按需加载,默认情况下是WhenAvailable;Ref,存储该Module的位置,如XXX.xap;State,定义了Module从注册到加载到初始化的整个过程中的状态。

3.ModuleCatalog: ModuleCatalog实现了IModuleCatalog接口,它是ModuleInfo的容器,保存着系统中所有Module的信息,不仅会管理哪些Module需要加载,什么时候加载以什么顺序加载等问题,还要检查各个Module之间是否存在着循环依赖、是否有重复的Module等等。ModuleCatalog提供了含参构造方法和AddModule方法,可以通过代码将Module注册进去,同时也可以在xaml文件中配置好Module,然后通过ModuleCatalog.CreateFromXaml方法来加载。

4.ModuleManager: ModuleManager实现了IModuleManager接口。顾名思义就是管理Module的类。IModuleManager中含有两个方法和两个事件:Run方法会将所有InitializationMode为WhenAvailable的Module加载,然后进行初始化,初始化的工作委托给了IModuleInitializer来完成,它会获取到Module类(上面提到的实现了IModule接口的类)的实例,然后调用其Initialize方法。LoadModule方法用来加载InitializationMode为OnDemand的Module。两个事件分别用来通知下载Module的进度变化以及Module加载完成。

下面用一个示例程序来说明如何在Prism中进行模块化程序开发。

1.创建一个Silverlight Application,叫做PrismModule。

2.在Solution中添加三个Silverlight Application,分别叫做ModuleA, ModuleB, ModuleC。然后删除这三个工程中的App文件和MainPage文件。

3.在ModuleA工程下添加一个UserControl,叫做ViewA,然后再添加一个类,叫做ModuleA。并添加Microsoft.Practices.Prism和Microsoft.Practices.ServiceLocation引用。下面是ViewA和ModuleA的代码:

1
2
3
4
5
6
7
8
9
10
11
12
<UserControl x:Class="ModuleA.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="Module A" FontSize="22" />
</Grid>
</UserControl>
1
2
3
4
5
6
public class ModuleA : IModule
{
public void Initialize()
{
}
}

4.对ModuleB和ModuleC重复做步骤3的操作,只是将文本改成相应模块。

5.在PrismModule中添加对ModuleA、ModuleB、ModuleC、Prism、UnityExtensions还有Unity for Silverlight的引用,然后创建Shell和Bootstrapper。添加一个UserControl,叫做Shell;再添加一个类,叫做Bootstrapper。

Shell代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<UserControl x:Class="PrismModule.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">

<StackPanel Margin="50">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Border VerticalAlignment="Top" BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionA" />
</Border>
<Border VerticalAlignment="Top" BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionB" />
</Border>
<StackPanel>
<Border BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionC" />
</Border>
<Button Content="Load Module C" Click="LoadModuleC" Width="120" Height="25" />
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

Shell.xaml.cs代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<UserControl x:Class="PrismModule.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="800">

<StackPanel Margin="50">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Border VerticalAlignment="Top" BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionA" />
</Border>
<Border VerticalAlignment="Top" BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionB" />
</Border>
<StackPanel>
<Border BorderBrush="Red" BorderThickness="2" Width="200" Height="100">
<ContentControl prism:RegionManager.RegionName="RegionC" />
</Border>
<Button Content="Load Module C" Click="LoadModuleC" Width="120" Height="25" />
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

Bootstrapper代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return this.Container.TryResolve<Shell>();
}

protected override void InitializeShell()
{
App.Current.RootVisual = (UIElement)this.Shell;
}

protected override IModuleCatalog CreateModuleCatalog()
{
return new ModuleCatalog();
}

protected override void ConfigureModuleCatalog()
{
Type typeA = typeof(ModuleA.ModuleA);
ModuleInfo moduleA = new ModuleInfo
{ // ModuleA没有设置InitializationMode,默认为WhenAvailable
ModuleName = typeA.Name,
ModuleType = typeA.AssemblyQualifiedName,
};

Type typeB = typeof(ModuleB.ModuleB);
ModuleInfo moduleB = new ModuleInfo
{
ModuleName = typeB.Name,
ModuleType = typeB.AssemblyQualifiedName,
InitializationMode = InitializationMode.OnDemand,
};

Type typeC = typeof(ModuleC.ModuleC);
ModuleInfo moduleC = new ModuleInfo
{
ModuleName = typeC.Name,
ModuleType = typeC.AssemblyQualifiedName,
InitializationMode = InitializationMode.OnDemand,
// ModuleC依赖于ModuleB
DependsOn = new Collection<string> { moduleB.ModuleName },
};

this.ModuleCatalog.AddModule(moduleA);
this.ModuleCatalog.AddModule(moduleB);
this.ModuleCatalog.AddModule(moduleC);
}
}

将App.xaml.cs中的Application_Startup方法改为

1
2
3
4
5
private void Application_Startup(object sender, StartupEventArgs e)
{
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
}

6.现在已经有了Region,需要将各个Module中的View填充到Region中。修改ModuleA,ModuleB和ModuleC的Initialize方法。

1
2
3
4
5
public void Initialize()
{
ServiceLocator.Current.GetInstance<IRegionManager>().
RegisterViewWithRegion("RegionA", typeof(ViewA));
}

将其中的A改为相应的字母。运行程序,结果如下:

image

我们点击按钮来加载ModuleC,因为ModuleC依赖于ModuleB,所以ModuleB也一块儿加载出来了。但是这与我们预期的效果不太一致。因为一共只load了一个xap文件,用WinRAR打开看一下,发现三个Module的程序集都在其中。

image

在Silverlight程序中,模块化程序开发应该不仅仅体现在开发时的模块化,运行时也应该是模块化的。比如ModuleA在程序加载时就load出来,但是ModuleB和ModuleC则是在点击了按钮后才load出来的,换句话说,在没点按钮前就不应该将ModuleB和ModuleC的程序集加载进来。现在由于PrismModule项目引用了三个Module,所以程序集会被一块打包进xap文件中。我们修改一下,将对ModuleB和ModuleC的引用的Copy Local属性设置为false:

imageimage

重新编译一下,再次查看xap文件,发现已经没有了ModuleB和ModuleC。

image

运行程序,报错。很简单,因为我们在Bootstrapper中用到了ModuleB和ModuleC,缺少了这两个dll,程序没法运行。为了解决这个问题,我们把初始化ModuleCatalog的过程改一下,不使用代码,而是使用配置文件。在Silverlight中,Prism支持使用xaml文件作为配置文件。下面在PrismModule工程下新建一个资源文件,ModuleCatalog.xaml。内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Modularity:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:Modularity="clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism">

<Modularity:ModuleInfo Ref="ModuleA.xap" ModuleName="ModuleA"
ModuleType="ModuleA.ModuleA, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

<Modularity:ModuleInfo Ref="ModuleB.xap" ModuleName="ModuleB" InitializationMode="OnDemand"
ModuleType="ModuleB.ModuleB, ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

<Modularity:ModuleInfo Ref="ModuleC.xap" ModuleName="ModuleC" InitializationMode="OnDemand"
ModuleType="ModuleC.ModuleC, ModuleC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<Modularity:ModuleInfo.DependsOn>
<sys:String>ModuleB</sys:String>
</Modularity:ModuleInfo.DependsOn>
</Modularity:ModuleInfo>
</Modularity:ModuleCatalog>

这里大体和用代码写一致,只不过Ref属性里要写明该Module对应的是哪个xap包。Prism在Silverlight程序中使用一个叫做XapModuleTypeLoader的类来加载Module,在将Module下载之后会获取AppManifest.xaml文件,也就是说如果你的Module是个类库工程的话,会在加载时产生错误。可以将几个类库的程序集文件包装在一个xap文件中作为一个Module来使用,或者自定义一个ModuleTypeLoader。

定义完Module的配置文件后,要改写Bootstrapper。首先删除用代码配置Module的方法ConfigureModuleCatalog,然后在CreateModuleCatalog方法中替换成一下内容:

1
2
3
4
5
protected override IModuleCatalog CreateModuleCatalog()
{
return Microsoft.Practices.Prism.Modularity.ModuleCatalog.CreateFromXaml(
new Uri("/PrismModule;component/ModuleCatalog.xaml", UriKind.Relative));
}

再次运行程序,正常运行。

image

这样就达到了按需加载的目的。节约带宽是一个好处,如果产品是分模块往外卖的时候,可以由客户按需定制。

不过再打开ModuleB和ModuleC的xap文件看一下,发现里面不仅有Module本身的程序集,还包括了引用的Prism的程序集等。而这些程序集其实已经在PrismModule.xap中包含了。完全没有必要重复下载。所以可以将多余的程序集的引用的Copy Local属性设置为false,这样就瘦身成功了。(想要避免重复加载相同的文件,也可以通过在项目的Properties面板中勾选Reduce XAP size by using application library caching选项)

如果你对Module的加载到执行的整个过程感兴趣,那么Prism本身提供了一个QuickStart,既有Unity版本也有Mef版本,不要错过。

在程序中使用框架必然要有一个切入点,框架会在这里进行初始化,处理相关配置信息等。在Prism中扮演这一角色的就是Bootstrapper。

Prism提供了一个抽象基类Bootstrapper,这个类里面包含了包含了许多空的虚方法,可以重写它们添加自己的逻辑。这个基类与任何容器无关,所以可以通过继承它来实现基于特定容器的Bootstrapper,不过通常我们大可不必这样做,因为Prism默认提供了两个基于特定容器的Bootstrapper——UnityBootstrapper和MefBootstrapper,分别使用Unity和Mef来实现依赖注入。而我们需要做的工作就是在这两个类之间选择一个适合自己的,稍微配置一下就可以了。当然如果你不喜欢这两个容器或者已有的程序使用了其它容器(如Spring.Net, Castle等),也可以通过继承Boostrapper抽象基类来实现自己的SpringBootstrapper和CastleBootstrapper。虽然UnityBootstrapper的代码看起来挺简单的,但是如果仿照这个来实现CastleBootstrapper却并不是那么容易的一件事(不信你可以试试),所以更好的办法是用现成的。

那么Bootstrapper都做了些什么呢?
  1. 创建Logger:

    执行CreateLogger方法,默认创建一个EmptyLogger,不会在任何地方输出log。当然是可以扩展的,比如你可以使用Clog来做一个适配器。

  2. 创建并配置ModuleCatalog

执行CreateModuleCatalog方法,默认创建一个空的ModuleCatalog。然后执行ConfigureModuleCatalog方法,默认情况下这个方法是空的。可以重写这两个方法,加入自定义的获取ModuleCatalog的逻辑,比如在CreateModuleCatalog中可以从一个xaml文件中读取Module信息。

1
2
3
4
5
protected override IModuleCatalog CreateModuleCatalog()
{
return ModuleCatalog.CreateFromXaml(new Uri("/AssemblyName;component/ModulesCatalog.xaml", UriKind.Relative));
}

  1. 创建并配置依赖注入容器

Prism中使用依赖注入来管理各个组件,你可以使用任何你熟悉的容器,比如Castle, Unity等。Prism中内置了对Unity以及Mef的支持,所以有两种预定义好的Bootstrapper: UnityBootstrapper和MefBootstrapper,其中分别采用UnityContainer和CompositionContainer作为依赖注入容器。以UnityBootstrapper为例,在这一步中会先调用CreateContainer方法,返回一个UnityContainer;然后调用ConfigureContainer方法,在这个方法中主要是将一些常用的类注册到容器中。

  1. 配置默认的Region适配器映射

为了使xaml中的UI控件可以使用Region,需要先注册一下。Prism默认支持Region的控件类型有:TabControl, Selector, ItemsControl, ContentControl。当然你也可以通过实现IRegionAdapter接口或者直接继承RegionAdapterBase来使其它控件也支持Region。

  1. 配置默认的Region 行为(Behavior)

为RegionBehaviorFactory添加一些默认的行为。这样可以扩展Region的行为。可以通过实现IRegionBehavior接口或继承RegionBehavior来自定义Region的行为,并重写ConfigureDefaultRegionBehaviors方法添加到Region。

  1. 注册框架异常类型

Prism提供了ExceptionExtensions类来帮助开发人员定位异常发生的根异常。在这一步通过调用RegisterFrameworkExceptionTypes方法向ExceptionExtensions中添加新的Root Exception。

  1. 创建并初始化Shell

首先调用CreateShell方法来创建一个Shell,这是一个抽象方法,通常这个方法中就是返回作为整个网站容器的页面。之后会将RegionManager attach到Shell上,然后更新定义的Regions,最后调用InitializeShell方法来初始化Shell。默认情况下这是个空方法,可以通过重写这个方法加入自定义的逻辑,可以在这个方法中将Shell作为Silverlight程序的根容器页面显示出来。

1
2
3
4
5
protected override void InitializeShell()`
{
Application.Current.RootVisual = Shell;
}

  1. 初始化Modules

调用InitializeModules方法,实际上就是调用ModuleManager.Run方法,会调用ModuleCatalog中的所有InitializationMode为WhenAvailable的Module的Initialize方法。

至此,整个容器的初始化过程就完毕了。

值得一提的还有CommonServiceLocator,这同样是Patterns & Practices小组的产品。它的作用很简单,就是统一依赖注入容器的接口,使程序不必依赖于特定的容器,只需要使用ServiceLocator,然后去间接地使用其它各种各样的容器。在Prism的内部就是使用ServiceLocator来进行管理的。所以不管使用什么样的容器,都需要提供一个实现了IServiceLocator接口的适配器,如使用Unity要提供UnityServiceLocatorAdapter,使用Mef要提供MefServiceLocatorAdapter。这样不管外部使用什么容器,内部都不需要改变。所以如果要使用Prism重头开始构架一个程序,那么在整个程序中不依赖于特定的依赖注入容器接口,而是使用ServiceLocator是一个不错的选择,这样可以在需要的情况下很容易地更换容器,只需要重写一个Bootstrapper和一个ServiceLocatorAdapter就可以了。

Prism是由微软Patterns & Practices团队开发的项目,目的在于帮助开发人员构建松散耦合的、更灵活、更易于维护并且更易于测试的WPF应用或是Silverlight应用以及Windows Phone 7应用。使用Prism可以使程序开发更趋于模块化,整个项目将由多个离散的、松耦合的模块组成,而各个模块又可以又不同的开发者或团队进行开发、测试和部署。目前Prism的最新版本是Prism 4,于2010年11月12日发布。Prism有很完整的文档以及丰富的示例程序。在这里我们仅针对于Silverlight程序的开发。

在下载Prism安装包并安装完成后,会在目标文件夹中发现很多文件。

推荐首先运行RegisterPrismBinaries.bat文件,这样在开发基于Prism的程序时可以更方便地添加引用程序集。

使用Prism之前,需要了解一些概念,下面通过一个非常简单的小程序来了解一下Prism。

1.打开Visual Studio 2010,新建一个Silverlight Application项目,并添加对Prism的引用。再创建三个Silverlight类库工程。

2.在Contract工程下新建一个接口,叫做ITextProvider。

1
2
3
4
5

public interface ITextProvider
{
string GetText();
}

3.在其它的三个项目中都引用Contract项目。

4.在PrismStarter工程下新建一个TextProvider类并实现ITextProvider接口。

1
2
3
4
5
6
7
8
9
10
11
public class TextProvider : ITextProvider
{
private int i = 0;

public string GetText()
{
i++;
return string.Format("From TextProvider [{0}]", i);
}
}

5.删除PrismStarter项目中自动生成的MainPage.xaml,创建一个新的UserControl,叫做Shell。页面代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<UserControl x:Class="PrismStarter.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="100" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>

<TextBlock FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center" Text="Prism Starter" />

<ContentControl Grid.Row="1" HorizontalContentAlignment="Stretch" prism:RegionManager.RegionName="RegionA" />

<ContentControl Grid.Row="2" HorizontalContentAlignment="Stretch" prism:RegionManager.RegionName="RegionB" />
</Grid>
</UserControl>

6.在ModuleA工程中添加对Prism程序集的引用。并添加一个UserControl叫做ViewA,页面代码为:

1
2
3
<Grid :Name="LayoutRoot" Background="White">
<TextBlock x:Name="textModuleA" FontSize="30" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>

CodeBehind中的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class ViewA : UserControl
{
public ViewA(ITextProvider textProvider)
{
InitializeComponent();

this.Loaded += (s, e) =>
{
textModuleA.Text = string.Format("Module A {0}", textProvider.GetText());
};
}
}

7.在ModuleA工程中添加一个类叫做ModuleA,并实现接口IModule。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ModuleA : IModule
{
private IRegionManager _regionManager;

public ModuleA(IRegionManager regionManager)
{
_regionManager = regionManager;
}

public void Initialize()
{
_regionManager.RegisterViewWithRegion("RegionA", typeof(ViewA));
}
}

注意这里的RegionA对应于Shell页面中的RegionName。

8.在ModuleB工程中重复6、7过程,只是将A替换为B。

9.在PrismStarter工程中添加对ModuleA和ModuleB的引用。

10.在PrismStarter工程中添加一个PrismStarterBootstrapper类,并继承UnityBootstrapper。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class PrismStarterBootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return this.Container.TryResolve<Shell>();
}

protected override void InitializeShell()
{ // 控制页面在初始化时显示Shell页面
App.Current.RootVisual = (UIElement)this.Shell;
}

protected override void ConfigureModuleCatalog()
{ // 注册Module。在实际开发中可以使用xaml做配置文件,
// 这样就可以将PrismStarter与ModuleA和ModuleB完全解耦,也就不再需要引用这两个项目
Type moduleAType = typeof(ModuleA.ModuleA);
ModuleInfo moduleA = new ModuleInfo
{
ModuleName = moduleAType.Name,
ModuleType = moduleAType.AssemblyQualifiedName,
};

Type moduleBType = typeof(ModuleB.ModuleB);
ModuleInfo moduleB = new ModuleInfo
{
ModuleName = moduleBType.Name,
ModuleType = moduleBType.AssemblyQualifiedName,
};

this.ModuleCatalog.AddModule(moduleA);
this.ModuleCatalog.AddModule(moduleB);
}

protected override void ConfigureContainer()
{ // 注册一下TextProvider,这样在通过容器请求ITextProvider时会返回TextProvider实例
base.ConfigureContainer();
this.Container.RegisterInstance<ITextProvider>(new TextProvider());
}
}

11.最后一步,打开App.xaml.cs,修改Application_Startup方法

1
2
3
4
5
private void Application_Startup(object sender, StartupEventArgs e)
{
PrismStarterBootstrapper bootstrapper = new PrismStarterBootstrapper();
bootstrapper.Run();
}

运行程序,结果如下:

image

下面简单介绍一下这个小例子中涉及到的一些概念。

Bootstrapper: 在程序中使用框架需要找到一个切入点,将框架植入进去,将一部分功能委托给框架来实现。在Silverlight中使用Prism的切入点就是App.xaml.cs中的Application_Startup方法。一般来说,这个方法中只是指定页面最先加载的页面,但是我们把默认的逻辑去掉,取而代之的是Bootstrapper(在本例中就是PrismStarterBootstrapper)。当调用Bootstrapper.Run方法时,它会完成一些准备工作,如一些配置等。因此你会发现,使用Prism后,启动程序时会比正常启动要慢一些,就是因为Bootstrapper做了许多工作。

Container: 依赖注入容器。在程序中使用依赖注入的好处到处都可以找的到。在Silverlight中使用容器来管理各个组件的一个很明显的好处就是使用单例来降低内存使用。否则每次加载一个页面都需要重新创建一个也很耗费资源的。当然好处不只这些,通过容器来注入一些服务(如本例中的IRegionManager和ITextProvider)显得相当方便。

Module: Prism帮助我们把程序分解成一个个功能模块,这些功能模块就叫做Module,通常一个工程就是一个Module。由于Module彼此是独立的,但是在运行时需要将它们整合到一起,因此Prism需要知道Module的存在,这里就涉及到了ModuleCatalog, ModuleCatalog就是Module的容器,里面包含了所有Module的信息,以ModuleInfo的形式存在。ModuleInfo就是对Module的抽象,包含Module的名字,类型,依赖等一些信息。

Shell: 相当于程序的入口,初始界面,还能够提供类似ASP.Net中的母版页的功能。Shell必须由Bootstrapper创建,因为Shell需要使用的一些service,比如RegionManager等,需要在Shell显示前注册。

Region: 相当于ASP.Net中的ContentPlaceHolder(是这么叫的吧?),起到占位符的作用,如本例中Shell中有两个Region——RegionA和RegionB,定义了两块区域。在Module的初始化过程中,通过IRegionManager将Module中的页面放进了定义好的Region中。IRegionManager负责管理Region,可以通过它向Region中注册View,进行导航等。

Prism的功能当然远不止这么简单,它还提供对MVVM模式的支持,对导航的支持等,在后续文章中会逐步介绍。希望能够通过本文让大家对Prism有一定的了解。

代码下载

DotNet

C#开源系统大汇总 - 心存善念 - 博客园

Npoi操作excel - 张龙豪 - 博客园

.NET Core 跨平台发布(dotnet publish) - LineZero - 博客园

如何用.net c# 读取epub格式文件 - szliszt的专栏 - 博客频道 - CSDN.NET

使用epublib自动生成epub文件 - zhyoulun的专栏 - 博客频道 - CSDN.NET

将Log4net的配置配置到的独立文件中 - 422159763 - 博客园

AutoMapper小结 - 呆河马 - 博客园

AutoMapper完成Dto与Model的转换 - kuangkro - 博客园

Quartz+TopShelf实现Windows服务作业调度 - Frozen.Zhang - 博客园

Windows服务调用Quartz.net 实现消息调度 - M.Zero - 博客园

WebApi:WebApi的Self Host模式 - MAQNH - 博客园

【MVC】ASP.NET MVC Forms验证机制 - bomo - 博客园

【WEB API项目实战干货系列】- 导航篇(十足干货分享) - DukeCheng - 博客园

ASP.NET MVC中Autofac实现的自动注入模式 - Nic Pei - 博客园

MVC5+Unity4.0注入依赖学习 - 灵猪谁仰的专栏 - 博客频道 - CSDN.NET

Unity框架的依赖注入-Dependency injection - 徐某人 - 博客园

C#软件license管理(简单软件注册机制) - CSDN博客

动手写C#注册码工具(提供源码) - 唯吴独尊 - 博客园

授权组件设计 - LicenseControlProject - Cracker - 博客园

ERP框架开发中的License许可验证机制设计与实现 (包含源代码下载) - 信息化建设 - 博客园

.NET分离exe和dll在不同的目录让你的程序更整洁 - .NET快速开发框架 - 博客园

.net RPC框架选型 - 凌晨三点半 - 博客园

[C#进阶系列]专题一:深入解析深拷贝和浅拷贝 - Learning hard - 博客园

通用的序列号生成器库 - 张善友 - 博客园

根据twitter的snowflake算法生成唯一ID - 梁照彬 - 博客园

C#动态调用WCF接口,两种方式任你选。 - Danny Chen - 博客园

WCF 学习笔记: ServiceHost - CSDN博客

使用ASP.Net WebAPI构建REST服务(六)——Self-Host - 天方 - 博客园

构建基于Chromium的应用程序 - 猫不理饼 - 博客园

8种主要排序算法的C#实现 - 胖鸟低飞 - 博客园

C#位运算 - Danny Chen - 博客园

快速排序算法(C#实现) - Eric Sun - 博客园

冒泡排序算法(C#实现) - Eric Sun - 博客园

归并排序算法(C#实现) - Eric Sun - 博客园

堆排序算法(C#实现) - Eric Sun - 博客园

插入排序算法–直接插入算法,折半排序算法,希尔排序算法(C#实现) - Eric Sun - 博客园

C# 经典排序算法大全 - 张世辉 - CSDN博客

C#排序算法小结 - hungerW - 博客园

C#排序算法的比较 - r163 - 博客园

ASP.NET MVC使用Oauth2.0实现身份验证 - 冰碟 - 博客园

Asp.Net MVC 4 Web API 中的安全认证-使用OAuth - Nic Pei - 博客园

使用Owin中间件搭建OAuth2.0认证授权服务器 - CSDN博客

使用DotNetOpenAuth搭建OAuth2.0授权框架 - 莱布尼茨 - 博客园

ASP.NET WebApi OWIN 实现 OAuth 2.0 - 田园里的蟋蟀 - 博客园

asp.net权限认证:OWIN实现OAuth 2.0 之授权码模式(Authorization Code) - 蓝建荣 - 博客园

[OAuth]基于DotNetOpenAuth实现Client Credentials Grant - dudu - 博客园

.net 单点登录实践 - 何雪峰 - 博客园

Personball’s Blog - 使用Owin中间件搭建OAuth2.0认证授权服务器

如何给你的ASP.NET页面添加HelpPage - pmars - 博客园

ASP.NET Identity登录原理 - Claims-based认证和OWIN - Jesse Liu - 推酷

如何使用FluentMigrator进行数据库迁移 - LamondLu - 博客园

领域驱动设计 - 随笔分类 - dax.net - 博客园

C# CacheHelper - Ariter - 博客园

Memcache升级版:CouchBase的安装配置与使用说明_PHP教程_开源小组_开源社区

如何用C#动态编译、执行代码 - Danny Chen - 博客园

Repository模式介绍汇总 - 跟着阿笨一起玩.NET - 博客园

8天掌握EF的Code First开发系列之5 视图、存储过程和异步API - JustYong - 博客园

1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】 - 灰太狼的梦想 - 博客园

EF批量操作数据与缓存扩展框架 - 天使不哭 - 博客园

献给Fluent NHibernate的初学者 - Nic Pei - 博客园

6.数据访问技术 - 随笔分类 - Apollo.NET - 博客园

EF架构~系列目录 - 张占岭 - 博客园

Entity Framework Code First (五)Fluent API - 配置关系 - 舍长 - 博客园

wpf 实现实时毛玻璃(live blur)效果 - CSDN博客

WPF 几行代码实现窗体毛玻璃效果(Aero Glass) - CSDN博客

Wpf开源收集 - 刺客mrchenzh - 博客园

WPF开源界面库 - iGotogo - 博客园

[Prism框架实用分享]如何在主程序中合理的弹出子窗体 - @Sunth - 博客园

【WPF】右下角弹出自定义通知样式(Notification)——简单教程 - catshitone的专栏 - CSDN博客

c#,使用WPF的Adorner实现iPhone上新邮件或消息提示效果—-实现(一) - CSDN博客

WPF实现Themes切换 - CSDN博客

对TabControl的简单优化 - 猴健居士 - 博客园

[Prism框架实用分享]如何在主程序中合理的弹出子窗体 - @Sunth - 博客园

Prism - 标签 - Jason Li - 博客园

Prism - Eric_K1m的专栏 - CSDN博客

WPF中DataGrid控件内Button的Command和CommandParameter的绑定 - jumtre的专栏 - CSDN博客

Prism.Interactivity 之 PopupWindowAction 用法简记 - 不老哥 - 博客园

WPF 漂亮的自定义分页控件 - 简书

免费的精品: Productivity Power Tools 动画演示 - stg609 - 博客园

c# 模拟表单提交,post form 上传文件、大数据内容 - CSDN博客

搭建基于MongoDB的文件管理系统(一) - 作业部落 Cmd Markdown 编辑阅读器

在ASP.NET MVC中实现大文件异步上传(2) - 51CTO.COM

黄聪:如何用代码设置控制自己网站的网页在360浏览器打开时强制优先使用极速模式,而非兼容模式 - 黄聪 - 博客园

分布式架构理论篇 - CSDN博客

.NET领域驱动设计系列 - 随笔分类 - Learning hard - 博客园

矩阵的坐标变换(转) - Danny Chen - 博客园

移动端热更新方案(iOS+Android) - 七夜i - 博客园

SQL Server 2012 开发新功能 序列对象(Sequence) - zhangyoushugz - 博客园

标签: CQRS | Edison Xu’s Blog

用JS获取地址栏参数的方法(超级简单) - 墟零 - 博客园

微信开发笔记——微信网页登录授权,获取用户信息 - =金刚= - 博客园

微信公众号开发之网页授权获取用户基本信息 - 潇十一郎 - 博客园

Senparc.Weixin SDK 微信公众号 .NET 开发教程 索引 - SZW - 博客园

asp.net core 引入vue工程 - 简书

C# Socket使用以及DotNetty和Supersocket 框架 - netlock - 博客园

读取社保卡信息 - dozeoo - 博客园

.net core的配置介绍(一):IConfiguration - 没有星星的夏季 - 博客园

.Net Core DevOps -免费用Azure四步实现自动化发布(CI/CD) - 布洛克菲勒 - 博客园

Robot Framework官方教程(一)入门 - 简书

[[C#].NET/C#程序开发中如何更优美地实现失败任务重试的逻辑? | 码友网](https://codedefault.com/s/what-is-the-cleanest-way-to-write-retry-logic-in-csharp-application#:~:text=在.NET%2FC%23的程序开发中,有时候需要对一些失败的任务进行多次的重试,如果重试的次数达到我们设定的阀值,则再放弃任务,比如有以下的C%23伪代码: int retries %3D 3 %3B while (true),0) throw %3B else Thread.Sleep (1000)%3B } })

Polly .NET瞬时故障处理 - 重试_水墨长天的博客-CSDN博客_polly 重试

从零搭建一个IdentityServer——集成Asp.net core Identity - 7m鱼 - 博客园

asp.net core使用identity+jwt保护你的webapi(二)——获取jwt token - xhznl - 博客园

ASP.NET Core 6.0 添加 JWT 认证和授权 - 芦荟柚子茶 - 博客园

【Vue】Vue与ASP.NET Core WebAPI的集成 :: Garfield-加菲的博客 — 专注于IT互联网,Web技术,.Net, .Net Core,Node.js, Go语言(golang)、前端框架、项目管理、软件架构 只有原创,没有转载,只有实践,才会成文。

.Net gRPC使用Jwt验证详细教程 - 冰河洗剑

.NET 6使用Redis - Lulus - 博客园

ASP.NET Core gRPC 使用 Consul 服务注册发现 - 晓晨Master - 博客园

ASP.Net Core下Authorization的几种方式 - 简书

C#常用的加密算法:MD5、Base64、SHA1、SHA256、HmacSHA256、DES、AES、RSA - TomLucas - 博客园

VS2022 安装.NET4.5目标包 - Stay627 - 博客园

搭建面向NET Framework的CI/CD持续集成环境(一)Windows服务器安装Jenkins - ElijahZeng - 博客园

搭建面向NET Framework的CI/CD持续集成环境(二)自动代码分支编译构建 - ElijahZeng - 博客园

C#中的时间戳 - 简书

OpenCV

OpenCV - 迭代的是人,递归的是神 - 博客频道 - CSDN.NET

OpenCV入门指南 - MoreWindows Blog - 博客频道 - CSDN.NET

[使用SeetaFace和Dlib实现人脸识别 | 第七区](https://zone-7.github.io/2018/02/24/others/2018-02-24-使用SeetaFace 和Dlib实现人脸识别/)

6.Qt实时人脸识别和Sqlite数据库_哔哩哔哩_bilibili

使用OpenCV+Dlib ,多线程实现人脸检测+人脸识别(C++ ) - 知乎

Dlib学习人脸比对_dlib 人脸比对-CSDN博客

dlib库包的介绍与使用,opencv+dlib检测人脸框、opencv+dlib进行人脸68关键点检测,opencv+dlib实现人脸识别,特征聚类 - 掘金

qt+opencv+dlib 人脸识别,可以存储人脸数据_dlib qt-CSDN博客

如何计算两个人脸的相似度 - 知乎

c++ dlib + opencv + facenat 进行人脸比对 - CSDN文库

机器学习库dlib的C++编译和使用(windows和linux) - 知乎

C++

Qt Creator 配置第三方库和头文件_qt creator加载第三方库csdn-CSDN博客

Qt中开启线程的五种方法_qt 开启线程-CSDN博客

Qt事件耦合器实现(类似C#的Prism中的事件耦合器)_qt偶合-CSDN博客

c/c++编译:使用CMAKE进行跨平台开发_cmake 跨平台_随便写写。的博客-CSDN博客

C++跨平台(二):grpc和zmq的方案预研_CodeBowl的博客-CSDN博客_grpc跨平台

arm平台Openssl交叉编译_aron566的博客-CSDN博客_arm openssl交叉编译

(11条消息) Qt 添加MSVC2017编译器(2022年保姆级教程,不安装完整VS)_Copperxcx的博客-CSDN博客_msvc2017

(13条消息) C 语言实现面向对象编程_onlyshi的博客-CSDN博客_c语言面向对象的编程方法

(14条消息) Hello Qt——QtCreator代码格式化_天山老妖的博客-CSDN博客_qt 格式化代码

(14条消息) qtcreator 格式化代码_北极熊的奋斗史的博客-CSDN博客

(14条消息) Ubuntu20.10编译安装Qt4.8.7_wanyiba的博客-CSDN博客

10.搭建vs2010+Qt4.8.5+QtCreator3.4.0开发环境_xhome516的博客-CSDN博客_qt4.8.5+vs2010环境配置

在 VS2015 中使用 Qt4 - 简书

魔改 Qt Creator 插件框架(附源码)

qt plugins 插件框架_qt 插件框架-CSDN博客

深入理解QtCreator的插件设计架构 - 简书

GoLang

后端 - Go 1.18 泛型全面讲解:一篇讲清泛型的全部_个人文章 - SegmentFault 思否

【Golang】关于Go中logrus的用法 - 踏雪无痕SS - 博客园

Go Grpc Jwt身份认证 - dz45693 - 博客园

数据库:PostgreSQL加载timescaledb拓展异常FATAL: extension “timescaledb” must be preloaded_hahahafree的博客-CSDN博客

spring cloud + kubeedge_鲜卑大帝的博客-CSDN博客

[centos网卡配置详解 - vinter_he - 博客园](https://www.cnblogs.com/vinter/p/12547698.html#:~:text=centos网卡配置文件一般位于:%2Fetc%2Fsysconfig%2Fnetwork-scripts%2F 文件名一般为:ifcfg-eno或者ifcfg-eth0类似的文件,可以先用ip,addr 命令或者是ifconfig命令查看网卡信息)

最全的Python虚拟环境使用方法 - 知乎

Ubuntu:PostgreSql安装PostGis、TimeScaleDB插件_love_QJP的博客-CSDN博客

(13条消息) golang pbkdf2加密存储用户密码_藏呆羊的博客-CSDN博客

Go 实现 PBKDF2 加密算法 - beihai blog

gin集成casbin - 掘金

手把手,带你从零封装Gin框架(四):数据库初始化(GORM) - 掘金

手把手,带你从零封装Gin框架(五):静态资源处理 & 优雅重启服务器 - 掘金

Consul 入门-gRPC 服务注册与发现 - 掘金

Docker部署Go程序 - 掘金

【Vscode】调试go语言程序的最佳实践 - 腾讯云开发者社区-腾讯云

GO操作influxdb_书笑生的博客-CSDN博客_go influxdb

golang 编程规范 - 项目目录结构 - 简书

基于 Gin 模块化开发 API 框架设计_水痕01的博客-CSDN博客_gin开发api

国标

spring boot +netty 解析国标协议(GB/T 26875.3-2011)用户信息传输装置_qq_41655468的博客-CSDN博客_国标26875协议

边缘计算

(11条消息) KubeEdge环境搭建-实现原理-官方计数器示例运行成功_Counter Demo_尖耳朵的阿凡达妹妹的博客-CSDN博客_kubeedge搭建

(11条消息) 学习k8s的接口(Api)使用,并试着调用KubeEdge中(计数器demo)设备的信息_在不甘与平凡中逆水行舟的博客-CSDN博客_k8s接口

从零开始——在Ubuntu22.04系统中部署KubeEdge架构_怂怂是张的博客-CSDN博客_ubantu部署kubeedge

kubernetes - 【KubeEdge】KubeEdge部署小指南-Edge节点接入(避坑)_个人文章 - SegmentFault 思否

k8s+kubeedge+sedna部署· - 鹦鹉理 - 博客园

Linux编译安装kubeedge_beyond阿亮的博客-CSDN博客_kubeedge编译安装

在 Kubernetes 中部署并使用 KubeEdge

源码安装kubeedge_rocsdu的博客-CSDN博客_cloudcore二进制

KubeEdge安装部署 - 请务必优秀 - 博客园

Linux

gentoo 安装docker 折腾手记 - 贵贵的博客 - 开发|架构|开源|共享

【图片】Archlinux安装小记(2016.3.3)【archlinux吧】_百度贴吧

【图片】arch/manjaro安装antergos全套主题(包括DE,DM,grub2)【archlinux吧】_百度贴吧

Arch Linux 安装、配置、美化和优化 - petercao - 博客园

Centos配置国内yum源-zhuzusong-ChinaUnix博客

CentOS yum 源的配置与使用 - David_Tang - 博客园

RHEL/CentOS/Fedora各种源(EPEL、Remi、RPMForge、RPMFusion)配置_Linux教程_Linux公社-Linux系统门户网站

不得不装的CentOS的三大yum源centos

ubuntu14.04中离线安装docker - 博客频道 - CSDN.NET

CentOS-6.5离线安装docker-1.7教程 - tuzhutuzhu的专栏 - 博客频道 - CSDN.NET

Android

android实现微信自动抢红包 - oden的博客 - 博客频道 - CSDN.NET

教你一步步实现Android微信自动抢红包_Android_脚本之家

Android AccessibilityService实现微信自动抢红包 - 博客频道 - CSDN.NET

Android微信抢红包外挂 源代码 - 翊轩LeOn - 博客频道 - CSDN.NET

AndroidCompile - VideoLAN Wiki

Android唤醒、解锁屏幕代码实例_Android_脚本之家

Android程序主动点亮&解锁屏幕的实现 - 移动平台应用软件开发技术 - 博客频道 - CSDN.NET

Android辅助功能AccessibilityService与抢红包辅助_Android_脚本之家

android抢红包代码解析支持微信与QQ - Android移动开发技术文章_手机开发 - 红黑联盟

Android蓝牙搜索设备,向其发送数据并接收-刘宇 - 刘宇的博客 - CSDN博客

android 蓝牙设备监听广播 - LeslieFang - 博客园

Android总结篇系列:Android广播机制 - Windstep - 博客园

Android 蓝牙开发(一)蓝牙通信 - 奋斗的菜鸟ing - CSDN博客

Android开发之蓝牙通信(一) - AnalyzeSystem的博客 - CSDN博客

Android Bluetooth(蓝牙)实例 - Android开发教程™

android 蓝牙通信编程 - Gabriel的专栏 - CSDN博客

Android 实现蓝牙客户端与服务器端通信 - Android移动开发技术文章_手机开发 - 红黑联盟

详解Android——蓝牙技术 带你实现终端间数据传输_Android_脚本之家

android自带的示例程序 BluetoothChat 变蓝牙串口助手 - Android小子的博客笔记 - CSDN博客

Android 蓝牙开发基本流程 - q610098308的专栏 - CSDN博客

Android蓝牙串口通信模板及demo,trick - MetalSeed - CSDN博客

Android Ble 4.0 蓝牙开发交互 - Lucy__的博客 - CSDN博客

Android和BLE模块连接通信 - Spades-S - 博客园

Android BLE开发——Android手机与BLE终端通信初识 - CKTim - 博客园

Android 蓝牙4.0(BLE)开发实现对蓝牙的写入数据和读取数据 - It_BeeCoder的博客 - CSDN博客

Android游戏源码大合集(主要是AndEngine和Libgdx的) - 下载频道 - CSDN.NET

Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果 - 下载频道 - CSDN.NET

Android滑动菜单特效实现,仿人人客户端侧滑效果demo - 下载频道 - CSDN.NET

Android教你如何一分钟实现下拉刷新功能demo - 下载频道 - CSDN.NET

Android第三方开源框架ImageLoader的完美Demo - 下载频道 - CSDN.NET

Android高手进阶之自定义View,自定义属性(带进度的圆形进度条) - 下载频道 - CSDN.NET

Android实现ListView的A-Z字母排序和过滤搜索功能 - 下载频道 - CSDN.NET

Android动画效果集合开源APP(BaseAnimation1.3) - 下载频道 - CSDN.NET

Android 通知栏Notification的全面整合学习 - 下载频道 - CSDN.NET

Android 打造史上最简单的侧滑菜单 - 下载频道 - CSDN.NET

164个完整的Java源程序代码 - 下载频道 - CSDN.NET

vlc-android源码编译过程记录 - 精神邋遢的民工 - 博客园

vlc-android 中调用用libvlcjni.so实现流媒体播放 - memegood123的专栏 - 博客频道 - CSDN.NET

vlc-android 获取MediaPlayerEncounteredError,MediaPlayerBuffering等各种事件的响应 - memegood123的专栏 - 博客频道 - CSDN.NET

【VLC-Android】vlc-android简例 - 农民伯伯 - 博客园

ffmpeg2.2在ubuntu下使用NDK编译——并在android工程下测试使用 - wainiwann - 博客园

Android版本-编译VLC - 雨の殇的天空 - 博客频道 - CSDN.NET

vlc-android源码的编译 - Find A Way 的博客 - 博客频道 - CSDN.NET

Ubuntu12.04编译vlc-android详细流程 - wainiwann - 博客园

Linux 下编译Android-VLC开源播放器详解(附源码下载) - 泡泡糖 - 博客园

LIBTOOL is undefined 问题的解决方法 - Sky_qing的专栏 - 博客频道 - CSDN.NET

基于Darwin实现的分布式流媒体直播服务器系统 - Babosa的专栏 - 博客频道 - CSDN.NET

DyncLang/DevLiveBook: 励志成为较全的直播技术导航_AnyRTC

Android wifi无线调试App新玩法ADB WIFI - 简书

WebRTC

使用WebRTC搭建前端视频聊天室——信令篇 - 说学逗唱 - SegmentFault

[部署rfc5766-turn-server--谷歌推荐的开源穿透服务器 复制链接] - 康林工作室 - 博客频道 - CSDN.NET

编译rfc5766-turn-server搭建turn服务器-码农场

Ubuntu下安装TURN Server (rfc5766-turn-server) - 不急不徐,持之以恒。 - BlogJava

随笔列表第7页 - RTC.Blacker - 博客园

C#+WebSocket+WebRTC多人语音视频系统 - 甩葱哥丶的个人空间 - 开源中国社区

一步一步搭建客服系统 (1) 3分钟实现网页版多人文本、视频聊天室 (含完整源码) - 疯吻IT - 博客园

web即时通信1–WebSocket与WebRTC的三种实现方式对比 —核心网络

在 Asp.NET MVC 中使用 SignalR 实现推送功能 - 罗朝辉(飘飘白云) - 博客频道 - CSDN.NET

java 调用wsdl的方式 - SamWu - 博客园

K8s

暴露redis-cluster到k8s集群外部.md_ll577644332的博客-CSDN博客

[(14条消息) kubernetes]-k8s部署单节点redis_爷来辣的博客-CSDN博客_k8s部署单节点redis

Docker - 实现本地镜像的导出、导入(export、import、save、load)

Microk8s 安装 与使用指南 - 腾讯云开发者社区-腾讯云

基于WSL2和Kind或Minikube:搭建Windows版Kubernetes_Kubernetes中文社区

kubeadm搭建k8s集群 - 请务必优秀 - 博客园

傻瓜式教学: Debian安装k3s(长期维护版本) | Solitudes

在 Kubernetes 上部署 Drone 持续集成环境 | Hanggi - NGNL

gitea+drone+kubernetes搭建devops平台_gitea+drone+k8s-CSDN博客

k3s containerd 配置 mirror 和 insecure - 知乎

将 minikube 的服务暴露到宿主机外 · jtr109’s Castle

嵌入式

〖嵌入式〗_叶帆的博客-CSDN博客

[耗时一周总结的嵌入式学习路线,超详细 - 知乎](https://zhuanlan.zhihu.com/p/531416610#:~:text=全文整体的学习路线: 嵌入式基础学习 -> 51单片机 -> STM32单片机 -> RTOS篇,ARM%2BLinux 每一个部分,也都从 学习内容 , 学习建议 , 学习资料 三个方面来展开,层层深入,步步指引。)

[熬夜肝了一份 C++/Linux 开发学习路线 - 帅地 - 博客园](https://www.cnblogs.com/kubidemanong/p/15151762.html#:~:text=熬夜肝了一份 C%2B%2B%2FLinux 开发学习路线 1 一、C%2B%2B 基础 (3-6个月) 2,6 六、数据结构与算法 (3-6%2B月) 7 七、项目 (2个月左右) 8 八、学习顺序)

Linux C/C++ 服务器/后端开发/后台开发学习路线_Linux服务器开发的博客-CSDN博客

VSCode配置C/C++环境 - 知乎

linux 下C语言学习路线 - lipps - 博客园

linux 下C语言学习路线_老徐拉灯的博客-CSDN博客_如何在linux中学习c语言

Linux系统开发学习路线_llhh33的博客-CSDN博客

go-logrus 日志框架封装使用 - 简书

微信小程序连接MQTT服务器全过程_白白的昕的博客-CSDN博客

这些操作删除console.log的方法,你都知道吗 - 知乎

Go语言相关书籍推荐(从入门到放弃) - 知乎

Gitea 与 Drone 集成实践:完全基于 Docker 搭建的轻量级 CI/CD 系统 - Gitea - 博客园

Gitea+Drone+Rancher CI/CD持续集成解决方案 - 掘金

有哪些值得推荐的c/c++开源框架与库 - 知乎

C语言网络编程(1)— UDP通信(这篇写得很详细,也讲了怎么借助网络调试助手)_c语言udp通信_TYINY的博客-CSDN博客

用C写一个UDP发送和接收程序_udp发送 c_11061104的博客-CSDN博客

Qt单个实例运行 - SingleApplication_yizhou2010的博客-CSDN博客

Qt应用程序的单例化(程序只运行一个实例)_qt中文件锁单例与共享内存单例_兜黎的博客-CSDN博客

C#获取硬盘序列号_lilin8905的博客-CSDN博客

消息摘要算法MD5图解及C语言实现 - 知乎

sha256 C语言实现_qq_43176116的博客-CSDN博客

HMAC-SHA256签名加密 C语言实现+例子_hmacsha256在线加密_Clnulijiayou的博客-CSDN博客

memcpy 合并数组 拷贝多个数组 memcpy采坑记_斗转星移3的博客-CSDN博客

C语言实现MD5加密,竟如此简单! - 腾讯云开发者社区-腾讯云

Golang领域模型-CQRS - Go语言中文网 - Golang中文社区

Go进阶10:logrus日志使用教程 | Go&Rust🦀

Go解决TCP粘包_go tcp粘包_向阳的野草的博客-CSDN博客

Go网络编程之UDP通信和文件传输 - 简书

kubeedge+edgemesh安装笔记_抓不到老鼠的汤姆的博客-CSDN博客

Golang最强大的访问控制框架casbin全解析 - 轩脉刃 - 博客园

ASP.NET MVC 5实现基于Quartz.net 的任务调度管理平台(一)_风神修罗使的博客-CSDN博客

Asp.Net Core2.0 基于QuartzNet任务管理系统 - ice.ko - 博客园

STM32常见通信方式(TTL、RS232、RS485、I2C,SPI,CAN)总结_有人用过bs32f103_位文杰TOP的博客-CSDN博客

Go语言实现websocket服务器 - 知乎

C++中的queue类、QT中的QQueue类 - 诺谦 - 博客园

05-部署持续部署服务-Drone(上) - 知乎

[Azure Devops] 使用 Azure Pipelines 实现 CI - 腾讯云开发者社区-腾讯云

使用Gitea+Drone来搭建自己的轻量级CI/CD自动构建平台 - 饭饭’s Blog

【小白向】基于Docker使用Gogs,Drone以及drone-runner-docker的自动化部署 - JohnBeBee - 博客园

基于etcd的服务发现与注册 - 掘金

C#实现ModBusRtu协议 - 知乎

MODBUS RTU MASTER的C语言代码 - r_jw - 博客园

FreeMobus移植在FreeRTOS上的移植(从机) - 云乐 - 博客园

grpc 双向通道 编写聊天室_grpc 双通道_tianv5的博客-CSDN博客

队列的实现(C语言)_vitobo的博客-CSDN博客

FreeRTOS(教程非常详细)_不秃也很强的博客-CSDN博客

c语言建立队列(顺序队列、循化队列和链式队列)_循环队列(数组)和链队列的建立及基本算法_落春只在无意间的博客-CSDN博客

数据结构STL——golang实现队列queue - 知乎

[eShopOnContainers 知多少1]:总体概览 - 「圣杰」 - 博客园

实现自己的.NET Core配置Provider之Yaml - BobTian - 博客园

Redis 学习笔记(六)Redis 如何实现消息队列 - 归斯君 - 博客园

【opencv实战】海康摄像rtsp流不同方案下的时延测试(Ing)_rtsp怎么测量拉流延时_昌山小屋的博客-CSDN博客

5分钟教你搭建Unity云渲染服务 - 知乎

ABP EF Core多数据库支持_abp多数据库支持_娃都会打酱油了的博客-CSDN博客

Hadoop教程 - yuan_xw的专栏 - 博客频道 - CSDN.NET

如何给变量取个简短且无歧义的名字_知识库_博客园

AutoMapper小结 - 呆河马 - 博客园

AutoMapper完成Dto与Model的转换 - kuangkro - 博客园

EF中Repository模式应用场景 - 指尖流淌 - 博客园

WPF 引用DLL纯图像资源包类库中的图片 - 耿爱学 - 博客园

WPF 如何将软件的所有图片保存在DLL内供主程序调用 - 蓝山咖啡的博客 - 博客频道 - CSDN.NET

三分钟教你学Git(十四) 之 线下传输仓库 - hongchangfirst - 博客频道 - CSDN.NET

使用epublib自动生成epub文件 - zhyoulun的专栏 - 博客频道 - CSDN.NET

如何用.net c# 读取epub格式文件 - szliszt的专栏 - 博客频道 - CSDN.NET

CMake 良心教程,教你从入门到入魂 - 知乎

(14条消息) 解决报错Cannot find module ‘webpack-cli/bin/config-yargs’_sxs7970的博客-CSDN博客_yargs 卸载

详解Docker 容器基础系统镜像打包_docker_脚本之家

一种docker基础镜像制作方法 - 老胡的笔记 - 博客频道 - CSDN.NET

Npoi操作excel - 张龙豪 - 博客园

非常详细的 Docker 学习笔记 - OPEN 开发经验库

CentOS-6.5离线安装docker-1.7教程 - tuzhutuzhu的专栏 - 博客频道 - CSDN.NET

用JIRA管理你的项目——(一)JIRA环境搭建 - Snowolf的意境空间! - ITeye技术网站

[JIRA] 最新Linux安装版本jira6.3.6安装破解以及数据导入的详细步骤-mchdba-ITPUB博客

Gradle Android最新自动化编译脚本教程(提供demo源码) - 心有灵犀鬼才心 - 博客频道 - CSDN.NET

Ubuntu20.04上安装Android Studio_ubuntu20.04安装android studio-CSDN博客

超全的auto.js基础操作,目前是autoX.js的控制方式。2023年9月23日更新!(第3/4章) - 知乎

[无障碍服务AccessibilityService详解-CSDN博客](https://blog.csdn.net/weixin_42574892/article/details/120042709#:~:text=常见无障碍服务示例 1 开关访问:允许行动不便的 Android 用户使用一个或多个开关与设备进行交互。,2 语音访问:允许行动不便的 Android 用户使用语音命令控制设备。 3 Talkback:视力受损或盲人用户常用的屏幕阅读器。)

Android 定时任务的8种实现方法 - 天涯海角路 - 博客园

通过C#将PDF快速导出为图片 - 个人文章 - SegmentFault 思否

[使用 C# 将 PDF 转换为图像](https://blog.conholdate.com/zh/total/convert-pdf-to-images-using-csharp/#:~:text=使用 C%23 将 PDF 转换为 PNG 图像 1,使用页码和输出 PNG 图片路径调用 Process (Page%2C String) 方法,将页面转换为 PNG。)

基于gitea+K3s实现DevOps/CI/CD - 掘金

InfluxDB安装以及使用 - 知乎

[c++ convert pdf to image-掘金](https://juejin.cn/s/c%2B%2B convert pdf to image)

设计一个通用的【系统操作日志】模块 - 知乎

超简单实现vr看房子、360全景图(附完整demo) - 掘金

微信小程序音视频与WebRTC互通的技术思路和实践 | 微信开放社区

实践修复 Linux 无法启动 EFI 故障 - 知乎

WPF:将调试信息输出到控制台-CSDN博客

使用 Harbor 作为 K3S 的镜像代理缓存后端 - roy2220 - 博客园

ubuntu22.04安装kubernetes1.26 (使用containerd)_ubuntu安装containerd-CSDN博客

用 Helm 在 k8s 上快速搭建 MySQL 主从集群 ,并提供对外访问 - 掘金

helm部署mysql-腾讯云开发者社区-腾讯云

ubuntu 20.4安装k8s 1.24.0、1.28.0(使用containerd)_ubuntu containerd 安装-CSDN博客

如何在 Ubuntu 22.04 上安装 Containerd 容器运行时

C# 断言 Assert - Mzhangyl - 博客园

C语言和设计模式(总结篇) 用了多年的C_c程序设计 模式-CSDN博客

Redis 集群模式与哨兵模式:详细对比与实例解析_redis cluster和哨兵区别-CSDN博客

Redis6搭建高可用的多主多从集群-阿里云开发者社区

redis集群搭建(非常详细,适合新手)_redis哨兵模式两主多从-腾讯云开发者社区-腾讯云

k8s安装redis主从版-腾讯云开发者社区-腾讯云

k8s中部署redis集群(三主三从) - 云起时。 - 博客园

【授人以渔】从根源上解决NAS影视库(Jellyfin/Emby/PLEX)刮削问题,群晖威联通华硕通用教程_NAS存储_什么值得买

etcd实现服务发现 - 烟花易冷人憔悴 - 博客园

Qt编译器迁移:从MinGW到MSVC - MrBeanC-Blog

Centos/ubuntu-搭建简单的国内代理服务器(socks5/http代理)-腾讯云开发者社区-腾讯云

2022 最新 Mac Vim 开发环境的部署与配置_macvim-CSDN博客

Gentoo网络设置 - 简书

arping工具使用_arping使用方法-CSDN博客

ping、arp、tracert三大命令详细用法,弄懂立马成大神 - 知乎

C语言函数大全及详解 - 知乎

移植Qt到ARM平台及搭建Qt交叉编译环境_qt arm-CSDN博客

嵌入式Linux开发: 从0开始编译并启动ARM Linux内核(全志)_arm linux虚机镜像怎么启动-CSDN博客

Linux系统7个运行级别(runlevel)详解 - 知乎

Linux Ubuntu 20.04 —添加开机启动(服务/脚本) - Areas - 博客园

WebApi+Grpc+Jwt身份认证 - zeran - 博客园

.NetCore使用Grpc通信,简单的微服务+JWT认证 - zeran - 博客园

网络代理神器ProxyChains快速安装配置使用 - CentOS_centos 安装proxychains-CSDN博客

amd64/UEFI/systemd/gnome/gentoo安装过程记录_gentoo安装gnome_Freeman Z的博客-CSDN博客

Gentoo安装流程分享(step by step),第一篇之基本系统的安装 - 知乎

FreeBSD Jail 使用 ipfw 进行 NAT 与端口转发 | VGOT Blog

C++后端开发路线——愿我踩过的坑,你可以绕着走-电子工程专辑

【精选】Asp.net core 身份认证框架 Microsoft Identity的使用以及如何使用Idengtity创建自带的用户模型SignInManager和UserManager的使用等等_microsoft.aspnetcore.identity_爱吃奶酪的松鼠丶的博客-CSDN博客

git 瘦身 解决 .git文件夹过大的问题_git瘦身-CSDN博客

.Net Core JWT 动态设置接口与权限,.Net Core官方的 JWT 授权验证-腾讯云开发者社区-腾讯云

asp.net core使用identity+jwt保护你的webapi(一)——identity基础配置 - xhznl - 博客园

.NET Core中JWT+OAuth2.0实现SSO,附完整源码(.NET6) - 包子wxl - 博客园

.NET 6 集成 IdentityServer4+AspNetCore Identity 读取本地数据表用户

[编程变量命名规则及单词缩写字典 - 五维思考 - 博客园](https://www.cnblogs.com/zhaoshujie/p/14983712.html#:~:text=编程单词缩写规则 1 使用变量名中每个有典型意义的单词。 如 Count of Failure 写成,ed 等。 如 Paging Request 写成 PagReq 。)

CTK完整教程(OSGI for C++ 实现 C++ Qt 模块化)-腾讯云开发者社区-腾讯云

CTK完整教程(OSGI for C++ 实现 C++ Qt 模块化) | 来唧唧歪歪(Ljjyy.com) - 多读书多实践,勤思考善领悟

编译 CTK(Win10 + Qt 5.14.0 + VS2015)_ctk编译-CSDN博客

将线程绑定在某个具体的CPU逻辑内核上运行_c# setthreadaffinitymask_皓月如我的博客-CSDN博客

Kubernetes 网络插件 Calico 完全运维指南 - 知乎

mysql5.7性能提升一百倍调优宝典_mysql5.7调优-CSDN博客

mysql5.7配置文件优化 - John-Python - 博客园

MySQL5.7配置my.ini文件_mysql5.7配置文件my.ini_It&code的博客-CSDN博客

mysql5.7配置文件详解 - 知乎

装X神器,让你的grafana看板变得炫酷起来-腾讯云开发者社区-腾讯云

Go与SOAP - Go语言中文网 - Golang中文社区

[C#]Soap服务通讯(客户端)_c# soap_eahao的博客-CSDN博客

Onvif协议:使用gSOAP创建SOAP调用实例_gsoap 生成soap_serve-CSDN博客

postgresql + pgpool 构建容灾高可用集群(数据同步流复制/主备自动切换) - 世间草木 - 博客园

K8S Calico网络插件 - RidingWind - 博客园

(三)InfluxDB入门(借助Web UI)_influxdb web界面_灵泽~的博客-CSDN博客

Docker 私有仓库搭建 - 程序员果果 - 博客园

Docker容器:本地私有仓库、harbor私有仓库部署与管理_Zhang110_的博客-CSDN博客

Docker 私有镜像仓库的搭建及认证 - 知乎

Dapper的基本使用,Insert、Update、Select、Delete-CSDN博客

QT学习笔记-QT安装postgresql驱动_postgresql 驱动_CodingPioneer的博客-CSDN博客

Qt 编译MySQL数据库驱动——MSVC版本_qt mysql 编译_英雄施工的博客-CSDN博客

[Kapacitor在Chronograf中的配置和使用 - 墨天轮](https://www.modb.pro/db/107297#:~:text=添加一个Kapacitor实例 1 在左侧导航栏中,单击配置齿轮图标。 已加载InfluxDB源列表。 2 在列表中的” Acitve Kapacitor”标题下的最右列中,找到InfluxDB源,单击”,4 单击连接按钮。 如果”连接详细信息”正确,则会显示一条成功消息,并且新部分将显示”配置警报端点”。 5 如果使用了第三方警报服务或SMTP,请更新”配置警报端点”部分中的第三方设置。 6 点击Send TestAlert按钮,会发送一条测试邮件到邮箱)

单机版Ceph环境部署,Linux平台 - 知乎

基于gin框架和jwt-go中间件实现小程序用户登陆和token验证 - zzayne - 博客园

OpenIddict 登录及详细流程解析 - 龙码精神 - 博客园

Linq动态拼接Expression表达式(可多表字段判别)_c# linq 动态分组 expression-CSDN博客

【Qt开源项目推荐】目录(持续更新)_maoboxxx的博客-CSDN博客

Github上的一些高分Qt开源项目【多图】_qt项目_雪域迷影的博客-CSDN博客

Prometheus+Grafana - 随笔分类 - 曹伟雄 - 博客园

在Linux中修改打开文件数量限制的3种方法 - 知乎

mysql中grant all privileges on赋给用户远程权限_李在奋斗的博客-CSDN博客

使用 etcd 作为服务配置中心 | Ray’s blog

.Net Core微服务系列–配置中心 - RstarYan - 博客园

使用locust进行Websocket压力测试和接口压力测试-腾讯云开发者社区-腾讯云

Loki & Promtail 详解-腾讯云开发者社区-腾讯云

(1条消息) 示例:WPF中使用Grid+Margin实现抽屉菜单效果_wpf 抽屉式菜单_He BianGu的博客-CSDN博客

最新超详细C++经典Boost库介绍_Come_code的博客-CSDN博客

Unity开源项目整理(长期整理+不定期更新)_CloudHu1989的博客-CSDN博客

ubuntu14.04中离线安装docker - 博客频道 - CSDN.NET

Docker-容器的操作 - 头痛不头痛 - 博客园

.NET Core 跨平台发布(dotnet publish) - LineZero - 博客园

常用docker命令,及一些坑 - edwardsbean的专栏 - 博客频道 - CSDN.NET

Docker常用命令 - 小爷,有点狂 - 博客频道 - CSDN.NET

Docker 常用命令 - 碉堡了 - 博客园

搭建开发环境 - React Native 中文网

百度地图内网开发项目 - javascript_net的专栏 - 博客频道 - CSDN.NET

自己动手写一个前端路由插件 - 最骚的就是你 - 博客园

Autofac 组件、服务、自动装配 《第二篇》 - 逆心 - 博客园

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 - 萌萌的It人 www.itmmd.com - CSDN博客

js数据验证集合、js email验证、js url验证、js长度验证、js数字验证等简单封装_表单特效_脚本之家

搭建自己的私有云服务器私有NAS系列 | 入坑大数据

CentOS6.5安装MySQL5.7详细教程 - $nail - 博客园

mysql 5.7配置项最详细的解释 - CSDN博客

Prism - 随笔分类 - 西夏 - 博客园

一步步实现 Prism + MEF(一)— 搭建框架 - 无主之城 - 博客园

WPF: WPF 中的 Triggers 和 VisualStateManager - WPInfo - 博客园

C#多线程和线程池 - 夜、微凉 - 博客园

C# List源码分析(一) - CSDN博客

c# List实现原理 - micDavid - 博客园

(粗译) Prism and WPF - 定制 Tab region adapter - 01部分 - tan_Cool - 博客园

WPF教程(十一)WPF中的命令行参数 - CSDN博客

(粗译) Prism and WPF - 定制 Tab region adapter - 02部分 - tan_Cool - 博客园

一个过滤Textbox输入的WPF Behavior - Alex Geng - 博客园

如何给 CI CD 服务器搭建上 .NET 5 构建和运行环境 - 云+社区 - 腾讯云

.net4.5部署到docker容器 - 张占岭 - 博客园

DevOps - Concourse - Anliven - 博客园

manjaro20安装后的配置、常用软件的安装、环境搭建 - Lanomw - 博客园

.net IOC框架 Unity&Autofac - 简书

解决 git 中文路径显示 unicode 代码的问题_u014028063的博客-CSDN博客_git 中文路径

(18条消息) 开发自己的gentoo LiveCD_gentoo 制作livecd_suirosu的博客-CSDN博客

开始使用gentoo linux——gentoo安装笔记(下) - devilyouwei - 博客园

(18条消息) 如何在UEFI系统上双引导 Arch Linux 和 Windows 10 ?_efi双引导切换_鸠摩智首席音效师的博客-CSDN博客

2021 Archlinux双系统安装教程(超详细) - 知乎

使用MQTTnet部署MQTT服务(转) - 吞硬币的小猪 - 博客园

一种基于RSA+AES算法实现的软件授权License设计思路(附源码) - 掘金

LSI 9217-8i 阵列卡 介绍以及卡刷 IT/IR 模式 - 简书

[Kubeedge部署指南 - KubeEdge使用文档 - 《openEuler 21.09 使用指南》 - 书栈网 · BookStack](https://www.bookstack.cn/read/openeuler-21.09-zh/KubeEdge-KubeEdge使用文档.md#4. 部署边缘端应用)

MVVM处理TreeView的SelectedItem的绑定的两种方式_treeviewitem绑定事件_lishuangquan1987的博客-CSDN博客

RK3399平台入门到精通系列讲解 - 总目录_rk3399学习_Linux 笔记的博客-CSDN博客

国标GB28181平台对接视频流 - 王纲 - 博客园

解放双手! bat 批处理自动化运行程序 - 知乎

Windows 批处理(bat)语法大全 - 赵青青 - 博客园

.net core gRPC与IdentityServer4集成认证授权 - 福禄渣渣辉 - 博客园

ESC/POS 控制指令 - ma_fighting - 博客园

小票打印ESC/POS命令集 - 简书

EPSON ESC/POS指令 - 简书

在NVMe硬盘安装ArchLinux+Windows11 | UrsusFeline-Blog

数字孪生系统开发讲解和源代码_Bigemap的博客-CSDN博客

[pgpool-ii4.1.2 高可用集群主备切换]配置部分 - 世间草木 - 博客园

JAVA-WVP+ZLMediaKit+MediaServerUI实现摄像头 GB28181推流播放录制-CSDN博客

几十款 WPF 控件 - UI 库,总有一款适合你 - 独立观察员

Virtualize Your Network on FreeBSD with VNET | Klara Inc (klarasystems.com)

Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。 应用场景:一系列相互依赖的对象有不同的具体实现。提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合。

http://www.cnblogs.com/PatrickLiu/p/7596897.html

http://www.cnblogs.com/zhili/p/AbstractFactory.html

1. OpenCV

https://opencv.org

https://github.com/opencv/opencv

OpenCV是迄今为止最古老也是最受欢迎的开源计算机视觉库,旨在为计算机视觉应用提供通用底层算法。

支持跨平台应用,支持Windows,Linux,Android和macOS。支持各种主流的开发语言,例如:Python,Java,C++等。OpenCV有一个Python Wrapper,支持GPU的CUDA模型。包含一些可以转换为TensorFlow模型的模型。最初由Intel开发,现在可以在开源BSD许可证下免费使用。

OpenCV的主要功能包括:

  • 2D和3D图像工具包
  • 人脸识别
  • 手势识别
  • 运动检测
  • 人机交互
  • 对象检测
  • 图像分割和对象识别

2. Scikit-Image

https://scikit-image.org/

https://github.com/scikit-image/scikit-image

Scikit-Image是公认的最方便的Python视觉库,它是Scikit-Learn的一个扩展库。是监督和无监督机器学习最常用的工具之一。可以用于将NumPy数组作为图像对象进行处理。

以下是使用Scikit-image进行硬币识别的例子。

1
import skimage as ski image = ski.data.coins() # ... or any other NumPy array! edges = ski.filters.sobel(image) ski.io.imshow(edges) ski.io.show()

3. Pillow (PIL Fork)

https://github.com/python-pillow/Pillow

Pillow是一个Python编写的图像处理库。它支持Windows、Mac OS X和Linux平台,可以在C和Python语言中使用Pillow库。主要用于阅读和保存不同格式的图像,Pillow还包括各种基本图像变换功能,例如:旋转、合并、缩放等。

4. TorchVision

https://pytorch.org/vision/stable/index.html

TorchVision是PyTorch库的一个扩展库,TorchVision拥有计算机视觉中最常见的图像转换功能,还包含计算机视觉神经网络的数据集和模型架构以及常见数据集。TorchVision旨在为方便使用PyTorch模型进行计算机视觉图像转换,而无需将图像转换为NumPy数组。TorchVision可以用于Python和C++语言开发环境。可以通过pip install将TorchVision与PyTorch库一起搭配使用。

以下是预训练分割模型的使用例子。

5. MMCV

https://github.com/open-mmlab/mmcv

MMCV是一个基于PyTorch的图像/视频处理和转换器。它支持Linux、Windows和macOS等系统,是计算机视觉研究人员最常用的包之一。支持Python和C++开发语音。

6.YOLO

https://github.com/ultralytics/ultralytics

YOLO是最快的计算机视觉工具之一,由Joseph雷德蒙和Ali Farhadi于2016年开发,专门用于实时图像对象检测。YOLO使用将神经网络,将图像划分为网格,然后同时预测每个网格,以提高识别效率。

目前YOLO已经发布V8。YOLOv8 是一款前沿、最先进(SOTA)的模型,基于先前 YOLO 版本的成功并引入了新的功能和改进,进一步提升了性能和灵活性。YOLOv8 的快速、准确且易于使用,使其成为各种对象检测与跟踪、实例分割、图像分类和姿态估计任务的绝佳选择。

7. TensorFlow

https://github.com/tensorflow

TensorFlow是由GoogleBrain团队开发并于2015年11月发布的AI框架,旨在促进构建AI模型的过程。它有一些扩展解决方案,如针对浏览器和Node.js的TensorFlow.js,以及针对终端设备的TensorFlow Lite。另外,TensorFlow还提供了一个更好的框架TensorFlow Hub。这是一个更易于使用的平台,可以使用TensorFlow Hub实现重复使用BERT和Faster R-CNN训练模型、查找可随时部署的模型、托管模型以供他人使用。

TensorFlow允许用户开发与计算机视觉相关的机器学习模型,例如:人脸识别、图像分类、目标检测等。与OpenCV一样,Tensorflow也支持各种语言,如Python、C、C++、Java或JavaScript。

8. Keras

https://keras.io/

Keras是一个基于Python的开源软件库,对初学者来说特别易用,它允许快速构建神经网络模型,是一个模块化的AI工具箱,计算机视觉工程师可以利用它来快速组装应用、训练模型。Keras的底层框架使用TensorFlow,并且拥有强大的社区支持,因此用户众多。可以使用Keras实现的内容例如:

  • 图像分割和分类
  • 手写识别
  • 三维图像分类
  • 语义图像聚类

9.MATLAB

https://ww2.mathworks.cn/products/matlab.html

MATLAB是Matrix Laboratory的缩写,但它是一个付费编程平台,适合用于如机器学习、深度学习、图像处理、视频信号处理等方面的应用,是一个受到工程师和科学家喜欢的编程平台。它配备了一个计算机视觉工具箱,包含许多算法能力,如:

  • 视频目标检测与目标跟踪
  • 物体识别
  • 校准摄像机
  • 处理三维视觉

10.NVIDIA CUDA-X

https://developer.nvidia.com/gpu-accelerated-libraries

CUDA是计算统一设备架构的首字母缩写,而NVIDIA CUDA-X是CUDA的更新版本。NVIDIA CUDA-X是一个GPU加速库和工具的集合,可以开始使用新的应用程序或GPA加速。它包含数学库、并行算法库、图像和视频库、通信库和深度学习库,可用于各种任务,例如:人脸识别、图像处理、3D图形渲染等。它兼容大多数操作系统,并且支持许多主流AI编程语言,如:C、C++、Python、Fortran、MATLAB等。

11.NVIDIA Performance Primitives

https://developer.nvidia.com/npp

CUDA(Compute Unified Device Architecture的缩写)是NVIDIA开发的并行计算平台和应用程序编程接口(API)模型。它允许开发人员使用GPU(图形处理单元)的强大功能来加快处理密集型应用程序的速度。
该工具包包含NVIDIA Performance Primitives(NPP)库,可为多个领域(包括计算机视觉)提供GPU加速的图像、视频处理和信号处理功能。此外,CUDA架构可用于各种开发任务,例如:人脸识别、图像处理、3D图形渲染等。它支持各种编程语言,包括C、C++、Python、Fortran或MATLAB,并且还与大多数操作系统兼容。

12.OpenVINO

https://docs.openvino.ai/

OpenVINO是Open Visual Inference and Neural Network Optimization的缩写。它是一套非常全面的计算机视觉工具。它由英特尔开发,是一个可以免费使用的跨平台框架,具有多种视觉处理能力,包括:

  • 对象检测
  • 人脸识别
  • 图像彩色化
  • 运动识别

13.PyTorch

https://github.com/pytorch/pytorch

PyTorch是一个Python的开源机器学习框架,主要由Facebook的AI研究小组开发。在构建复杂体系结构时具有很大的灵活性。可以用于机器视觉方面开发图像评估模型、图像分割、图像分类等。

14.Caffe

https://caffe.berkeleyvision.org/

CAFFE是Convolutional Architecture for Fast Feature Embedding的缩写。是一个易于使用的开源深度学习和计算机视觉框架,由加州大学伯克利分校开发。它使用C++编写,支持多种开发语言,支持多种用于实现图像分类和图像分割的深度学习架构。Caffe可以用于视觉、语音和多媒体领域的应用,支持图像分割、分类等模型开发。

15.Detectron2

https://github.com/facebookresearch/detectron2

Detecrton 2是由Facebook AI Research(FAIR)开发的基于PyTorch的模对象检测库。Detectron 2是Detection的升级版;包括:Faster R-CNN、Mask R-CNN、RetinaNet、DensePose、Cascade R-CNN、Panoptic FPN和TensorMask等模型。Detecrton 2的功能包括:密集位姿预测、全景图像分割、联合分割、对象检测等。

16.SimpleCV

http://simplecv.org/

SimpleCV是一个开源免费的机器视觉框架。通这个框架,可以轻松访问OpenCV等几个高性能的计算机视觉库,而无需深入了解位深度、颜色空间、缓冲区管理或文件格式等复杂概念。

从TensorFlow 到 Caffe2:盘点深度学习框架 - allcloud - 博客园

Excerpt

机器之心报道 本文首先介绍GitHub中最受欢迎的开源深度学习框架排名,然后再对其进行系统地对比 下图总结了在GitHub中最受欢迎的开源深度学习框架排名,该排名是基于各大框架在GitHub里的收藏数,这个数据由MitchDeFelice在2017年5月初完成。 TensorFlow 地址:http


机器之心报道

本文首先介绍GitHub中最受欢迎的开源深度学习框架排名,然后再对其进行系统地对比

下图总结了在GitHub中最受欢迎的开源深度学习框架排名,该排名是基于各大框架在GitHub里的收藏数,这个数据由MitchDeFelice在2017年5月初完成。

TensorFlow

地址:https://www.tensorflow.org/

TensorFlow最开始是由谷歌一个称之为DistBeliefV2的库发展而来,它是一个公司内部的深度神经网络库,隶属于谷歌大脑项目。有一些人认为TensorFlow是由Theano彻底重构而来。

谷歌开源TensorFlow后,立即吸引了一大批开发爱好者。TensorFlow可以提供一系列的能力,例如图像识别、手写识别、语音识别、预测以及自然语言处理等。2015年11月9号,TensorFlow在Apache2.0协议下开源发布。

TensorFlow1.0版本已于2017年2月15日发布,这个版本是之前8个版本的优化改进版,其致力于解决Tensorflow之前遇到的一系列问题以及完善一些核心能力。TensorFlow获得成功的因素有:

TensorFlow提供了如下工具:

TensorBoard:对于网络模型和效果来说是一个设计优良的可视化工具。TensorFlowServing:可以保持相同的服务器架构和API,使得部署新算法和实验变得简单。TensorFlowServing提供了与TensorFlow模型开箱即用的整合,但同时还能很容易扩展到其它类型的模型和数据。

TensorFlow编程接口支持Python和C++。随着1.0版本的公布,Java、Go、R和HaskellAPI的alpha版本也将被支持。此外,TensorFlow还可在谷歌云和亚马孙云中运行。

随着0.12版本的发行,TensorFlow将支持Windows7、Windows10和Server2016。由于TensorFlow使用C++Eigen库,所以库可在ARM架构上编译和优化。这也就意味着你可以在各种服务器和移动设备上部署你的训练模型,而无需执行单独的模型解码器或者加载Python解释器。

TensorFlow支持细粒度的网格层,而且允许用户在无需用低级语言实现的情况下构建新的复杂的层类型。子图执行操作允许你在图的任意边缘引入和检索任意数据的结果。这对调试复杂的计算图模型很有帮助。

分布式TensorFlow(DistributedTensorFlow)被加进了0.8版本,它允许模型并行,这意味着模型的不同部分可在不同的并行设备上被训练。

自2016年3月,斯坦福大学、伯克利大学、多伦多大学和Udacity都将这个框架作为一个免费的大规模在线开放课程进行教授。

TensorFlow的缺点如下:

TensorFlow的每个计算流都必须构造为一个静态图,且缺乏符号性循环(symbolicloops),这会带来一些计算困难。没有对视频识别很有用的三维卷积(3-Dconvolution)。尽管TensorFlow现在比起始版本(v0.5)快了58倍,,但在执行性能方面依然落后于竞争对手。

Caffe

地址:http://caffe.berkeleyvision.org/

Caffe是贾扬清的杰作,目前他在FacebookAI平台担任首席工程师。Caffe可能是自2013年底以来第一款主流的工业级深度学习工具包。正因为Caffe优秀的卷积模型,它已经成为计算机视觉界最流行的工具包之一,并在2014年的ImageNet挑战赛中一举夺魁。Caffe遵循BSD2-Clause协议。

Caffe的快速使其完美应用于实验研究和商业部署。Caffe可在英伟达单个K40GPU上每天处理6000万张图像。这大概是1毫秒预测一张图片,4毫秒学习一张图片的速度,而且最新的版本处理速度会更快。

Caffe基于C++,因此可在多种设备上编译。它跨平台运行,并包含Windows端口。Caffe支持C++、Matlab和Python编程接口。Caffe拥有一个庞大的用户社区,人们在其中为被称为「ModelZoo(https://github.com/BVLC/caffe/wiki/Model-Zoo)」的深度网络库做贡献。AlexNet和GoogleNet就是社群用户构建的两个流行网络。

虽然Caffe在视频识别领域是一个流行的深度学习网络,但是Caffe却不能像TensorFlow、CNTK和Theano那样支持细粒度网络层。构建复杂的层类型必须以低级语言完成。由于其遗留架构,Caffe对循环网络和语言建模的支持总体上很薄弱。

Caffe2

地址:https://caffe2.ai/

目前,贾扬清和他在Facebook的团队正在开发新一代框架Caffe2。今年4月18日,Facebook开源了Caffe2。Caffe2与Caffe的区别是什么?Caffe2更注重模块化,在移动端、大规模部署上表现卓越。如同TensorFlow,Caffe2使用C++Eigen库,支持ARM架构。

用一个实用脚本,Caffe上的模型可轻易地被转变到Caffe2上。Caffe设计的选择使得它处理视觉类型的难题时很完美。Caffe2延续了它对视觉类问题的支持,且增加了对自然语言处理、手写识别、时序预测有帮助的RNN和LSTM支持。

期待不久之后能看到Caffe2超越Caffe,就像它宣称的那样在深度学习社区流行。

在本周三英伟达推出Volta架构的第一块加速卡TeslaV100后,Caffe的开发者第一时间展示了TeslaV100在Caffe2上运行ResNet-50的评测。数据显示在新框架和新硬件的配合下,模型每秒钟可以处理4100张图片。

链接:https://caffe2.ai/blog/2017/05/10/caffe2-adds-FP16-training-support.html

CNTK

链接:https://github.com/Microsoft/CNTK/wiki

微软的CNTK(MicrosoftCognitiveToolkit)最初是面向语音识别的框架。CNTK支持RNN和CNN类型的网络模型,从而在处理图像、手写字体和语音识别问题上,它是很好的选择。使用Python或C++编程接口,CNTK支持64位的Linux和Windows系统,在MIT许可证下发布。

与TensorFlow和Theano同样,CNTK使用向量运算符的符号图(symbolicgraph)网络,支持如矩阵加/乘或卷积等向量操作。此外,像TensorFlow和Theano一样,CNTK有丰富的细粒度的网络层构建。构建块(操作)的细粒度使用户不需要使用低层次的语言(如Caffe)就能创建新的复杂的层类型。

CNTK也像Caffe一样基于C++架构,支持跨平台的CPU/GPU部署。CNTK在AzureGPULab上显示出最高效的分布式计算性能。目前,CNTK不支持ARM架构,这限制了其在移动设备上的功能。

MXNet

链接:http://mxnet.io/

MXNet(发音为mix-net)起源于卡内基梅隆大学和华盛顿大学的实验室。MXNet是一个全功能、可编程和可扩展的深度学习框架,支持最先进的深度学习模型。MXNet支持混合编程模型(命令式和声明式编程)和多种编程语言的代码(包括Python、C++、R、Scala、Julia、Matlab和JavaScript)。2017年1月30日,MXNet被列入ApacheIncubator开源项目。

MXNet支持深度学习架构,如卷积神经网络(CNN)、循环神经网络(RNN)和其包含的长短时间记忆网络(LTSM)。该框架为图像、手写文字和语音的识别和预测以及自然语言处理提供了出色的工具。有些人称MXNet是世界上最好的图像分类器。

MXNet具有可扩展的强大技术能力,如GPU并行和内存镜像、快速编程器开发和可移植性。此外,MXNet与ApacheHadoopYARN(一种通用分布式应用程序管理框架)集成,使MXNet成为TensorFlow有力的竞争对手。

MXNet不仅仅只是深度网络框架,它的区别在于支持生成对抗网络(GAN)模型。该模型启发自实验经济学方法的纳什均衡。

Torch

链接:http://torch.ch/

Torch由Facebook的RonanCollobert和SoumithChintala,Twitter的ClementFarabet(现任职于英伟达),以及GoogleDeepMind的KorayKavukcuoglu共同开发。很多科技巨头(如Facebook、Twitter和英伟达)都使用定制版的Torch用于人工智能研究,这大大促进了Torch的开发。Torch是BSD3协议下的开源项目。然而,随着Facebook对Caffe2的研究,以及其对移动设备的支持,Caffe2正成为主要的深度学习框架。

Torch的编程语言为Lua。Lua不是主流语言,在开发人员没有熟练掌握Lua之前,使用Torch很难提高开发的整体生产力。

Torch缺乏TensorFlow的分布式应用程序管理框架,也缺乏MXNet和Deeplearning4J对YARN的支持。缺乏多种编程语言的API也限制了开发人员。

PyTorch

地址:http://pytorch.org/

PyTorch由AdamPaszke、SamGross与SoumithChintala等人牵头开发,其成员来自FacebookFAIR和其他多家实验室。它是一种Python优先的深度学习框架,在今年1月被开源,提供了两种高层面的功能:

使用强大的GPU加速的Tensor计算(类似numpy)

构建于基于tape的autograd系统的深度神经网络

该框架结合了Torch7高效灵活的GPU加速后端库与直观的Python前端,它的特点是快速成形、代码可读和支持最广泛的深度学习模型。如有需要,你可以复用你最喜欢的Python软件包(如numpy、scipy和Cython)来扩展PyTorch。该框架因为其灵活性和速度,在推出以后迅速得到了开发者和研究人员的青睐。随着GitHub上越来越多代码的出现,PyTorch作为新框架缺乏资源的问题已经得以缓解。

Deeplearning4J

地址:https://deeplearning4j.org/

Deeplearning4J(DL4J)是用Java和Scala编写的Apache2.0协议下的开源、分布式神经网络库。DL4J最初由SkyMind公司的AdamGibson开发,是唯一集成了Hadoop和Spark的商业级深度学习网络,并通过Hadoop和Spark协调多个主机线程。DL4J使用Map-Reduce来训练网络,同时依赖其它库来执行大型矩阵操作。

DL4J框架支持任意芯片数的GPU并行运行(对训练过程至关重要),并支持YARN(Hadoop的分布式应用程序管理框架)。DL4J支持多种深度网络架构:RBM、DBN、卷积神经网络(CNN)、循环神经网络(RNN)、RNTN和长短时间记忆网络(LTSM)。DL4J还对矢量化库Canova提供支持。

DL4J使用Java语言实现,本质上比Python快。在用多个GPU解决非平凡图像(non-trivialimage)识别任务时,它的速度与Caffe一样快。该框架在图像识别、欺诈检测和自然语言处理方面的表现出众。

Theano

地址:http://deeplearning.net/software/theano/

Theano由蒙特利尔大学算法学习人工智能实验室(MILA)维护。以Theano的创始人YoshuaBengio为首,该实验室是深度学习研究领域的重要贡献者,拥有约30至40名学生和教师。Theano支持快速开发高效的机器学习算法,在BSD协议下发布。

Theano的架构如同一个黑箱;整个代码库和接口使用Python,其中C/CUDA代码被打包成Python字符串。这使得开发人员很难导航(navigate)、调试和重构。

Theano开创了将符号图用于神经网络编程的趋势。Theano的符号式API支持循环控制(即scan),这使得实现RNN容易且高效。

Theano缺乏分布式应用程序管理框架,只支持一种编程开发语言。Theano是很好的学术研究工具,在单个CPU上运行的效率比TensorFlow更有效。然而,在开发和支持大型分布式应用程序时,使用Theano可能会遇到挑战。

在了解这些深度学习框架的基本内容后,下面我们可以看看它们之间在库资源、建模能力、速度等度量下的对比情况。

这组对比参考了多种公开基准评测,以及我们在图像/语音识别应用时对这些技术的主观印象。此外,你需要注意:

语言

当你开始一个深度学习项目时,你最好使用一个支持你所会语言的框架。比如Caffe(C++)和Torch(Lua)只能支持有限的语言(最近,随着PyTorch的出现,情况有所改观)。所以如果你希望选用上述两个框架,我们建议你事先熟悉C++或Lua语言。相比之下,TensorFlow与MXNet具有丰富的多语言支持,即使你对C++感到陌生也可以使用它们。

教程和资源

目前,各类深度学习框架的教程与可利用的资源在质量和数量上有着显著的不同。Theano,TensorFlow,Torch和MXNet有着很详尽的文档教程,很容易被初学者理解和实现。与此相比,虽然微软的CNTK和英特尔的NervanaNeon也是强大的工具,我们却很少能见到有关它们的新手级资料。此外,在研究过程中,我们发现GitHub社区的参与度不仅可以用于准确地评价不同工具的开发水平,而且还是在搜索StackOverflow或repo的GitIssues时能否快速解决问题的参考性指标。当然,作为谷歌提供的框架,TensorFlow理所当然地在教程,资源,开发者和社区贡献者的数量上遥遥领先。

CNN建模能力

卷积神经网络(CNN)经常被用于图像识别、推荐引擎和自然语言识别等方向的应用。CNN由一组多层的神经网络组成,在运行时会将输入的数据进行预定义分类的评分。CNN也可用于回归分析,例如构成自动驾驶汽车中有关转向角的模型。在横评中,我们评价一种框架的CNN建模能力考虑到以下几个特性:定义模型的机会空间、预构建层的可用性、以及可用于连接这些层的工具和功能。我们发现,Theano,Caffe和MXNet都有很好的CNN建模能力。其中,TensorFlow因为易于建立的InceptionV3模型,Torch因为其丰富的CNN资源——包括易于使用的时间卷积集使得这两种框架在CNN建模能力上脱颖而出。

RNN建模能力

循环神经网络(RNN)常用于语音识别,时间序列预测,图像字幕和其他需要处理顺序信息的任务。由于预建的RNN模型不如CNN数量多,因此,如果你已经有一个RNN深度学习项目,优先考虑旧RNN模型是在哪种框架里实现的最重要。目前,Caffe上的RNN资源最少,而Microsoft的CNTK和Torch有丰富的RNN教程和预构建模型。当然,最流行的TensorFlow中也有一些RNN资源,TFLearn和Keras中更有很多使用TensorFlow的RNN示例。

架构

为在特定框架中构建和训练新模型,易于使用和模块化的前端是至关重要的。TensorFlow,Torch和MXNet都有直观而模块化的架构,让开发相对变得简单。相比之下,我们在Caffe这样的框架上需要进行大量的工作才能创建一个新层。另外我们发现在开发过程中,因为有TensorBoardwebGUI等应用的存在,TensorFlow极易在训练中和训练后进行debug和监控。

速度

Torch和Nervana具有开源卷积神经网络基准测试的最佳性能:

https://github.com/soumith/convnet-benchmarks/blob/master/README.md

Tensorflow的性能在大多数测试中是具有竞争力的,而Caffe和Theano稍稍落后:

https://github.com/tobigithub/tensorflow-deep-learning/wiki/tf-benchmarks

微软声称他们的CNTK在一些RNN训练任务中有最快的速度。

在另一项对比Theano、Torch和TensorFlow的RNN性能的研究中,Theano是其中最快的:

https://arxiv.org/abs/1511.06435

多GPU支持

大多数深度学习应用都需要用到巨量的浮点运算(FLOP)。例如,百度的DeepSpeech识别模型需要10sExaFLOPs用于训练,这是大于10e18的计算量:

https://arxiv.org/abs/1512.02595

考虑到目前英伟达Pascal架构的TitanX等顶级显卡可以每秒执行10e9FLOP:

https://www.nvidia.com/en-us/geforce/products/10series/titan-x-pascal/

因此,假如需要在大型数据集上训练一个新模型——用单GPU机器的话——可能会需要一个星期之久。为了减少构建模型所需的时间,我们需要使用多GPU并联的方式组建自己的机器。幸运的是,上述大部分架构都可以很好地支持多GPU运算。其中,据报道MXNet有着最好的多GPU优化引擎:

http://www.allthingsdistributed.com/2016/11/mxnet-default-framework-deep-learning-aws.html

Keras兼容性

Keras是一个用于快速构建深度学习原型的高级库。我们在实践中发现,它是数据科学家应用深度学习的好帮手。Keras目前支持两种后端框架:TensorFlow与Theano,而且Keras再过不久就会成为TensorFlow的默认API:

http://www.fast.ai/2017/01/03/keras/

尽管如此,Keras的作者表示,这一高级库在未来仍会作为支持多种框架的前端存在:

https://github.com/fchollet/keras/issues/5050#issuecomment-272945570

总结

如果你想要开始深度学习,你应该从评估自己的团队技能和业务需求开始。例如,如果一个以Python为中心的团队想开发图像识别的应用程序,你应该使用TensorFlow,因为它有丰富的资源,较好性能和完整的原型工具。如果一个有Lua能力的团队希望将RNN大规模应用到生产环境中去,他们则会受益于Torch的高速和强大的RNN建模能力。

未来,我们将继续讨论在更大规模的应用中这些框架的表现。这些挑战包括多机并联时的多GPU优化,多种开源库的兼容性,如CMUSphinx和Kaldi等,尽请期待。

深度学习领域发展迅猛,江湖风起云涌。在此,咪博士为大家细细盘点、比较,各大深度学习框架。也祝大家都能训出好模型,调出好参数。

以下是咪博士的观点,供大家参考:

  • 如果你是初学者,那么推荐选择 Keras 或 Gluon 这样简单易用的接口入门。至于是 Keras 还是 Gluon 就不必太纠结了,因为二者都很容易上手,完全可以都学一下。如果非要分个先后的话,可以先试试 Gluon 毕竟开发者是中国人,有官方出品的中文教程带你入门。
  • 学完 Keras 或 Gluon “前端”框架之后,再选择一个“后端”框架深入学习,TensorFlow (Keras 后端) 或 MXNet (Gluon 后端) 是咪博士推荐的 2 个后端框架。TensorFlow 谷歌 (Google) 出品,MXNet 有 亚马逊 (Amazon) 支持,它们都是非常优秀的深度学习框架。至于是 TensorFlow 还是 MXNet,那就得看你的需求了。TensorFlow 受众更广,但是性能较差,而且不支持动态计算图;MXNet 目前还比较小众,但性能较好,而且支持动态计算图,十分方便搞自然语言处理 (NLP) 的朋友。
  • 学习完后端框架之后,你就可以非常灵活地定制自己的神经网络,自由地在深度学习的世界里翱翔了。这里候,如果你有兴趣(或需要),可以试试其他的一些框架,如 PyTorch (灵活多变,适合研究), Caffe2 (性能优化,手机也能跑), Deeplearning4j (Java 首选,整合 Hadoop, Spark), 以及 ConvNetJS (Js 开发,浏览器上玩深度学习)。
  • 其他一些深度学习框架,诸如 Theano (Lasagne, 以及 Blocks), Torch, Caffe, CNTK, Chainer, Paddle, DSSTNE, DyNet, BigDL, Neon 等,由于众多原因,咪博士就不给大家推荐了。

下面是详细的比较和说明:

一、推荐使用

Keras

受到 Torch 启发,Keras 提供了简单易用的 API 接口,特别适合初学者入门。其后端采用 TensorFlow, CNTK,以及 Theano。另外,Deeplearning4j 的 Python 也是基于 Keras 实现的。Keras 几乎已经成了 Python 神经网络的接口标准。

Gluon

亚马逊 (Amazon) 和 微软 (Microsoft) 于 2017 年 10 月联合推出的深度学习 API。Gluon 类似 Keras,提供了简单易用的 API 接口。但和 Keras 不一样的地方是,Gluon 还支持动态计算图(对自然语言处理特别有用)。Gluon 后端目前采用 MXNet,未来还将支持微软的 CNTK。

TensorFlow

谷歌 (Google) 大厂出品,追随者众多。相比其他框架,TensorFlow 速度较慢,但它提供的 TensorBoard 可视化工具还是很不错的。

MXNet

已被 亚马逊 (Amazon) 选为 AWS 上的深度学习框架,支持动态图计算。MXNet 有许多中国开发者,因而有非常良好的中文文档支持。Gluon 接口使得 MXNet 像 Keras 一样简单易用。

二、值得一试

PyTorch

背后金主是 脸书 (Facebook) ,同样支持动态计算图,提供很好的灵活性,适合研究。

Caffe2

同样是 脸书 (Facebook) 出品,为生产环境设计,提供在各种平台(包括移动设备)的运行时。

Deeplearning4j

与其他(大多数)基于 Python 的深度学习框架不同,Deeplearning4j 基于 Java 开发,与 Hadoop, Spark 生态结合得很好。尤其令人称道的是其优秀的文档,官司方文档直接就有中文版本。另外,虽然是面向 Java 的框架,Deeplearning4j 也提供了 Python 的接口(基于 Keras 实现)

ConvNetJS

基于 Javascript 的深度学习框架,可以在浏览器中训练深度神经网络。最重要的用途是帮助学习 Deep Learning

三、不推荐

Theano, Lasagne, 以及 Blocks

Yoshua Bengio 于 2017 年 09 月宣布不再维护 Theano,所以这个项目事实上已经宣告死亡了。其他基于 Theano 的库,如 Lasagne 和 Blocks,也可以散了。

Torch

虽然设计精良(Keras 就是参考 Torch 设计的),但它基于 Lua 语言,太过小众了。而且 Facebook 已经推出了 Python 版本的 PyTorch 了。

Caffe

Caffe2 已经正式发布了,彻底取代 Caffe 只是时间问题罢了。

CNTK

微软出品,授权协议有一些特别,而且似乎也没有什么特别亮眼的地方。

Chainer

曾经是动态计算图的首选框架,特别适用于自然语言处理。但是,现在许多其他的框架,如 MXNet, PyTorch, 以及 DyNet 也支持该特性,所以 Chainer 的这一优势也就不复存在了。

Paddle

百度的深度学习框架,受众太小。

DSSTNE

曾是亚马逊的深度学习引擎,但是很小众,而且现在亚马逊又选择了 MXNet,所以 DSSTNE 的前途就更渺茫了。

DyNet

源自卡耐基梅隆大学,支持动态计算图,但是太小众了。

BigDL

Intel 基于 spark 的深度学习库,但只能运行在 Intel 芯片之上。

Neon

据说速度很快,但太过小众,而且发展还不完善,许多特性还不支持。

参考

  1. https://deeplearning4j.org/compare-dl4j-tensorflow-pytorch
  2. http://docs.chainer.org/en/stable/comparison.html
  3. http://www.ipaomi.com/2017/11/06/2018-年-深度学习框架-盘点-比较-推荐/

【坚信技术技术改变世界】 【欢迎学习交流】 【免费】【视频教程】【问答社区】 【爱跑咪】【http://www.iPaoMi.com】 【QQ交流: 57148911】