系统正在维护中
方案一
nginx.conf1
2
3
4
5
6server {
listen 80
server_name localhost
# rewrite ^(.*)$ /maintainace_page.html break;
}
方案二
拦截503
如何优雅告知用户,网站正在升级维护
不间断升级维护
“蓝绿部署”
方案一
nginx.conf1
2
3
4
5
6server {
listen 80
server_name localhost
# rewrite ^(.*)$ /maintainace_page.html break;
}
方案二
拦截503
如何优雅告知用户,网站正在升级维护
“蓝绿部署”
OpenCV是计算机视觉领域应用最广泛的开源工具包,基于C/C++,支持Linux/Windows/MacOS/Android/iOS,并提供了Python,Matlab和Java等语言的接口
1 | pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple opencv-python |
1 | img = cv2.imread('singlemushroom.jpg', cv2.IMREAD_UNCHANGED) |
cv.imread的枚举参数
1 | result = cv2.resize(src, (200,100)) |
1 | #矩阵运算 |
1 | #通道顺序与R-G-B顺序相反 |
1 | #读取图片 |
自适应阈值 adapativeThreshold
1 | adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) |
1 | thresh1 = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) |
设想3*3矩阵 对中心位置像素值做卷积运算 其作用即一种平滑滤波
1 | #高斯滤波 |
1 | #腐蚀 |
开为先腐蚀再膨胀 闭为先膨胀后腐蚀
顶帽:原图像 - 开运算结果 顶帽得到的是开运算中断开的细节
底帽:原图像 - 闭运算结果 底帽得到的是闭运算中补上的细节
1 |
|
一种边缘提取方法
1 | contours,_=cv2.findContours(img,RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) |
cv2.drawContours()
1 | cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None) |
1 | x, y, w, h = cv2.boundingRect(contour) |
1 | mu = cv2.moments(contour, False) |
或者叫蒙版 将感兴趣区域(Region of Interest, ROI)提取出来 掩盖其他区域.
1 | h, w = gaussianBlur.shape |
反映像素的值在图像中的分布,值范围分段,进行统计,值可以是亮度,或任意色彩通道的分量
直方图可以作为阈值分割的参数选择依据
1 | import cv2 |
PIL( Python Imaging Library)是 Python 的第三方图像处理库,由于其功能丰富,API 简洁易用,因此深受好评。由于 PIL 库更新缓慢,目前仅支持 Python 2.7 版本,这明显无法满足 Python3 版本的使用需求。于是一群 Python 社区的志愿者(主要贡献者:Alex Clark 和 Contributors)在 PIL 库的基础上开发了一个支持 Python3 版本的图像处理库,它就是 Pillow。
Pillow 提供了丰富的图像处理功能,可概括为两个方面:
图像归档
图像处理
图像归档,包括创建缩略图、生成预览图像、图像批量处理等;而图像处理,则包括调整图像大小、裁剪图像、像素点处理、添加滤镜、图像颜色处理等。
Pillow 库可以配合 Python GUI(图形用户界面)工具 Tkinter 一起使用。
输入棋盘图片路径 棋盘角点数(横纵方格数减1)1
2
3
4
5
6
7
8def calibratePos(imgPath, w, h):
chessboardImg = cv2.imread(imgPath)
chessboardImg = cv2.cvtColor(chessboardImg, cv2.COLOR_BGR2GRAY)
ret, chessboard = cv2.findChessboardCorners(chessboardImg, (w, h), None)
cv2.drawChessboardCorners(chessboardImg, (w, h), chessboard, ret)
# cv2.imwrite('calibrated_image.jpg', chessboardImg)
cv2.imshow('calibrated image', chessboardImg)
cv2.waitKey(0)
vue的状态管理库
其核心是管理一个store(仓库) store保存变量的状态 组件引用store 查询状态
以commit mutation的方式更新状态
状态驱动视图 UI=f(state)
state
使用单一状态树,即app只用一个对象管理所有变量
vuex通过vue插件系统将store注入到每一个组件,子组件通过this.$store.count访问
1 | comouted: mapState(['count']) |
字符串为state的变量名
1 | store.commit('increment', payload) |
1 | const store = createStore({ |
mutation的处理方法不能是异步的 对于异步的状态是无法追踪的
与mutation类似
分发action1
store.dispatch('increment')
action通常传递一个mutation 其处理方法可以是异步的1
2
3
4
5
6
7actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
store/index.js1
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// 数据
const state = {
count,
user:{name:''}
}
const getters = {
getUser(state){
return state.user
}
}
// 修改数据
const mutations = {
updateUser(state, user){
state.user = user
}
}
// 异步操作
const actions = {
delayUpdate(store, user){
setTimeout(()=>{
store.commit('updateUser', user)
})
}
}
// 分装
const modules = {
moduleA:{
state,
mutations,
actions
},
moduleB:{
state,
mutations,
actions
}
}
子组件中 调用mutation用commit方法 调用action用dispatch方法1
2
3this.$store.commit('updateUser', user)
this.$store.dispatch('delayUpdate', user)
TypeError: Cannot read properties of undefined (reading ‘commit’)
vuex@4 不兼容vue2 改为vuex@3
定义store时 Vue.use(Vuex)
vtk Widget是官方提供的常用小工具,如LineWidget、AngleWidget、PaitWidget等
vtk Widget架构遵循MVC,分为三个组件
下图示意调用widget的不同组件的通信关系
Widget 工厂用于组装Widget及其state、representations
构建vtkWidgetState
调用getWidgetForView 工厂new一个widget对象 将state赋给该对象 创建并设置representations即SetRepresentation
开发者应继承vtkAbstractWidgetFactory开发widget
VTK的交互器样式(vtkInteractorStyle)通常只是控制相机以及提供一些简单的键盘和鼠标事件的交互技术。交互器样式在渲染场景中并没有一种表达形式,也就是说,在交互时我们看不见交互器样式到底是什么样子的,用户在使用这些交互器样式时,必须事先知道哪些键盘和鼠标事件是控制哪些操作的。FromCSDN: Widgets简介
vtkWidget同为vtkInteractorObserver子类,监听并响应交互器事件,又添加可视化的representation
Developing Widgets
vtkWidgetManager 是管理widgets创建、抑制(suppression)及聚焦(focus)的对象,每个render中唯一1
2
3
4
5
6
7
8widget = vtkWidget.newInstance()
handle = widgetManager.addWidget(widget, viewType)
widgetManager.setRenderer(renderer)
widgetManager.grabFocus(widget)
widgetManager.enablePicking()
widgetManager.removeWidget(widget)
widget.delete()
focus至多一个widget 激活并使能其响应事件(其实behaviour也可以在unfocus的状态下响应)
使用widget的newInstance方法创建widget对象 这时widget state被创建 用于在不同组件间同步状态 比如工具栏和canvas的相互交互
viewType用于指示widget manager该使用的representation。
创建子状态1
2
3
4
5
6
7
8
9
10
11
12vtkStateBuilder
.createBuilder()
.addStateFromMixin({
labels: ['{LABEL0}'],
mixins: ['origin', 'color', 'scale1', 'visible'],
name: '{NAME}',
initialValues: {
scale1: 0.1,
origin: [1, 2, 3],
visible: false,
}
})
调用widgetManager.getRepresentationsForViewType(viewType)返回含representation的集合 参数viewType是addWidget时指定的参数
返回各项 {builder, labels} 前者是Representation类 后者是representation对象要用到的子状态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
38switch (viewType) {
case ViewTypes.DEFAULT:
case ViewTypes.GEOMETRY:
case ViewTypes.SLICE:
return [
{
builder: vtkCircleContextRepresentation,
labels: ['handle', 'trail'],
},
{
builder: vtkPolyLineRepresentation,
labels: ['trail'],
},
];
case ViewTypes.VOLUME:
return [
{
builder: vtkSphereHandleRepresentation,
labels: ['handles'],
initialValues: {
scaleInPixels: true,
},
},
{
builder: vtkSphereHandleRepresentation,
labels: ['moveHandle'],
initialValues: {
scaleInPixels: true,
},
},
{
builder: vtkSVGCircleHandleRepresentation,
labels: ['handles', 'moveHandle'],
}
];
default:
return [{ builder: vtkSphereHandleRepresentation, labels: ['handle'] }];
}
Representation托管自身actors和mappers, actor在Representation创建时创建,推入model.actors中进而渲染
Representation应继承vtkHandleRepresentation 或 vtkContextRepresentation
Widget behavior
widgetManager.addWidget返回的handle就是widget behavior对象 它控制这widget的行为:接收并响应鼠标、键盘事件 见其定义的方法形如 PublicAPI.handle{XXX}(callData)
widget behavior也可以访问renderer rendererWindow 和 interactor
1 | // main.js |
h 是 createElement 的别名
$mount(‘#app’) 表示将该组件挂在到id=”app”的dom上,这个#app在public/index.html上
类似于React的 Context Provider, 避免父组件向孙子后代组件传参时逐层引用,而以依赖注入的形式暴露给其他组件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25const app = Vue.createApp({})
app.component('todo-list', {
data() {
return {
todos: ['Feed a cat', 'Buy tickets']
}
},
provide: {
user: 'John Doe'
},
template: `
<div>
{{ todos.length }}
<!-- 模板的其余部分 -->
</div>
`
})
app.component('todo-list-statistics', {
inject: ['user'],
created() {
console.log(`Injected property: ${this.user}` // > 注入的 property: John Doe
}
})
注意 provide 组件实例property,需要用返回函数的形式1
2
3
4
5provide() {
return {
todoLength: this.todos.length
}
}
1 | @startuml |
指的是生命周期的选项 类似React class组件中‘选择’恰当的生命周期钩子嵌入业务逻辑。 created, mounted 等生命周期钩子,直接对应 componentDidMount, componentDidUpdate 等
Composition API则React function组件中的hooks
ref() 和 reactive() 对应 useState。
computed() 对应 useMemo。
onMounted -> useEffect(…, [])
onUpdated -> useEffect(…, […]) (不指定依赖)
onUnmounted -> useEffect(() => { return () => { … } }, [])
defineProperty
defineConponent
vue cli 项目配置包含项目基本配置和对webpack的封装
基本配置:
1 | module.exports = defineConfig({ |
本节为后续补充,用于资深软件工程师基础面试复习;上文保留原始笔记。上文用 React Hooks 类比 Composition API 便于入门,但两者的响应式模型、依赖声明和更新机制并不等价。
回答 Vue 原理问题时,可以先建立一条完整链路:
key 和编译器提示执行 patch,最终修改必要的 DOM。所以“数据变化就重新渲染整个页面”并不准确。变化触发的是依赖该数据的 effect;组件可能重新执行渲染函数,但真实 DOM 只提交比较后需要变更的部分。
ref、reactive 与解构边界ref(value) 用带 .value 的对象保存值,适合基本类型、需要整体替换的对象以及 composable 的返回值。reactive(object) 返回 Proxy,适合围绕同一对象组织多个相关字段。它依赖代理访问完成追踪,不能替换成一个全新的普通对象后还期待原引用继续响应。.value。reactive 对象得到的是当前属性值,后续读取不再经过原 Proxy。可用 toRef() 或 toRefs() 保留属性级响应性。shallowRef()、markRaw() 有时比默认深响应更合适。1 | import { reactive, toRefs, watchEffect } from 'vue' |
这里的 online、alarm 是指向原对象属性的 ref。若写成 const { online } = state,得到的只是解构当时的数字。
computed、watch 与 watchEffect| API | 主要职责 | 选择依据 |
|---|---|---|
computed |
声明有缓存的派生状态 | 结果可以由其他响应式状态纯计算得到 |
watch |
监听明确的数据源并执行副作用 | 需要新旧值、精确控制触发源或控制执行时机 |
watchEffect |
自动收集同步执行阶段读取的依赖 | 副作用依赖较直观,希望立即运行且不想重复列依赖 |
不要用 watch 维护本可由 computed 得到的第二份状态,否则容易产生同步顺序和一致性问题。异步监听还要处理过期请求:在回调中注册 cleanup,取消旧请求或让旧响应失效,避免后发请求被先发请求的迟到结果覆盖。
1 | watch(deviceId, async (id, _oldId, onCleanup) => { |
Vue 3 并非只依靠运行时逐节点比较。编译器可以识别静态节点和动态绑定,运行时据此减少不必要的比较。理解这一点比背诵某个 diff 实现细节更重要。
连续的同步状态修改通常会被批量处理:
1 | count.value += 1 |
nextTick() 的含义是等待当前 Vue 更新队列刷新,不是通用延时器,也不保证图片加载、网络请求、浏览器绘制或第三方库的异步任务已经完成。
key 表达的是节点身份key 首先回答“新旧两次渲染中的节点是不是同一个实体”。稳定、唯一并来自业务实体的 key,可以让 Vue 正确复用或销毁组件实例和 DOM 状态。
用数组下标作为会插入、删除或重排列表的 key,可能让输入框状态、组件局部状态和实体错位。刻意改变组件 key 则可要求 Vue 销毁旧实例并创建新实例,但不应把它当作掩盖状态设计问题的常规刷新手段。
因此,“key 只是为了提升 diff 性能”是不完整的回答;正确性和状态身份比性能更先。
provide/inject 适合跨层提供稳定依赖,例如表单上下文、主题或领域服务;它不是所有共享状态的默认替代品。useXxx 命名判断。资深工程师还应说明组件边界:输入输出是否清晰、状态由谁拥有、副作用在哪里释放、组件能否独立测试,以及领域状态是否被 UI 框架细节绑死。
假设工业状态看板持续接收数千台设备的遥测,页面出现卡顿。不要一开始就回答“上虚拟列表”或“换 Web Worker”,而应分层定位:
shallowRef();不要为了“响应式”深代理整棵设备对象图。这类回答体现的是测量、分层和取舍,而不是背出更多 Vue API。
为什么修改状态后马上读取 DOM 还是旧值?
响应式值已同步改变,但组件 DOM 更新被调度和批处理。需要读取 Vue 本轮提交后的 DOM 时使用 await nextTick()。
reactive 和 ref 哪个性能更好?
通常不应先按微小性能差异选择。应先看状态形态、是否整体替换、是否需要解构和 composable API 的稳定性;大型数据再结合测量选择浅响应或原始对象。
为什么不能在子组件里直接修改 prop?
prop 的所有权属于父组件。子组件修改会破坏单向数据流,并可能在父组件重新渲染时被覆盖。可通过 emit 请求父级更新,或在边界清晰时使用 v-model 协议。
Composition API 是否天然比 Options API 更快?
二者主要是代码组织方式,不应笼统宣称 Composition API 运行更快。Composition API 的主要价值是按业务关注点组合逻辑、增强类型推导和逻辑复用;性能仍取决于实际依赖、渲染和数据结构。
深度学习网络对输入的数据进行多层的非线性变换操作, 不断耦合低层特征, 层层往上, 最后得到高层的语义表达
gpt 175 billion netro cell
白嫖限制试用的api
使用cloud function实现外网gpt代理访问
梯度下降
relu dropout
tianchi.aliyun
vibe coding 写深度学习: 我要做二手车价格预测,使用神经网络 tensorflow,搭建一个二层的神经网络,神经元的数量分别为 128 和 64 训练这个神经网络,使用 10%验证集进行验证,通过MAE进行验证,使用早停法,可以learning_rate稍微小一些,训练轮数大一些
创建新解决方案 使用webapi模板 new -> Project -> ASP.NET Core Web API template
命令行工具参考Microsoft Doc: dotnet new1
2
3
4
5
6mkdir MyServices
cd MyServices
dotnet new sln
mkdir src
dotnet new webapi -lang C# -o src/MyServices.API
dotnet sln add src/MyServices.API/MyServices.API.csproj
添加class library项目1
2
3
4dotnet new classlib -lang C# -o src/MyServices.EntityManagers
dotnet new classlib -lang C# -o src/MyServices.Models
dotnet sln add src/MyServices.EntityManagers/MyServices.EntityManagers.csproj
dotnet sln add src/MyServices.Models/MyServices.Models.csproj
创建详细目录,如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19─src
├───MyServices.API
│ ├───Controllers
│ ├───Infrastructure
│ │ ├───ActionFilters
│ │ ├───DbContext
│ │ ├───Helpers
│ │ ├───OData
│ │ └───Security
│ └───Properties
├───MyServices.EntityManagers
│ ├───interfaces
│ ├───Managers
│ └───Utilities
└───MyServices.Models
├───Contexts
├───DTO
├───Enums
└───Migrations
安装依赖
API layer
Microsoft DOc: Swagger/OpenAPI Swagger 项目已于 2015 年捐赠给 OpenAPI 计划,自此它被称为 OpenAPI。 是一个与语言无关的规范,用于描述 REST API。 它使计算机和用户无需直接访问源代码即可了解 REST API 的功能。
visual stuadio创建ASP.NET Core Web API项目模板,包含Enable OpenAPI support选项 即swagger页面
初始startup.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
27
28
29public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication1 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
配置加载名为swagger.json的接口描述,记作WebApplication1 v1的接口文档
swagger.json不会自动生成 从controller获取接口文档由下述swagger的实现包完成
启用xml注释
右键API项目 -> Properties -> Build -> Output
Output path 为空 即项目根目录
勾选XML documentation file 并命名
1
2
3
4
5
6
7
8
9
10
11services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
c.DocInclusionPredicate((name, api) => api.HttpMethod != null);
// Locate the XML file being generated by ASP.NET
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "WebApplication1.API.xml", SearchOption.TopDirectoryOnly);
// Tell Swagger to use those XML comments.
xmlFiles.ToList().ForEach(xmlFile => c.IncludeXmlComments(xmlFile));
});
详情待续 参考Microsoft Doc:Swashbuckle入门