项目地址: https://github.com/vicalloy/daily-portrait
最近蓄须,每天拍一张照片记录变化,为此衍生出的项目。
- 根据眼睛位置自动对齐照片,并自动生成视频( gif 和 avi )。
- 人脸检测使用 face-recognition 。
- 图片位置修正使用 opencv-python 。

项目地址: https://github.com/vicalloy/daily-portrait
最近蓄须,每天拍一张照片记录变化,为此衍生出的项目。
GFPGAN 是一个使用 AI 进行人脸修复的工具,即使对非常模糊的人脸也可起到不错的修复效果。Hugging Face 提供了AI应用Demo的快速部署。我 Fork 了一份 GFPGAN 的 Demo 并做了少量的调整以加强对图片的支持。
在线体验地址 https://huggingface.co/spaces/vicalloy/GFPGAN
AI技术在图片生成领域有了不错的进展,现在已经可以通过文字生成质量不错的图片了。之前就一直想尝试用AI人脸修复将画中的人脸修复成照片,只是迫于拖延症一直未能真正动手。这些天试了一下,发现这个想法切实可行,就是修复出的效果算不上出色。
樱木花道
唐太宗李世民
乾隆
韩熙载
宋太祖赵匡胤
前些时间心血来潮想弄个ARM单板做个微型服务器。没想到今年树莓派涨价太狠,原本¥400点4b直奔¥1000去了。刚好看到Orange pi5要发布了,据说性能提升巨大,价格¥500起。本还有些犹豫,想到树莓派都成理财产品了,于是预购享折扣。
Orange pi5
采用的是瑞芯微的 RK3588S
根据测试性能介于骁龙845/855之间。在华为推出后,这已是最强的国产ARM芯片了,比树莓派4b要强出不少。该芯片集成了 6TOPS
算力的NPU,不过瑞芯微提供的SDK最新只支持到Ubuntu20.04,因此我没有实际测试过。
Orange pi5
提供了一个 M.2 接口,不过遗憾的是没有板载 Wi-Fi ,因此只能SSD,无线网卡2选一。
由于是新出的板子,还没有官方/第三方外壳(注:现在第三方外壳已经出来了),自己用硬纸板/塑料片/尼龙立柱做了个简单的外壳。偶尔做个手工,收获满满的成就感。
初步构想是作为家庭里的微型服务器使用,跑一些不需要实时性的“高负载”的任务(已有台云主机,大多服务可以跑在云主机上)。这些天把机器的基础设施搭建了一下,更具体的用途再说了(大概率吃灰)。
为简化管理,能用 Docker 部署等服务尽量用 Docker 部署。跑的 Python 脚本用 Pipenv 创建虚拟环境。
目前部署的服务有
拿到板子后做的开箱视频: https://www.bilibili.com/video/BV198411G7oy/
项目地址: https://github.com/vicalloy/outline-docker-compose
前一段想部署一个 Wiki ,看了一圈被 Outline 的颜值吸引。Outline 支持部署到自己服务器,只是自部署的体验真的不太好。Outline 部署主要就下面几个问题。
网上已用基于 docker-compose 的部署方案主要有两个:
出于自己部署的需要,参考 outline-wiki-docker-compose
的实现,新开了 Outline 的部署项目。
config.sh
一个配置文件,其他配置文件由脚本生成。项目地址:https://github.com/vicalloy/oidc-server/
多很多想自己部署 Outline 的人来说,没有本地的认证系统是一个非常头痛的问题。该Issue Local Authentication #1881 的评论数是 Outline 未关闭 Issue 中最多的。我也一度被该问题劝退。
可能 Outline 主推的还是 Cloud 版,虽然内建认证对自部署影响很大,官方依旧没有给出明确的支持方案。注:不少服务是提供OIDC认证的,如果你同时使用Gitlab,你可以使用Gitlab做OIDC认证服务器。
我最初的想法部署一个做简单的ODIC认证服务器给 Outline。出于节约内存的考虑,这个服务最好是Go或是Rust编写。找了一圈未发现合适的应用,于是回到了自己最熟悉的 Django 上。
OIDC Server 主体代码来源于 django-oidc-provider 的 example 。甚至可以说这个项目就是将 example 做了个打包。依托于 Django 优秀的插件机制和 Admin 模块,在几乎不用写代码的情况下就可以得到一个还过得去的 OIDC Server。当然缺点是内存占用量有点大,这个服务需要用掉大概100M的内存。
注:ODIC Server
docker镜像使用 Github Action
进行构建。不得不说 Github Action
的体验真的非常棒。
之前因为嫌备案麻烦,一直用的国外的主机。只是网站的访问速度一言难尽,毫无体验可言。
近期腾讯云做活动,1G内存3年只要¥150,简直和不要钱一样。禁不住诱惑上车了。
由于有了2G的“大内存”(之前只有1G内存),搬家后所有的服务都改用Docker部署。
目前服务器上跑的服务有:
proxy_set_header X-Forwarded-Proto $scheme;
解决问题。注:可以在docker-compose.ym
中将networks
设置为external
实现不同docker-compose
之间的容器互联。由于我使用nginx
作为网关,因此所有服务都使用nginx
的network
。
version: "3"
services:
filebrowser:
image: filebrowser/filebrowser:latest
restart: always
ports:
- ${IP}:10180:80
volumes:
- ./data:/srv
- ./db/database.db:/database.db
networks:
- nginx_default
networks:
nginx_default:
external: true
之前一直使用 certbot 进行免费证书的申请,只是这东西的体验一直不是很好。这次换成了acme.sh 。 acme.sh 完全使用shell脚本编写,使用起来非常简单,按照官网文档很快就可以弄好。
之前为了改善网站的访问速度使用了 cloudflare 的CDN功能(然而速度一如既往的慢),域名服务也一并迁到了 cloudflare 。既然不再使用 cloudflare DNS的解析也迁回了国内的 DNSPOD。
注:免费的HTTPS证书已经支持泛域名了,泛域名只支持DNS方式进行认证。
近期研究 ONNX Runtime Web 做的一个小东西。很多代码都“借鉴”于其他开源项目,解决了图片变形等问题。
使用深度学习模型做的图片风格迁移。使用 React 和 ONNX Runtime Web 开发,推理后端用的 WebAssembly ( CPU )。根据我的测试,用 WebGL 要慢不少,而且内存占用有些夸张。
在线访问: https://vicalloy.github.io/image-transformer/
项目地址: https://github.com/vicalloy/image-transformer
fast neural style
这个模型也可以支持输出任意图片大小,不过动态参数模型太大,复杂度也高,不适合 Web 使用。django-lb-workflow 我开发的一个Django流程引擎APP。设计之初是以使用便捷性为目标,自带了完整的模板,希望可以方便的集成到已有系统。尽管已经将django-lb-workflow
做到尽量的易用,但距离真正的开箱即用还有一段距离。
Carrot Box是一个完整的Django易用,带了权限管理、部门、角色等必要模块,真正的做到开箱即用。通过对Carrot Box
的定制可以方便的改造为OA、工单系统、CRM等业务系统。
Carrot Box
的主要特点:
之前的django-lb-workflow
范例站点已经切换到 Carrot Box
。
管理员账号:admin
密码:password
切换为其他用户: http://wf.haoluobo.com/impersonate/search
退回管理员账号: http://wf.haoluobo.com/impersonate/stop
make init-pyenv
make init
make run
项目地址(Go): https://github.com/vicalloy/telegram-shell-bot-go
由于对Go不熟悉,因此之前版本的 Telegram Shell Bot 采用Python实现。在Python版发布后就开始尝试使用Go重新实现,毕竟之所以要做这东西也是想借个小程序体验一下Go语言。
随着微服务的兴起,相较以往服务的粒度可以拆分的更细。系统复杂度更多的转变为微服务构架设计的复杂度。服务拆分后每个具体的服务的复杂度将降低,系统对程序语言本身的构架能力的依赖会减少很多。同时在服务拆分后,各个服务组件可以灵活的采用适合的技术来完成工作。
Go语言本身极度精简(简陋),如果要象Java一样搭建一个单体的巨型项目会存在一定困难。Go的高性能,异步,加之足够简单,使Go在一些对性能要求较高,但业务复杂度相对较低的场合会非常适合。
Go可能永远不能变的同Java一样流行,但Go已经足够成功,值得去体验。
Telegram Shell Bot Go 是我第一次使用Go写东西,由于只是一个小项目体验还不算特别深。Go语言中最精华的并发相关内容(goroutine / channel / select)并没有用到。
总的来说Go有着还不错的开发体验,但另一方便由于习惯了Python,Go又有不少让我用的不是特别舒服的地方。有人说Go是better C,我个人还是比较认可这个观点,相比其他语言Go很像C语言。
项目地址: https://github.com/vicalloy/telegram-shell-bot
很早之前就打算做这么一个东西,后来因为要调用的脚本是 Python 写的,于是直接在 Bot 里调用 Python 代码。 近期把这个想法重新实现了。
网上也有类似的项目,其中一些比较简单,甚至都没有对用户做校验,这样只要有人可以连上你的机器人就可以控制你的机器。类似的机器人里功能最强的是shell-bot。”shell-bot”模拟了一个 tty,实现较复杂,没有仔细研究。
Telegram Shell Bot目前提供的功能有:
;
跳过命令检查,类似的字符也应当加到字符串黑名单中。/tasks
命令查看有哪些命令还在执行中,并可以通过 /kill pid 的方式强制结束命令。echo password | su -S
的方式实现,需要自行评估风险。前几天又看了一下Django的Class-based views,想着django-lb-workflow的一些设计似乎还需要优化一下,于是又去折腾了一下django-lb-workflow。
Class-based views提高了代码的复用性,但过多的Mixin和继承层次让代码变的不那么容易理解。而且在面对一些“特殊”需求时会变的有些别扭。
一个列表界面搭配一个查询表单是一个很常见的操作,但想要在Django默认的ListView里添加这个查询Form并不太容易。在ListView里通过重载get_queryset方法修改查询内容。通过重载get_context_data修改context内容。按照我的理解合理的方式应当是在get_queryset函数中创建form,在form校验成功后使用form的参数作为查询条件返回查询后的queryset。但get_queryset无法直接同get_context_data函数打交道,必须先将 self.form = form
在到get_context_data中通过self.form
来获取form信息。这个过程变的非常不直观和奇怪。最终我还是选择不直接继承ListView,在自定义的ListView中重载get函数,在get函数中处理form和查询。
django-el-pagination
,使用Django自带的分页功能。simplewf
模块。对于只有一个事项名称和内容的流程,可以不写任何代码,只需要在系统中配置流程节点。做了上面一些更新后,对这个项目又开始有些倦怠了。下面的这些问题可能要等到下次再对这个项目提起兴趣的时候了。
Class-based views
中,可以通过Minxin灵活配置。注:Django REST framework权限部分的设计比较完善,相关代码可以直接移植过来。