算法金 | 时间序列预测真的需要深度学习模型吗?是的,我需要。不,你不需要? - 算法金「全网同名」 - 博客园

mikel阅读(327)

来源: 算法金 | 时间序列预测真的需要深度学习模型吗?是的,我需要。不,你不需要? – 算法金「全网同名」 – 博客园

参考 论文:https://arxiv.org/abs/2101.02118

更多内容,见微*公号往期文章:

审稿人:拜托,请把模型时间序列去趋势!!

使用 Python 快速上手 LSTM 模型预测时间序列

1. 时间序列预测的重要性

时间序列预测,这玩意儿在数据分析界可是个香饽饽,尤其在电力、交通、空气质量这些领域里,预测得准,资源分配更合理,还能让相关部门提前做好准备。但深度学习这小子横空出世,开始抢传统统计学方法的风头。那么问题来了,时间序列预测非得用深度学习吗?咱们今天就来掰扯掰扯。

2. 传统时间序列预测模型

2.1 滚动平均(Moving Average, MA)

滚动平均,这招简单粗暴,就是把一段时间的数据一平均,把那些随机的波动给抹平,让长期趋势露个脸。这招对付那些没啥花头的时间序列挺管用。

2.2 向量自回归(Vector Autoregression, VAR)

VAR模型,这货是个多面手,能把多个时间序列的过去值拿来预测未来,把变量间的相互勾搭给看个清楚。这在经济学和金融领域里头,预测经济指标的相互作用,玩得风生水起。

2.3 自回归综合移动平均(AutoRegressive Integrated Moving Average, ARIMA)

ARIMA模型,这家伙把自回归、差分、移动平均三招合一,专门对付时间序列里的趋势和季节性。得先把序列给整平稳了,这样预测起来才靠谱。这模型在经济预测、销售预测、气象预测这些领域里头,玩得挺溜。

传统时间序列预测模型优点不少:

  1. 理论基础扎实:这些模型都是统计学出身,数学表达式和参数估计方法都明明白白。
  2. 解释性强:模型参数都有个说法,分析起来容易。
  3. 计算效率高:计算起来简单,处理大数据也不费劲。

不过,这些老方法在处理复杂的非线性关系和多变量交互效应时,就显得有点力不从心了。数据量大了,复杂度高了,深度学习方法就有机会上位了。

\

3. 深度学习模型

3.1 长短期记忆网络(Long Short-Term Memory, LSTM)

LSTM,这货是递归神经网络的升级版,门控机制一加,梯度消失问题就解决了。这货记性好,长时间序列里的信息记得牢,预测起来自然给力。

3.2 基于注意力的双阶段RNN(Dual-stage Attention-based Recurrent Neural Network, DARNN)

DARNN,这货加上了注意力机制,能挑出时间序列里的重要特征,预测精度就上去了。先提取特征,再用注意力机制和解码器预测,这招在不少预测任务里都挺灵。

3.3 Deep Global Local Forecaster (DeepGlo)

DeepGlo,这货把时间序列分成全局趋势和局部细节,分别建模,最后合并预测结果。这样不同尺度的特征都能照顾到,预测的准确性自然就高了。

3.4 时空融合转化器(Temporal Fusion Transformer, TFT)

TFT,这货用多头注意力机制和序列到序列的结构,处理时间序列的复杂关系。短期长期依赖关系都能搞定,处理复杂时空特征的数据,表现杠杠的。

3.5 DeepAR

DeepAR,这货基于自回归思想,序列到序列的建模方式,用过去的时间序列数据预测未来。这货能处理大规模高维数据,预测时还能考虑多个时间序列的相互影响,精度自然不低。

深度学习模型虽然在时间序列预测上挺能打,但复杂度高,计算成本也高,对数据量和计算资源要求也不小。所以选模型的时候,得综合考虑应用场景、数据特点和计算资源,挑最合适的。

4. GBRT模型的对比研究

4.1 研究背景

深度学习虽然火,但传统的机器学习方法,比如梯度提升回归树(GBRT),在实际应用中也挺能打。GBRT通过多个弱学习器组合,提升预测性能。研究人员把GBRT和深度学习模型比了比,看看谁更牛。

4.2 研究方法

这项研究把时间序列预测任务变成了窗口回归问题,对GBRT模型进行了特征设计和结构调整。就是把时间序列数据分成固定长度的窗口,每个窗口的数据用来预测下一个时间点的值。所有模型都用同样的数据集和评估指标,公平比较。

4.3 研究数据集

研究用了多个公开的时间序列数据集,涵盖能源消耗、交通流量、空气质量等领域,数据时间跨度和频率各异,全面评估模型表现。

4.4 评估指标

评估模型预测性能,用了均方误差(MSE)、均绝对误差(MAE)和对称平均绝对百分比误差(sMAPE)这些常用指标,全面衡量预测误差和稳定性。

研究结果,GBRT在多个数据集上的表现超过了所有评估的深度神经网络(DNN)模型。这说明,在时间序列预测任务中,传统机器学习方法有时候还挺能打的。

5. GBRT模型的优势

5.1 解释性高

GBRT模型,就像个明白事理的老江湖,每个决策点都清清楚楚,让人一看就懂。跟那些深不可测的深度学习模型比起来,它更接地气,容易让人信服。

5.2 计算效率高

说到计算效率,GBRT模型就像是轻功了得的侠客,行动迅速,不拖泥带水。深度学习模型可能还在慢吞吞地翻山越岭,它已经一溜烟跑到了目的地。

5.3 特征工程能力强

GBRT模型在特征工程上,就像个手艺高超的铁匠,能将普通的铁块锻造成锋利的宝剑。通过巧妙设计特征,它能够捕捉数据中的关键信息,让预测更加精准。

5.4 灵活性高

GBRT模型的灵活性,就像个能屈能伸的武林高手,无论面对什么样的对手,都能随机应变,调整自己的策略。通过调整参数,它能够适应各种不同的数据集和预测任务。

虽然GBRT模型在时间序列预测中表现出色,但它的威力还是得靠精心的特征工程和细致的参数调整来发挥。在实际应用中,得像打磨宝剑一样,细心调校,才能让它发挥出最大的威力。

6. 特征工程与损失函数的重要性

6.1 特征工程

特征工程,就像是给武林高手挑选武器,选对了,战斗力倍增。在时间序列预测中,通过提取时间、滚动统计、滞后等特征,能让模型更加敏锐地捕捉数据的脉动。

6.2 损失函数

损失函数,就像是武林比武的规则,决定了比试的胜负。选择合适的损失函数,能让模型在训练中更加精准地找到自己的不足,从而不断进步。

通过实验,我们发现GBRT模型在特征工程和损失函数的选择上,展现出了极高的灵活性和适应性。就像武林高手在比武中不断调整自己的招式,GBRT模型也能通过精细的特征设计和合理的损失函数选择,显著提升自己的预测性能。

7. 模型架构的创新

7.1 架构创新的难点

模型架构的创新,就像是武林中的绝世武功,听起来很酷,但练起来却难如登天。新架构往往需要大量的实验和调优,而且复杂性可能会带来更高的计算成本和更长的训练时间。

7.2 成功的架构创新实例

尽管如此,还是有些架构创新,像是武林中的奇遇,让人眼前一亮。比如LSTM的门控机制,就像是突然领悟了一门高深的内功心法,让模型在处理长时间依赖关系时更加得心应手。

7.3 特征工程和损失函数的优先性

研究表明,当特征工程和损失函数设置得当,架构创新带来的提升其实有限。这就像是武林中的基本功,只有基本功扎实了,才能让后续的招式发挥出更大的威力。

7.4 创新带来的风险

模型架构的创新,也伴随着一定的风险。新架构的复杂性可能会导致训练过程中的不稳定性,增加过拟合的风险,同时还可能需要更多的数据和计算资源。在实践中,如何平衡创新带来的潜在收益和这些风险,是一个需要仔细权衡的问题。

8. 多输出预测的局限性

8.1 多输出预测的基本方法

在时间序列预测中,把预测器包装成支持多输出的MultiOutputRegressor,就像是一箭双雕,提高了预测效率,同时还能捕捉不同时间序列之间的相互依赖。

8.2 存在的局限性

但多输出预测也有它的局限性。由于所有输出都共享同一个模型结构和参数设置,这就像是用同一把钥匙开所有的锁,可能无法充分适应每个时间序列的独特性,导致预测精度下降。

8.3 改进建议

为了克服这些局限,可以考虑在模型中增加更强的约束,就像是给每个锁配上一把专属的钥匙。通过引入分层模型结构,在顶层捕捉不同时间序列的共同特征,在底层分别建模每个时间序列的特有特征。

8.4 实验验证

研究表明,通过引入这些改进措施,多输出预测模型在多个时间序列预测任务中取得了显著提升。这就像是武林中的高手,通过不断的修炼和创新,最终达到了新的境界。

9. 实验结果

9.1 单变量时间序列预测

在单变量时间序列预测任务中,GBRT模型就像是一匹黑马,无论是有协变量还是没有协变量,都展现出了优越的性能。特别是在没有协变量的情况下,通过合理的特征设计,GBRT模型能够有效捕捉时间序列中的趋势和波动,预测结果优于大多数深度学习模型。

9.2 多变量时间序列预测

在多变量时间序列预测任务中,GBRT模型与LSTNet、DeepAR、DeepState、TFT等深度学习模型相比,就像是武林中的一场较量,GBRT模型在大多数数据集上都取得了更高的预测精度。这主要归功于GBRT模型在特征工程和参数调整上的灵活性,使其能够更好地适应不同的数据特点和预测任务。

9.3 有协变量的预测

在有协变量的预测任务中,GBRT模型就像是得到了神助攻,通过合理利用协变量信息,能够进一步提升预测精度。例如,在能源消耗预测任务中,通过引入天气数据和历史用电量作为协变量,GBRT模型能够更准确地预测未来的能源需求。

9.4 结果分析

总体来看,实验结果验证了GBRT模型在时间序列预测中的竞争力。尽管深度学习模型在某些特定任务中表现出色,但GBRT模型通过合理的特征设计和参数调整,在大多数情况下能够取得更高的预测精度和稳定性。

[ 抱个拳,总个结 ]

  • 时间序列预测,在多个领域里头,传统方法和深度学习方法各有千秋。
  • 传统时间序列预测模型,像MA、VAR和ARIMA,理论基础扎实,计算效率高,但在处理复杂的非线性关系和多变量交互效应方面,就显得有点力不从心。
  • 深度学习模型,如LSTM、DARNN、DeepGlo、TFT和DeepAR,自动学习数据中的复杂模式和特征,在多个预测任务中展示出强大的性能。
  • GBRT模型,在实验中表现优越,尤其在适当配置的情况下,能够超过许多最先进的深度学习模型。
  • 特征工程和损失函数,在机器学习中至关重要,合理的特征设计和损失函数选择能够显著提升模型性能。
  • 模型架构的创新带来的提升有限,优先关注特征工程和损失函数的优化更为重要。
  • 多输出预测方法存在局限性,通过合理的改进措施可以提升其性能。
  • 实验结果显示,GBRT模型在单变量和多变量时间序列预测中均表现出色,特别是在有协变量的情况下,优势更加明显。

更多内容,见微*公号往期文章:

审稿人:拜托,请把模型时间序列去趋势!!

使用 Python 快速上手 LSTM 模型预测时间序列

– 科研为国分忧,创新与民造福 –

日更时间紧任务急,难免有疏漏之处,还请大侠海涵内容仅供学习交流之用,部分素材来自网络,侵联删

记一次 .NET某网络边缘计算系统 卡死分析 - 一线码农 - 博客园

mikel阅读(455)

来源: 记一次 .NET某网络边缘计算系统 卡死分析 – 一线码农 – 博客园

一:背景

1. 讲故事

早就听说过有什么 网络边缘计算,这次还真给遇到了,有点意思,问了下 chatgpt 这是干嘛的 ?

网络边缘计算是一种计算模型,它将计算能力和数据存储位置从传统的集中式数据中心向网络边缘的用户设备、传感器和其他物联网设备移动。这种模型的目的是在接近数据生成源头的地方提供更快速的计算和数据处理能力,从而减少数据传输延迟并提高服务质量。网络边缘计算使得在设备本地进行数据处理和决策成为可能,同时也有助于减轻对中心数据中心的网络流量和负载。

看到.NET还有这样的应用场景还是挺欣慰的,接下来就来分析下这个dump到底是怎么回事?

二:WinDbg 分析

1. 为什么会卡死

不同程序的卡死有不同的分析方式,所以要先鉴别下程序的类型以及主线程的调用栈即可,参考如下:


0:000> !eeversion
5.0.721.25508
5.0.721.25508 @Commit: 556582d964cc21b82a88d7154e915076f6f9008e
Server mode with 64 gc heaps
SOS Version: 8.0.10.10501 retail build

0:000> k
 # Child-SP          RetAddr               Call Site
00 0000ffff`e0dddac0 0000fffd`c194c30c     libpthread_2_28!pthread_cond_wait+0x238
...
18 (Inline Function) --------`--------     libcoreclr!RunMain::$_0::operator()::{lambda(Param *)#1}::operator()+0x14c [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1536] 
19 (Inline Function) --------`--------     libcoreclr!RunMain::$_0::operator()+0x188 [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1538] 
1a 0000ffff`e0dde600 0000fffd`c153e860     libcoreclr!RunMain+0x298 [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1538] 
...
20 0000ffff`e0dded10 0000fffd`c1bf7800     libhostpolicy!corehost_main+0xc0 [/root/runtime/src/installer/corehost/cli/hostpolicy/hostpolicy.cpp @ 409] 
21 (Inline Function) --------`--------     libhostfxr!execute_app+0x2c0 [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 146] 
22 (Inline Function) --------`--------     libhostfxr!<unnamed-namespace>::read_config_and_execute+0x3b4 [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 520] 
23 0000ffff`e0ddeeb0 0000fffd`c1bf6840     libhostfxr!fx_muxer_t::handle_exec_host_command+0x57c [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 1001] 
24 0000ffff`e0ddf000 0000fffd`c1bf4090     libhostfxr!fx_muxer_t::execute+0x2ec
25 0000ffff`e0ddf130 0000aaad`c9e1d22c     libhostfxr!hostfxr_main_startupinfo+0xa0 [/root/runtime/src/installer/corehost/cli/fxr/hostfxr.cpp @ 50] 
26 0000ffff`e0ddf200 0000aaad`c9e1d468     dotnet!exe_start+0x36c [/root/runtime/src/installer/corehost/corehost.cpp @ 239] 
27 0000ffff`e0ddf370 0000fffd`c1c63fe0     dotnet!main+0x90 [/root/runtime/src/installer/corehost/corehost.cpp @ 302] 
28 0000ffff`e0ddf3b0 0000aaad`c9e13adc     libc_2_28!_libc_start_main+0xe0
29 0000ffff`e0ddf4e0 00000000`00000000     dotnet!start+0x34

从卦中的指标来看,这是一个 Linux 上部署的 Web网站,既然是网站的卡死,那就要关注各个线程都在做什么。

2. 线程都在干嘛

以我多年的分析经验,绝大多数都是由于 线程饥饿 或者说 线程池耗尽 导致的,首先我们看下线程池的情况。


0:000> !t
ThreadCount:      365
UnstartedThread:  0
BackgroundThread: 354
PendingThread:    0
DeadThread:       10
Hosted Runtime:   no
                                                                                                            Lock  
 DBG   ID     OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
   0    1    31eaf 0000AAADF267C600  2020020 Preemptive  0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn 
...
 423  363    36d30 0000FFDDB4000B20  1020220 Preemptive  0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker) 
 424  364    36d31 0000FFDDA8000B20  1020220 Preemptive  0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker) 
 425  365    36d32 0000FFDDAC000B20  1020220 Preemptive  0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker) 

0:000> !tp
Using the Portable thread pool.

CPU utilization:  9%
Workers Total:    252
Workers Running:  236
Workers Idle:     13
Worker Min Limit: 64
Worker Max Limit: 32767

Completion Total:   0
Completion Free:    0
Completion MaxFree: 128
Completion Current Limit: 0
Completion Min Limit:     64
Completion Max Limit:     1000

从卦中看当前有 365 个托管线程,这个算多吗?对于64core 来说,这个线程其实算是正常,训练营里的朋友都知道,server版的gc仅gc线程就有 64*2=128 个,接下来再看一个指标就是当前是否存在任务积压? 可以使用 !ext tpq 命令,参考输出如下:


0:000> !ext tpq
global work item queue________________________________

local per thread work items_____________________________________

从卦中看当前没有任务积压,这就有点反经验了。

3. 真的不是线程饥饿吗

最后一招比较彻底,就是看各个线程栈都在做什么,可以使用 ~*e !clrstack 命令。

这不看不知道,一看吓一跳,有 193 个线程在 Task.Result 上等待,这玩意太经典了,然后从上面的调用栈 UIUpdateTimer_Elapsed 来看,貌似是一个定时器导致的,接下来我就好奇这代码是怎么写的?

分析上面的代码之后,我发现它是和 Linux Shell 窗口进行命令交互,不知道为何 Shell 没有响应导致代码在这里卡死。

4. 为什么线程池没有积压

相信有很多朋友对这个反经验的东西很好奇为什么请求没有积压在线程池,其实这个考验的是你对 PortableThreadPool 的底层了解,这里我就简单说一下吧。

  1. 在 ThreadPool 中有一个 GateThread 线程是专门给线程池动态注入线程的,参考代码如下:

private static class GateThread
{
    private static void GateThreadStart()
    {
        while (true)
        {
            bool wasSignaledToWake = DelayEvent.WaitOne((int)delayHelper.GetNextDelay(tickCount));

            WorkerThread.MaybeAddWorkingWorker(threadPoolInstance);
        }
    }
}

  1. 一旦有人调用了 Task.Result 代码,内部会主动唤醒 DelayEvent 事件,告诉 GateThread 赶紧通过 MaybeAddWorkingWorker 方法给我注入新的线程,参考代码如下:

private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken cancellationToken)
{
    bool flag3 = ThreadPool.NotifyThreadBlocked();

}
internal static bool NotifyThreadBlocked()
{
    if (UsePortableThreadPool)
    {
        return PortableThreadPool.ThreadPoolInstance.NotifyThreadBlocked();
    }
    return false;
}
public bool NotifyThreadBlocked()
{
    GateThread.Wake(this);
}

上面这种主动唤醒的机制是 C# 版 PortableThreadPool 做的优化来缓解线程饥饿的,这里有一个重点就是它只能缓解,换句话说如果上游太猛了还是会有请求积压的,但为什么这里没有积压呢? 很显然上游不猛呗,那如何眼见为实呢? 这就需要看 timer 的周期数即可,到当前的线程栈上给扒出来。


0:417> !DumpObj /d 0000ffee380757f8
Name:        System.Timers.Timer
MethodTable: 0000fffd4ab24030
EEClass:     0000fffd4ad6e140
Size:        88(0x58) bytes
File:        /home/user/env/dotnet/shared/Microsoft.NETCore.App/5.0.7/System.ComponentModel.TypeConverter.dll
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
0000fffd4c947498  400001c        8 ...ponentModel.ISite  0 instance 0000000000000000 _site
0000000000000000  400001d       10 ....EventHandlerList  0 instance 0000000000000000 _events
0000fffd479195d8  400001b       98        System.Object  0   static 0000000000000000 s_eventDisposed
0000fffd47926f60  400000e       40        System.Double  1 instance 3000.000000 _interval
0000fffd4791fb10  400000f       48       System.Boolean  1 instance                1 _enabled
0000fffd4791fb10  4000010       49       System.Boolean  1 instance                0 _initializing
0000fffd4791fb10  4000011       4a       System.Boolean  1 instance                0 _delayedEnable
0000fffd4ab241d8  4000012       18 ...apsedEventHandler  0 instance 0000ffee3807aae8 _onIntervalElapsed
0000fffd4791fb10  4000013       4b       System.Boolean  1 instance                1 _autoReset
0000fffd4c944ea0  4000014       20 ...SynchronizeInvoke  0 instance 0000000000000000 _synchronizingObject
0000fffd4791fb10  4000015       4c       System.Boolean  1 instance                0 _disposed
0000fffd49963e28  4000016       28 ...m.Threading.Timer  0 instance 0000ffee38098dc8 _timer
0000fffd48b90a30  4000017       30 ...ing.TimerCallback  0 instance 0000ffee3807aaa8 _callback
0000fffd479195d8  4000018       38        System.Object  0 instance 0000ffee38098db0 _cookie

从卦中看当前是 3s 为一个周期,这就能解释为什么线程池没有积压的底层原因了。

三:总结

这个卡死事故还是蛮好解决的,如果有一些经验直接用dotnet-counter也是能搞定的,重点在于这是一个 Linux的dump,同时又是 .NET上的一个很好玩的场景,故此分享出来。

值得推荐的.NET ORM框架 - 追逐时光者 - 博客园

mikel阅读(450)

来源: 值得推荐的.NET ORM框架 – 追逐时光者 – 博客园

前言:

最近有很多同学问我.NET方面有哪些好用的ORM框架,我觉得这方面的介绍网上应该会介绍的比较全面文章,于是我想搜一篇全面的介绍文章发给他们结果我发现网上说来说去基本上就是那几个,于是就有了这篇文章。该篇文章已收录到【DotNetGuide(C#/.NET/.NET Core学习、工作、面试指南)👉】GitHub知识库中欢迎大家前往订阅(有帮助的话别忘了给我一颗小星星⭐),假如大家有更好的ORM框架推荐可以前往GitHub仓库中留言💖!

什么是ORM?

ORM 是 Object Relational Mapping 的缩写,译为“对象关系映射”,是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。它解决了对象和关系型数据库之间的数据交互问题,ORM的作用是在关系型数据库和业务实体对象之间作一个映射,这样我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。

如何选择合适自己的ORM框架?

对于我们而言选择ORM框架的目的其实都是为了让我们的程序更好的操作数据库,提高开发编程效率和程序的维护拓展性。因此我们在为自己负责的项目选择合适的ORM框架的时候需要从项目的业务场景出发,选择最适合自己团队的ORM框架(注意没有完美的框架,适合团队的才是最好的)。以下是一些比较好用且优秀的.NET-ORM框架汇总,排名不分先后可供大家参考学习(假如您有更好的.NET相关ORM推荐请在文末留言,谢谢)。

EF/EF Core

Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技术,EF Core 是适用于 .NET 的现代对象数据库映射器。它支持 LINQ 查询、更改跟踪、更新和架构迁移。EF Core 通过提供程序插件 API 与 SQL Server、Azure SQL 数据库、SQLite、Azure Cosmos DB、MySQL、PostgreSQL 和其他数据库一起使用。(微软官方出品)。

EF Core 可用作对象关系映射程序 (O/RM),这可以实现以下两点:

  • 使 .NET 开发人员能够使用 .NET 对象处理数据库。
  • 无需再像通常那样编写大部分数据访问代码。

官方文档教程:https://docs.microsoft.com/zh-cn/ef/

GitHub地址:https://github.com/dotnet/efcore

以下是EF/EF Core相关拓展程序包:

Dapper

Dapper是一个简单的.NET对象映射器,在速度方面具有”King of Micro ORM”的头衔,几乎与使用原始的ADO.NET数据读取器一样快。ORM是一个对象关系映射器,它负责数据库和编程语言之间的映射。Dapper通过扩展IDbConnection提供一些有用的扩展方法去查询您的数据库。
主要特点:高性能、易排查、易运维、灵活可控。

以下是Dapper相关拓展程序包:

  • Dapper-Extensions – Dapper Extensions 是一个小型ORM库,通过为您的 POCO 添加基本的 CRUD 操作(获取、插入、更新、删除)来补充Dapper。对于更高级的查询场景,Dapper Extensions 提供了一个谓词系统。这个库的目标是通过不需要任何属性或基类继承来保持你的 POCO 纯净。
  • Dapper-FluentMap – Dapper的扩展。
  • Dommel – Dapper的CRUD操作。
  • MicroOrm.Dapper.Repositories – Dapper的CRUD操作。

FreeSql

FreeSql 是一款功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。
主要特点:
  • 支持 CodeFirst 模式,即便使用 Access 数据库也支持数据迁移;
  • 支持 DbFirst 模式,支持从数据库导入实体类,或使用实体类生成工具生成实体类;
  • 支持 深入的类型映射,比如 PgSql 的数组类型等;
  • 支持 丰富的表达式函数,以及灵活的自定义解析;
  • 支持 导航属性一对多、多对多贪婪加载,以及延时加载;
  • 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;
  • 支持 MySql/SQLServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/Access 等数据库;

官方文档地址:http://www.freesql.net/

GitHub地址:https://github.com/dotnetcore/FreeSql

SqlSugar

SqlSugar是一款老牌 .NET 开源ORM框架,支持.NET CORE 和 MySql、SQLServer、Sqlite、Oracle 、 postgresql 、达梦、人大金仓 数据库,具有EF NH的功能,比EF更人性化的语法,支持真实的批量操作,另外还有媲美Dapper的性能。

主要特点:简单易用、功能齐全、高性能、轻量级、服务齐全、支持全自动分表组件,SAAS分库,大数据处理的ORM。
官网地址:http://www.donet5.com

Chloe

Chloe 是一个轻量级的对象/关系映射(ORM)库。查询接口类似于 LINQ。您可以使用 Chloe.ORM 通过 lambda 查询 LINQ 之类的数据并执行任何操作(加入查询 | 组查询 | 聚合查询 | 插入 | 批量更新 | 批量删除)。

文档地址:https ://github.com/shuxinqin/Chloe/wiki

GitHub地址:https://github.com/shuxinqin/Chloe

nhibernate-core

 NHibernate 是一个成熟的开源对象关系映射器,适用于 .NET 框架。它被积极开发,功能齐全,并在数千个成功的项目中使用。

NHibernate社区网站 – https://nhibernate.info

GitHub地址:https://github.com/nhibernate/nhibernate-core

SmartSql

SmartSql = C# 中的 MyBatis + .NET Core+ 缓存(内存 | Redis)+ R/W 拆分 + PropertyChangedTrack +动态存储库 + InvokeSync + 诊断。

SmartSql 借鉴了 MyBatis 的思想,使用 XML 来管理 SQL ,并且提供了若干个筛选器标签来消除代码层面的各种 if/else 的判断分支。SmartSql将管理你的 SQL ,并且通过筛选标签来维护本来你在代码层面的各种条件判断,使你的代码更加优美。

主要特点:简洁、高效、高性能、扩展性、监控、渐进式开发!

PetaPoco

PetaPoco 是一个用于 .NET(4、4.5+、net standard 2.0+)和 Mono 的微型、快速、易于使用的 micro-ORM。由于 PetaPoco 所代表的简单性和易用性,它受到许多人的喜爱。PetaPoco 是首选的微 ORM,也是任何体面的开发人员工具包中必不可少的实用程序。
主要特点:
  • Dapper一样,它很快,因为它使用动态方法生成 (MSIL) 将列值分配给属性。
  • Massive一样,它现在也支持动态 Expandos。
  • ActiveRecord一样,它支持对象和数据库表之间的密切关系。
  • SubSonic一样,它支持使用 T4 模板生成 poco 类(仅限 V5)。
  • Massive一样,它以单个文件的形式提供,您可以轻松地将其添加到任何项目或编译(仅限 V5)。

linq2db

LINQ to DB 是最快的LINQ数据库访问库,在POCO对象和数据库之间提供了一个简单、轻量、快速且类型安全的层。
在架构上,它比 Dapper、Massive 或 PetaPoco 等微 ORM 高出一步,因为您使用 LINQ 表达式,而不是魔术字符串,同时在代码和数据库之间维护一个薄抽象层。您的查询由 C# 编译器检查并允许轻松重构。
但是,它不像 LINQ to SQL 或实体框架那么重。没有更改跟踪,因此您必须自己进行管理,但从积极的方面来说,您可以获得更多控制权并更快地访问您的数据。

文档地址:https://linq2db.github.io/ 

GitHub地址:https://github.com/linq2db/linq2db

RepoDb

 RepoDB是一个开源的.NET ORM库,它弥合了微ORM和完整ORM之间的差距。它帮助您简化在开发过程中何时使用基本操作和高级操作的切换。

主要特点:

  • 易于使用- 这些操作都作为您的 IDbConnection 对象的扩展方法实现。只要您的连接处于打开状态,就可以对您的数据库调用任何操作。
  • 高性能- 它缓存已经生成的编译表达式以供将来重用和执行。它了解您的架构以创建最佳的编译表达式 AOT。
  • 内存高效- 它提取并缓存您的对象属性、执行上下文、对象映射和 SQL 语句。它在整个转换和执行过程中重用它们。
  • 动态和混合- 它提供了成熟 ORM 的一些高级功能。它极大地帮助开发人员在开发过程中进行上下文切换时简化体验。
  • 开源软件——它是一个开源软件,并且永远是免费的。它旨在进一步改进 .NET 数据访问体验和解决方案,以及社区的集体思想。
  • 高质量- 它是一个高质量的微型 ORM,由 10K+ 真实单元和集成测试支持。它经过高度测试,并被生产环境中运行的各种关键系统使用。

GitHub地址:https://github.com/mikependon/RepoDB

ServiceStack.OrmLite

 OrmLite是一个快速、简单、类型化的.NET ORM,OrmLite 的目标是提供一个方便、DRY、无配置、与 RDBMS 无关的类型包装器,该包装器与 SQL 保持高度亲和性,公开直观的 API,生成可预测的 SQL 并干净地映射到断开连接和数据传输对象 (DTO) 友好、普通的旧C# 对象 (POCO)。这种方法更容易推理您的数据访问,从而清楚地知道什么 SQL 在什么时间执行,同时减轻意外行为、隐式 N+1 查询和重对象关系映射器 (ORM) 中普遍存在的泄漏数据访问。

文档地址:https://docs.servicestack.net/ormlite/

GitHub地址:https://github.com/ServiceStack/ServiceStack.OrmLite

SQLite-net

 简单、强大、跨平台的 SQLite 客户端和 .NET 的 ORM。

主要特点:

  • 非常容易与现有项目集成并在所有 .NET 平台上运行。

  • SQLite 上的瘦包装器,快速高效。(这个库不应该是您查询的性能瓶颈。)

  • 用于安全执行 CRUD 操作和查询(使用参数)并以强类型方式检索这些查询结果的非常简单的方法。

  • 与您的数据模型一起工作,而不会强迫您更改您的类。(包含一个小的反射驱动 ORM 层。)

GitHub地址:https://github.com/praeclarum/sqlite-net

Insight.Database

Insight.Database是一个用于 .NET 的快速、轻量级的 micro-orm。

GitHub地址:https://github.com/jonwagner/Insight.Database

cyqdata

 cyq.data是一个高性能且功能最强大的orm(支持.NET Core),支持Txt、Xml、Access、Sqlite、Mssql、Mysql、Oracle、Sybase、Postgres、DB2、Redis、MemCache。

GitHub地址:https://github.com/cyq1162/cyqdata

TinyORM

TinyORM是一个简单、快速且安全的微型.NET ORM。

Wiki地址:https://github.com/sdrapkin/SecurityDriven.TinyORM/wiki

GitHub地址:https://github.com/sdrapkin/SecurityDriven.TinyORM

querybuilder

SQL 查询构建器,用 c# 编写,帮助您轻松构建复杂的查询,支持 SqlServer、MySql、PostgreSql、Oracle、Sqlite 和 Firebird。

官网地址:https://sqlkata.com/

GitHub地址:https://github.com/sqlkata/querybuilder

一款利用人工智能将自然语言查询转换为 SQL 代码的互译工具 - SQL Translator - 追逐时光者 - 博客园

mikel阅读(403)

来源: 一款利用人工智能将自然语言查询转换为 SQL 代码的互译工具 – SQL Translator – 追逐时光者 – 博客园

前言

对于后端程序员来说,编写SQL代码是日常工作中不可或缺的一部分。然而,随着数据复杂性的增加,如何高效、准确地编写SQL查询成为了新的挑战。幸运的是,SQL Translator的出现为后端程序员提供了一个强大的工具,将自然语言查询转换为精确的SQL代码,极大地提高了工作效率。

SQL Translator介绍

SQL Translator是一款利用人工智能将自然语言查询转换为 SQL 代码的互译工具,它的主要目的是简化SQL查询的编写过程,让非专业的SQL用户、数据库管理员、数据分析师等能够以自然语言的形式输入查询,然后快速获得对应的SQL代码。此外,用户还可以将已有的SQL代码输入,获取易于理解的自然语言翻译,从而更直观地理解SQL代码的含义。

此项目基于MIT License协议开源、100%免费。

工具特性

  • 支持暗黑模式。
  • 支持大小写切换。
  • 支持复制到剪贴板。
  • 支持SQL语法高亮显示。
  • 支持查看查询历史。

本地项目部署

克隆项目到本地

git clone https://github.com/whoiskatrin/sql-translator.git

安装所需的软件包

cd sql-translator
npm install

生成应用程序

npm run build

在.env文件中输入您的OPENAI API的密钥

OPENAI_API_KEY=$YOUR_API_KEY

启动开发服务器

npm start

在线效果演示

创建一个用户表

插入用户表数据

查询用户表数据

SQL语句翻译

查看查询历史记录

程序员常用的工具软件

该工具已收录到程序员常用的工具软件栏目中,欢迎关注该栏目发现更多优秀实用的开发工具!

一款.NET开源的i茅台自动预约(抢茅台)小助手

mikel阅读(715)

来源: 一款.NET开源的i茅台自动预约(抢茅台)小助手

今天大姚给大家分享一款.NET开源、基于WPF实现的i茅台APP接口自动化每日自动预约(抢茅台)小助手:HyggeImaotai。

图片

项目介绍

该项目通过接口自动化模拟i茅台APP实现每日自动预约茅台酒的功能,软件会在指定时间开始对管理的用户进行批量预约。

项目功能

  • 用户管理
  • 预约项目
  • 店铺管理
  • 日志管理

项目源代码

图片

工具下载

  • https://github.com/lisongkun/HyggeImaotai/releases
图片

源代码运行

图片
图片

功能截图

图片
图片
图片
图片
图片
图片

项目源码地址

更多项目实用功能和特性欢迎前往项目开源地址查看👀,别忘了给项目一个Star支持💖。

https://github.com/lisongkun/HyggeImaotai

优秀项目和框架精选

该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。

https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md

无业游民写的最后一个.net有关项目框架 - 星仔007 - 博客园

mikel阅读(417)

来源: 无业游民写的最后一个.net有关项目框架 – 星仔007 – 博客园

理想很丰满,现实往往很残酷。

一种按照ddd的方式,根据业务来把自己需要的模块一个一个写出来,再按照模块把需要的接口一个一个的写出来,堆砌一些中间件,以及解耦的command,handler等等

,一个项目就这么成型了。上面的项目有一个非常清晰的特点,就是按需开发,不需要去可以定义业务相关的公共的模块,有就有没就没。这项目看起来没有什么公共框架,就是一个项目。当然这样效率性能也是最高的,不需要过多的包装一层又一层的公共代码。

有关示例如下,不做过多的赘述:

liuzhixin405/netcore-micro (github.com)

一种业务非常大,开发人员只需要写业务实现,这就需要一个公共框架,提供公共的可复制模块让业务人员写业务代码。

下面以为简洁的方式呈现这种开发模式,项目层级如下:

三个模块分别是业务模块,主机,基础模块。业务模块Business通过dll形式提供给host来完成注册和发布。

主机host可以存放公共的基础模块,例如注册、登录、认证等,这里省略。

业务模块存放业务代码,包括提供接口。

流程如下:request => 业务模块controller => business => service=> repository

整个项目接口不变,实现可各异。

在仓储层定义几个公共的方法,

复制代码
 public interface IRepository<TEntity,TID> where TEntity : IEntity<TID>
 {
     Task<ApiResult> AddAsync(TEntity entity);
     Task<ApiResult> UpdateAsync(TEntity entity);

     Task<ApiResult> DeleteAsync(Expression<Func<TEntity, bool>> filter);
     Task<ApiResult> DeleteAsync(TID id);
     // 通用分页查询
     Task<PagedResult<TEntity>> GetPagedAsync(PagingParameters<TEntity> pagingParameters);

     // 其他常用操作
     Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> filter);

 }
复制代码

服务层也是同样的方法

复制代码
 [Intercept("business-service log")]
 public interface IService
 {
    Task<ApiResult> AddAsync(IRequestDto requestDto);
    Task<ApiResult> UpdateAsync(IRequestDto requestDto);
    Task<ApiResult> DeleteAsyncc(IRequestDto requestDto);
    Task<ApiResult> GetPagedAsyncc(IRequestDto requestDto) ;
    Task<ApiResult> FindAsyncc(IRequestDto requestDto);
 }
复制代码

 

依赖注入还是老一套,实现它就行。

复制代码
 public interface IModule
 {
     void ConfigureService(IServiceCollection services, IConfiguration configuration = null);
     void Configure(IApplicationBuilder app, IWebHostEnvironment env = null);
 }

 public abstract class ModuleBase : IModule
 {
     public virtual void ConfigureService(IServiceCollection services, IConfiguration configuration = null)
     {
     }

     public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env = null)
     {
     }
 }
复制代码

在主机通过扫描assembly来注册服务

复制代码
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Project.Base.Reflect;
using System.Reflection;
using Project.Base.ProjExtension;
using Project.Base.Common;
using Project.Base.DependencyInjection;
using Project.Base.Module;
namespace Project.Host
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);
            builder.Configuration.AddJsonFile("appsettings.Modules.json", optional: false, reloadOnChange: true);
            //IModule注入 ,然后扫描调用ConfigureService,Business注入需要的服务入口
            builder.Services.InitModule(builder.Configuration);
            var sp = builder.Services.BuildServiceProvider();
            var moduleInitializers = sp.GetServices<IModule>();
            foreach (var moduleInitializer in moduleInitializers)
            {
                moduleInitializer.ConfigureService(builder.Services, builder.Configuration);
            }
            // Add services to the container.
            var assemblys = GolbalConfiguration.Modules.Select(x => x.Assembly).ToList();


            var mvcBuilder=builder.Services.AddControllers().ConfigureApplicationPartManager(apm => {

                var folder = Path.Combine(Directory.GetCurrentDirectory(), "bus_lib");
                var serviceList = (builder.Configuration.GetSection("ServiceList").Get<string[]>()) ?? new string[] { "ADM" };//默认加载基础服务
                string[] serviceFiles = Directory.GetFiles(folder, "*.Api.dll").Where(x =>
                    serviceList.Any(y => x.Contains(y))
                ).ToArray();

                foreach (var file in serviceFiles)
                {
                    if (File.Exists(file))
                    {
                        var assembly = Assembly.LoadFrom(file);
                        var controllerAssemblyPart = new AssemblyPart(assembly);
                        apm.ApplicationParts.Add(controllerAssemblyPart);
                    }
                }
            });
            foreach (var assembly in assemblys)
            {
                // 扫描并注册其他程序集中的控制器
                mvcBuilder.AddApplicationPart(assembly);
                // 扫描并注册其他程序集中的服务   针对特性注入
                builder.Services.ReisterServiceFromAssembly(assembly);
            } 

            
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();
            builder.Services.AddBusinessServices();

            var app = builder.Build();
            ServiceLocator.Instance = app.Services;

            //imodule 的Configure调用,business可以实现中间件等操作
            foreach (var moduleInitializer in moduleInitializers)
            {
                moduleInitializer.Configure(app, app.Environment);
            }
            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();


            app.MapControllers();

            app.Run();
        }
    }
}
复制代码

 

业务需求注入代码如下:

复制代码
using ADM001_User.Model;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson.Serialization;
using MongoDB.Bson;
using MongoDB.Driver;
using Project.Base.IRepository;
using Project.Base.Module;
using Project.Base.Reflect;
using Project.Base.Repository;
using Project.Base.Services;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ADM001_User.Business.Settings;
using Project.Base.Model;

namespace ADM001_User.Business
{
    public class UserModule : ModuleBase
    {

        public override void ConfigureService(IServiceCollection services, IConfiguration configuration = null)
        {
            services.AddDbContext<UserDbContext>(options =>
       options.UseInMemoryDatabase("InMemoryDb"));

            services.AddScoped<IRepository<User, int>, GenericRepository<User, int, UserDbContext>>();
            services.AddTransient<IService, UserService>();

            AddMongo(services);
            AddMongoRepository<User, int>(services, "users");

        }


        private static IServiceCollection AddMongo(IServiceCollection services)
        {
            BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
            BsonSerializer.RegisterSerializer(new DateTimeOffsetSerializer(BsonType.String));
            services.AddSingleton(serviceProvider =>
            {
                var configuration = serviceProvider.GetService<IConfiguration>();
                var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
                var mongoDbSettings = configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>();
                var mongoClient = new MongoClient(mongoDbSettings.ConenctionString);
                return mongoClient.GetDatabase(serviceSettings.ServiceName);
            });
            return services;
        }
        private static IServiceCollection AddMongoRepository<T, TID>(IServiceCollection services, string collectionName) where T : IEntity<TID>
        {
            services.AddSingleton<IRepository<User, int>>(serviceProvider =>
            {
                var db = serviceProvider.GetService<IMongoDatabase>();
                return new MongoRepository<User, int>(db, "collectionname");
            });
            return services;
        }
    }
}
复制代码

 

在business层加了aop,通过proxy的方式

复制代码
using Castle.DynamicProxy;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Project.Base.Reflect
{
    public static class ServiceExtension
    {
        private static readonly ProxyGenerator _generator = new ProxyGenerator();
        public static IServiceCollection AddBusinessServices(this IServiceCollection services)
        {
            var folder = Path.Combine(Directory.GetCurrentDirectory(), "bus_lib");

            var dllFiles = Directory.GetFiles(folder, "*.Business.dll");

            var assemblies = dllFiles.Select(Assembly.LoadFrom).ToArray();

            var businessTypes = assemblies.SelectMany(a => a.GetTypes().Where(t => t.IsClass&&!t.IsAbstract)).Where(type => type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IBusiness<>))).ToList();
            CastleInterceptor castleInterceptor = new CastleInterceptor();

            foreach (var type in businessTypes)
            {
                var interfaceType = type.GetInterfaces().First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IBusiness<>));
                services.AddTransient(interfaceType, provider =>
                {
                    var target = ActivatorUtilities.CreateInstance(provider, type);
                    return _generator.CreateInterfaceProxyWithTarget(interfaceType, target, castleInterceptor);
                });
            }

            return services;
        }
    }
}
复制代码

在你需要的每个方法前加上特性就可以了

复制代码
using Project.Base.Model;
using Project.Base.ProjAttribute;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ADM001_User.Business
{
    /// <summary>
    /// 有需要就实现前后动作
    /// </summary>
    public class AddAop: BaseAopAttribute
    {
        public override Task After(BusinessAopContext aopContext)
        {
            return Task.CompletedTask;
        }

        public override Task Before(BusinessAopContext aopContext)
        {
            return Task.CompletedTask;
        }
    }
}
复制代码

 

再控制器层加了个公共的,不管是controller拦截还是公共的部分都可以写到这里

复制代码
 [Route("api/[controller]/[action]")]
 [ApiController]
 public class InitController<TModel>:ControllerBase
 {
     protected readonly ILogger<InitController<TModel>> _logger;
      public InitController(ILogger<InitController<TModel>> logger)
     {
         _logger = logger;

     }
   
 }
复制代码

 

该框架主打就是一个简陋,像日志,缓存 ,消息中间件都可以提前约定好公共接口,service层接口调用,business层注入需要的实现。按照接口和实现分离的方式该项目还需要调整下目录

地址如下:

liuzhixin405/single-arch (github.com)

C#/.NET/.NET Core优秀项目和框架2024年6月简报 - 追逐时光者 - 博客园

mikel阅读(471)

来源: C#/.NET/.NET Core优秀项目和框架2024年6月简报 – 追逐时光者 – 博客园

前言

公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。

简报GitHub开源地址:https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectMonthly.md

优秀项目和框架精选:https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md

CsvHelper

ModernWpf

HyggeImaotai

WatchDog

Dorisoy.Pan

  • 项目简介: Dorisoy.Pan是一款基于.NET8开源(MIT License)、免费、跨平台文档管理系统,使用MS SQL 2012 / MySQL8.0(或更高版本)后端数据库,您可以在 Windows、Linux 或 Mac 上运行它,项目中的所有方法都是异步的,支持令牌基身份验证,项目体系结构遵循著名的软件模式和最佳安全实践。源代码是完全可定制的,热插拔且清晰的体系结构,使开发定制功能和遵循任何业务需求变得容易。
  • 项目源码地址: https://github.com/dorisoy/Dorisoy.Pan
  • 公众号详细介绍: https://mp.weixin.qq.com/s/_kAZdnJarAexDEA_d_Ldng

OxyPlot

Jvedio

  • 项目简介: Jvedio是.NET开源、功能强大的本地视频管理软件,支持扫描本地视频并导入软件,建立视频库,提取出视频的唯一识别码,自动分类视频,添加标签管理视频,使用人工智能识别演员,支持翻译信息,基于FFmpeg截取视频图片,Window桌面端流畅美观的应用软件。
  • 项目源码地址: https://github.com/hitchao/Jvedio
  • 公众号详细介绍: https://mp.weixin.qq.com/s/JwJFkZxrJVEqgXVxonT-1g

胡桃工具箱

  • 项目简介: 胡桃工具箱是一款.NET开源(MIT License)、免费、实用的多功能原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新功能相结合,它提供了一套完整且实用的工具集,且无需依赖任何移动设备。它不对游戏客户端进行任何破坏性修改以确保工具箱的安全性。
  • 项目源码地址: https://github.com/DGP-Studio/Snap.Hutao
  • 公众号详细介绍: https://mp.weixin.qq.com/s/5-Dybat5IagTk6XxaIHZug

TheAlgorithms/C-Sharp

  • 项目简介: 一个C#实现的各种算法集合,这些算法涵盖了计算机科学、数学和统计学、数据科学、机器学习、工程等多个领域。这些实现及其相关文档旨在为教育工作者和学生提供学习资源。因此,可能会找到针对同一目标使用不同算法策略和优化的多种实现。
  • 项目源码地址: https://github.com/TheAlgorithms/C-Sharp
  • 公众号详细介绍: https://mp.weixin.qq.com/s/KRl7Zoe3Co42zbWGJitRbg

FaceRecognitionDotNet

SeeSharpSnake

DotNetGuide技术社区交流群

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

关于C#winform端Settings.settings的见解_winform settings-CSDN博客

mikel阅读(473)

来源: 关于C#winform端Settings.settings的见解_winform settings-CSDN博客

1.说明
由于最近工作比较忙很长时间没有写文章了,最近在项目中使用Settings.settings时遇见了一些问题,故作记录,希望各位大神指点。
2.Settings.settings说明
Settings.settings结构如上图,在Settings.settings中添加节点时Settings.Designer.cs自动生成该节点的属性,App.config自动生成节点信息。
3.使用方式介绍
private void button1_Click(object sender, EventArgs e)
{
    RefreshLabel();
}
private void RefreshLabel()
{
    label1.Text = “UserSave:” + Settings.Default.UserSave;
    label2.Text = “User:” + Settings.Default.User;
    label3.Text = “Application:” + Settings.Default.Application;
    Settings.Default.UserSave = “2”;
    Settings.Default.User = “2”;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    Settings.Default.Save();
}
4.属性介绍
名称:自定义节点名称,使用 Settings.Default.名称 获取或修改该节点的值
类型:设置节点的类型,获取或修改该节点的值必须使用相同的数据类型;
范围:包含用户和应用程序(后续单独说明);
值:可设置初始值;
5.属性-范围
范围包含了用户和应用程序
(1)用户节点
1.允许修改节点值;
2.修改节点的值仅在程序本次运行时生效,下次运行需要使用程序的默认值则不能调用
Settings.Default.Save();
3.修改节点的值需要在程序下次运行使用必须调用
Settings.Default.Save();
Settings.Default.Save(); 介绍
1.如果节点设置为用户,并且调用了Save()方法,会在C:\Users\Administrator\AppData\Local\项目名称\对应版本\1.0.0.0\user.config的文件中存储修改后的节点的值;
项目名称:当前运行的项目的名称
对应版本:共四种,包含:开发环境中启动的Debug、Release以及在Debug或Release中直接执行程序的.exe(可执行文件);
2.若未调用Save()方法,user.config不会生成或修改;
3.调用Save()方法时,仅保存调用前修改过所有节点的值,调用后修改的值不会改变,修改后节点在exe.config、vshost.exe.config不会显示修改后的值
4.建议在程序退出时,调用Save()方法;若仅需要节点在本次调用修改有效,则不能调用Save(),防止程序出现不可估计的错误;
5.若不仅包含了启动本次修改有效节点,还包含了修改后下次启动仍有效节点,建议在Settings.settings中添加用户节点,但是不能在程序调用Save方法,再配合使用Configuration使用。
(2)应用程序节点
1.节点的值不允许在程序中修改;
2.不会在C:\Users\Administrator\AppData\Local\项目名称\对应版本\1.0.0.0\user.config生成节点;
3.在app.config、exe.config、vshost.exe.config中生成节点
6.Configuration说明
在app.config添加节点,会在exe.config、vshost.exe.config中生成节点;
#region ConfigurationManager使用说明
// 想调用ConfigurationManager必须要先在工程里添加system.configuration程序集的引用
// 在引用点击右键选择添加引用,搜索Config就会找到
#endregion
using System;
using System.Configuration;
using System.Xml;
/******************************************************
* 模块作者: zheng
* 创建时间: 2021/6/27 20:18:15
* 功能描述: 1.用于对Winform端对EXE.config或操作vshost.exe.config文件的读写;
*           2.修改构造函数中初始化对象改变操作对象。
* 使用说明: 1.右击引用,添加System.Configuration;
*           2.使用该类时需要修改命名空间;
*           3.使用前建议向app.config添加节点,节点示例:
*           <appSettings file=””>
*             <add key=”光源连接端口” value=”com1″ />
*             <add key=”COM1″ value=”COM1,9600,8,None,1,已启用” />
*           </appSettings>
*******************************************************/
namespace MicroscaleMeasure.Utils
{
    class AppConfigUtil
    {
        /// <summary>
        /// 管理配置文件对象
        /// </summary>
        private static readonly Configuration MConfig;
        static AppConfigUtil()
        {
            //1.操作vshost.exe.config
            //MConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            //2.操作exe.config
            var file = System.Windows.Forms.Application.ExecutablePath;
            MConfig = ConfigurationManager.OpenExeConfiguration(file);
        }
        /// <summary>
        /// 获取AppSettings中某一节点值
        /// </summary>
        /// <param name=”key”>节点名称</param>
        public static string GetConfigValue(string key)
        {
            if (MConfig.AppSettings.Settings[key] != null)
                return MConfig.AppSettings.Settings[key].Value;
            else
                return string.Empty;
        }
        /// <summary>
        /// 修改配置文件,若节点不存在则添加节点
        /// </summary>
        /// <param name=”aKey”>需要修改的节点名称</param>
        /// <param name=”aValue”>需要修改的节点的值</param>
        public static void UpdateAppSettings(string aKey, string aValue)
        {
            if (MConfig.AppSettings.Settings[aKey] != null)
                MConfig.AppSettings.Settings[aKey].Value = aValue;// 修改
            else
            {
                var ass = (AppSettingsSection)MConfig.GetSection(“appSettings”);
                ass.Settings.Add(aKey, aValue);// 添加
            }
            MConfig.Save(ConfigurationSaveMode.Modified);// 保存修改
            ConfigurationManager.RefreshSection(“appSettings”);// 强制重新载入配置文件的连接配置
        }
    }
}
————————————————
                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_47492910/article/details/121810100

我用OpenGlass做了一个AI眼镜【上篇】 | Rocket Lu

mikel阅读(1875)

我用OpenGlass做了一个AI眼镜【上篇】

来源: 我用OpenGlass做了一个AI眼镜【上篇】 | Rocket Lu

在AI硬件领域,随着大型语言模型(LLM)的价格战愈演愈烈,文心、豆包都已经进入卷价格阶段,进入“厘时代”。5月,GPT-4o和Gemini家族的发布,OpenAI和Google也在将创新焦点转向多模态大型模型。
AI硬件的想象空间愈发广阔,逐渐从单纯的AI玩具逐步转向消费级AI电子设备。自去年以来,消费电子市场上涌现出几款颇具代表性的AI新品,其中包括智能眼镜Ray-Ban Meta、可穿戴投影设备Humane Ai Pin,以及在今年CES上亮相的掌上设备Rabbit R1。

消费级AI 硬件

01 Rabbit R1

在2024年CES展会上首次亮相的Rabbit R1,首批1万台迅速售罄,自推出以来销售额已突破1000万美元,显示出消费者对这款产品的极高接受度和需求。对于新一代AI硬件设备,市场充满了期待和想象。

02 Rewind(https://www.limitless.ai/

Rewind的外设主要是4月16日刚开放预售的Limitless Pendant,售价99美元,具备Wi-Fi和蓝牙功能,能够记录整日的对话和个人见解。它可以收集云端和现实世界中的数据,能够记录日常会议、即兴对话等,并通过配套的应用程序方便地回放。用户可以通过轻触吊坠来标记对话中的重要时刻,便于后续查找,并且可以随时与个性化AI进行互动,获取所需信息或帮助
notion image

03 AI PIN(https://humane.com/shop

notion image
AI PIN是初创公司Humane的首个产品,一款可以别在衣服上的AI设备,于在当地时间11月9日正式发布。Humane成立于2018年,由前苹果软件工程总监Bethany Bongiorno和前苹果设计师Imran Chaudhri 作为夫妻档共同创办。AI Pin在去年11月10日开始接受预定,今年4月11日开始发货,售价为699美元起,但每月还需额外支付24美元订阅费。

04 Meta Ray-Ban Glass(https://www.ray-ban.com/usa/ray-ban-meta-smart-glasses

notion image
Meta与雷朋(Ray-Ban)联名的第二代智能眼镜在2023年第四季度的发货量超30万副,远超Meta此前预期。Ray-Ban Meta发布于去年9月,当时它与Quest 3一同亮相,产品起售价299美元,与上一代保持一致,镜片可以定制,镜片起售价17美元起步。今年4月,Meta团队称已经提高眼镜的生产计划,并将为眼镜全面开放多模态AI能力。Meta AI是一个多模态人工智能,最早亮相于去年Meta Connect大会,当时Meta计划逐步将其引入到Facebook、Instagram、Quest 3以及Ray-Ban Meta等软硬件产品矩阵当中。对于Ray-Ban Meta而言,Meta AI于去年12月在美国地区启动了抢先体验,并于4月正式面向美国和加拿大用户推出。
根据测评来看,AI Pin在体验方面已经“翻车”,Rabbit R1被质疑与AI手机趋同,热度逐渐变淡。Ray-Ban Meta是目前相对较为成功的一个AI电子产品。但是我们可以看到整体AI设备的售价都是在100美元以上,还是偏贵。
5月13日,正好看到Nik Shevchenko分享了一个视频,展示他用20 美元制作了一个外设,挂在眼镜边上,就可以做一个AI智能眼镜,于是我准备复刻一个。
notion image

首先是准备工作

需要的硬件是一台电脑(我用的是MacPro M2芯片),一个芯片主板、一个电池、一个3D打印的外壳、一根质量好的TypeC数据线。
这些国内都能买到,需要购买清单的可以滴滴我(😄我找开发板老板,化缘了一个618粉丝专属福利,备注Rocket)
等硬件都拿到手后,可以开始软件工作了。

01 下载Arduino IDE

这个软件我在整合包里准备好了,大家可以直接回复“Glass”下载

02 设置ESP32S3主板程序

打开Terminal,输入下面代码,把OpenGlass项目代码下载到本地,你也可以手动下载。

shell

git clone https://github.com/BasedHardware/OpenGlass.git
Shell
然后打开找到OpenGlass文件夹里的 firmware folder 文件夹,并在 Arduino IDE 中打开 .ino 文件。
为ESP32S3 Sense主板设置 Arduino IDE:
notion image
先将 ESP32S3 板 添加到您的 Arduino IDE:

  • 菜单栏,选择“文件”>“首选项”(File > Preferences),然后在“其他 Boards Manager URL”(“Additional Boards Manager URLs” )填写这个链接: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  • 导航到“工具”>“开发板”>“开发板管理器…”(Tools > Board > Boards Manager),在搜索框中输入关键字 esp32 ,选择最新版本的 esp32 并安装它。我这两个都安了一下,但任意选一个就行。(esp32升级了,所以只下第二个的2.0.17版本就行,不要下两个了,也不要升级版本,不然都会报错!)
notion image
notion image
  • 选择您的主板和端口:
    • 在 Arduino IDE 顶部,选择开发板和端口。
    • 弹窗中搜索 xiao 并选择 XIAO_ESP32S3 。
notion image
notion image
  • “PSRAM:”设置为“PSRAM:”“OPI PSRAM”
在刷机之前,转到Arduino IDE中的“工具”下拉列表,并确保将“PSRAM:”设置为“PSRAM:”“OPI PSRAM”
notion image
官方的教程就到这了,但如果你这个时候进行编译的话,一定会发现哐哐报错。
因为还有一些依赖库没有安装。
我们还需要点击左边菜单的库,搜索并安装 ArduinoBLE
notion image
安装完后,基本就ok了,如果还有报错,可以看看是否还有依赖库没安上。
现在就可以,用一个type c数据线把板子和电脑连接,就可以进行烧录程序了。
  1. 点击 验证 按钮(对号图标),检查代码是否有错误。
  1. 点击 上传 按钮(箭头图标),将代码上传到XIAO ESP32S3开发板。

03 验证功能

  1. 打开Arduino IDE的 串口监视器,检查输出信息。
  1. 确保设备连接到蓝牙。
  1. 检查摄像头是否能够拍照,并通过蓝牙发送数据。
按照这些步骤进行操作,你应该能够成功地将固件上传到XIAO ESP32S3开发板,并实现摄像头和蓝牙的功能。
软件工作基本结束了,这个时候还有2个步骤需要完成。

04 完善硬件:XIAO ESP32S3开发板连接天线、摄像头、电池

天线的安装
在XIAO ESP32S3的正面左下角,巧妙地设计了一个独立的“WiFi/BT天线连接器”。为了捕获更清晰的WiFi和蓝牙信号,您需要从包装中取出附带的天线,并细心地将其安装至连接器上。
在安装天线时,您可能会发现直接用力按压并非易事,且可能对手指造成不适。这里有一个安装小窍门:首先,轻轻地将天线连接器的一侧嵌入到连接器块内,然后,从另一侧轻轻下压,您会发现天线便能顺滑地安装到位。
同样地,当需要拆卸天线时,也请避免使用蛮力直接拉扯。只需在一侧施力,轻轻地提起,天线便能轻松脱离。
notion image
安装扩展板(用于Sense)
XIAO ESP32S3 Sense,还包括一个扩展板。此扩展板具有1600*1200 OV2640摄像头传感器、板载SD卡插槽和数字麦克风。
通过使用XIAO ESP32S3 Sense安装扩展板,您可以使用扩展板上的功能。
安装扩展板非常简单,只需将扩展板上的连接器与XIAO ESP32S3上的B2B连接器对齐,用力按压并听到“咔嗒”一声,即可完成安装。
notion image
焊接电池
其实如果你不真的戴出门,其实可以不用接。这块需要焊接,没有焊接技能的人不推荐自己动手,容易把板子搞坏。焊接电池,电池负极焊接到开发板的负极,将正极焊接到开关上,然后再焊接回开发板的正极。这个部分我会在下篇里详细讲到。

05 启动照片的页面程序

烧录完主板,还需要设置一下 Groq 和OpenAI的API。
  1. 在位于 https://github.com/BasedHardware/OpenGlass/blob/main/sources/keys.ts keys.ts 的文件中添加 Groq 和 OpenAI 的 API 密钥。
  1. 对于 Ollama,从存储库中自行托管 https://github.com/ollama/ollama 的 REST API,并将 URL 添加到 keys.ts 文件中。
    1. 启动应用程序:

shell

npm start
Shell
如果使用 yarn 启动应用程序

shell

yarn start
Shell
启动成功,你在terminal能看到web页面地址,复制到浏览器可以打开。
notion image
目前这个阶段,我通过这个AI设备,实现的功能是可以每隔4秒自动拍照照片,并自动上传记录在本地电脑上。

0607更新-常见报错

好多小伙伴在最后启动这里遇到了问题,我再补充一下
如果在终端中收到“command not found: npm”的错误消息,这意味着你的系统中没有安装Node.js和npm,或者它们没有正确配置在你的系统路径中。以下是安装和配置Node.js和npm的步骤:

使用nvm(Node Version Manager)

    1. 安装nvm

shell

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
Shell
    1. 加载nvm(你可能需要将下面的命令添加到你的~/.zshrc~/.bashrc文件中):

shell

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Shell
    1. 重启终端或重新加载配置文件

shell

source ~/.zshrc  # 如果你使用的是zsh
# 或者
source ~/.bashrc # 如果你使用的是bash
Shell
    1. 安装最新版本的Node.js

shell

nvm install node
Shell
    1. 验证安装

shell

node -v
npm -
Shell

直接安装Node.js

  1. 下载并安装Node.js
      • 下载适用于你操作系统的LTS(长期支持)版本并进行安装。
    1. 验证安装

shell

node -v
npm -v
Shell

配置项目

在安装Node.js和npm后,进入你的项目目录并运行以下命令:
    1. 安装项目依赖

shell

npm instal
Shell
    1. 启动项目

shell

npm start
Shell
如果安装和配置都正确,你的项目应该会成功启动。如果你在安装或启动过程中遇到问题,请确保你已经按照上述步骤正确安装了Node.js和npm,并且在正确的目录中运行命令。

安装Expo

Expo,这是一个用于构建React Native应用的工具。需要先安装Expo CLI,然后才能启动你的项目
以下是安装和使用Expo的步骤:
1. 安装Expo CLI
  1. 打开终端。
    1. 运行以下命令来全局安装Expo CLI:

shell

npm install -g expo-cli
Shell
    1. 验证安装:

shell

expo --version
Shell
如果显示Expo CLI的版本号,说明安装成功。
2. 启动项目
    1. 确保你在项目目录中:

shell

cd /path/to/OpenGlass
Shell
    1. 安装项目依赖(如果还没有安装):

shell

npm install
Shell
    1. 运行项目:

shell

npm start
Shell
3. 安装过程可能遇到的问题
权限问题
如果你在安装Expo CLI时遇到权限问题,可以使用以下命令在前面添加sudo(macOS和Linux):

shell

sudo npm install -g expo-cli
Shell
然后输入你的系统密码。
4. 使用Expo开发
安装并启动Expo后,你可以在项目目录中运行以下命令来启动开发服务器:

shell

expo start
Shell
这将启动一个本地开发服务器,并打开一个浏览器窗口,显示一个二维码。你可以使用Expo Go应用扫描这个二维码,在你的移动设备上预览你的应用(目前手机端还没开发,需要自己做个App。
版本提示
如果你的Node.js版本较高(17+),你可能需要降级到一个兼容的版本。你可以使用nvm来管理和切换不同版本的Node.js。
查看当前的Node.js版本:

shell

node -v
Shell
安装一个兼容的版本(比如16 LTS):

shell

nvm install 16
nvm use 16
Shell
确认使用的版本:

shell

node -v
Shell
然后重新运行项目:

shell

npx expo start
Shell
如果你nvm没有安装,那先安装一个Homebrew(Mac),那么接下来你需要
以下是使用 Homebrew 安装 nvm 的步骤:
  1. 打开终端:首先,您需要打开您的终端应用程序。
    1. 安装 Homebrew(如果您尚未安装):

shell

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Shell
安装过程中可能会提示您输入密码,并且可能需要输入 sudo 来获取必要的权限。
    1. 使用 Homebrew 安装 nvm

shell

brew install nvm
Shell
    1. 验证安装:安装完成后,您可以通过运行以下命令来验证 nvm 是否已正确安装:

shell

nvm --version
Shell
    1. 重新加载您的 shell 配置文件或重新启动终端,以确保 nvm 可以被正确识别:

shell

brew shell-nvm
Shell
    1. 安装 Node.js 版本:使用 nvm 安装您需要的 Node.js 版本,例如安装版本 16:

shell

nvm install 16
Shell
    1. 设置默认 Node.js 版本(如果需要):

shell

nvm alias default 16
Shell

下篇预告

连接LLM大模型,实现照片描述、Ask Photo照片内容对话
增加记录语音功能
文件按时间戳存储
加上控制开关,整个漂亮的外壳
💡
对这个话题感兴趣的小伙伴,欢迎加我一起探索交流~ 专门建了一个【OpenGlass交流群】欢迎大家互相交流!
notion image
notion image

又火一个惊艳的开源项目,诞生了!

mikel阅读(577)

来源: 又火一个惊艳的开源项目,诞生了!

大家好,今天继续聊聊科技圈发生的那些事。

一、ToonCrafter

ToonCrafter 可以通过预训练的图像到视频扩散先验来插值两个卡通图像。通俗点说,就是给出起始帧,给出结束帧,ToonCrafter会帮你补全中间的部分,生成一段完整的视频图像。另外,它还有个功能,基于给出的草图,给草图中的内容上色。

图片
图片

ToonCrafter基于图像条件的扩散模型,通过丰富的运动先验来合成复杂的非线性运动和现象。主要包括三个关键的技术:

  • 卡通矫正学习:通过对预训练的生成模型进行微调,使其能够更好地理解动画的上下文,并生成与卡通风格匹配的内容。
  • 细节注入与传播解码:引入一个基于双参考的3D解码器,使用混合注意力残差学习机制,将有损的帧潜在变量转换回像素空间,并注入输入图像中的细节信息。
  • 基于草图的可控生成:ToonCrafter配备了一个帧独立的草图编码器,使用户能够通过草图输入来引导生成过程。

我们来看一个具体的例子:

图片

将这两张图作为起始帧和结束帧,让 ToolCrafter 进行补全。

图片

成功补全风中凌乱的发型,效果生动逼真,灵动飘逸,毫无违和感。

这个工具最优秀的特点是,生成出的gif图体积极小,给出的这些demo示例大多都只有几百KB的大小。同时,还能兼顾生成质量。

图片

项目已经开源,也已经有了 HuggingFace 的在线体验,感兴趣的小伙伴,可以体验看看。

在线体验地址:

https://huggingface.co/spaces/Doubiiu/tooncrafter

项目地址:

https://github.com/ToonCrafter/ToonCrafter

二、Stable-Diffusion-3-Medium

备受瞩目的Stable Diffusion 3,终于开源了!

图片

SD3 自从二月份发布以来,其优秀的性能就一直好评不断。而在几天前的6月12日,Stability AI 正式宣布开源 SD3!

据悉,本次开源的Stable Diffusion 3 Medium 包含20万亿个参数,代表了Stability AI目前的最高水准。在 HuggingFace 上已经可以下载到模型权重文件了。

话不多说,我们先来看看效果:

图片
An astronaut riding a green horse

SD3相比起前代,主要提升了生成图像的细节处理,图像的质量会很高。同时,模型的尺寸非常优秀,即使是在常见的消费级GPU上,也有非常卓越的性能。

顺提一句,SD3已经能支持8k生成了,不过整出来的文件过大,这里就不直接放效果图了。

不过目前也有消息称,SD3在人像生成方面可能会出现一些比较“惊悚”的现象,针对整个人体的生成,SD3似乎有些不着调,就像这样…

图片

或许是数据集的问题,SD3无法理解完整的人类图像,在生成此类图像的时候,就略显尴尬了。

不过,抛开这个问题不谈,SD3绝对是一款优秀的文本生成图像模型!无论是生成图像的精细程度,还是生成效率,都有很大的提升。感兴趣的小伙伴,可以自行体验一下。

在线体验地址:

https://huggingface.co/spaces/stabilityai/stable-diffusion-3-medium

三、consistent-character

今天咱们要说的第三个项目 consistent-character,是一个偏娱乐向的项目。

这个项目在 HuggingFace 上的介绍非常简单:Create images of a given character in different poses,也就是让图像上的角色以不同的姿势出现。当然,既然要提供prompt生成,常见的换衣服功能也是必不可少的。

所以,我们要第N次请出咱们的皮衣刀客了,每次不知道拿谁当输入素材的时候,总会找到老黄的…

图片

作为示例,咱们就用默认的prompt吧,换身衣服就可以了。

图片

这里一定要记得打开这个选项,让生成的图像能有随机的pose,注入项目的灵魂。

图片
图片

效果还不错!咱们的皮衣刀客瞬间斯文了一把,穿上了笔挺的西装,一副大佬样。可以看到,项目生成的图片给老黄换了几个不同的姿势,甚至是个“无死角”的帅哥呢。

那么,如果我们再换一个prompt,来点不一样的风格呢?

a man, Mohican hairstyle, rocker style undershirt.

男子,莫西干发型,摇滚风格打底衫

图片

画风突变!这感觉,令人有点无法言说。

这个项目目前还没有开源,这里给出 HuggingFace 的地址,可以放上自己想操作的照片,给出prompt,就可以试试这个奇妙的效果了。不过,如果照片分辨率太高,等待时间可能会比较长。感兴趣的小伙伴可以自行体验看看!

在线体验地址:

https://huggingface.co/spaces/fffiloni/consistent-character

好了,本期的内容就是这么多,我们下期再见!