它反映了包括Qt在内的GUI应用程序的消息处理模型:
(1) 用户操作界面,被操作系统内核空间中的设备驱动程序感知
(2) 设备驱动程序向操作系统的用户空间的GUI应用程序发出系统消息
(3) GUI应用程序将系统消息转换为信号,进而触发槽函数
在GUI应用程序中,一个核心且关键的操作就是将系统消息转换为信号,涉及到Qt的事件处理机制:
(1) Qt平台将系统底层发来的消息转换为Qt事件,并将其Qt事件产生后立即被分发到QWidget对象
(2) QWidget对象中的event(QEvent* )函数对事件进行处理,即根据不同的事件,调用不同的事件处理函数
(3) 在事件处理函数中发送Qt中预定义的对应事件的Qt信号,进而调用到信号关联的槽函数
以触摸屏为例 当用户点击触摸屏,首先感知到屏幕上被触摸的XY坐标是操作系统内核空间的触摸屏设备驱动程序,然后设备驱动程序会将用户操作封装成消息传递给GUI程序运行时创建的消息队列,GUI程序在运行过程中需要实时处理队列中的消息,当队列没有消息时,程序将处于停滞状态。
windows平台上GUI程序示例 在Windows上实现GUI有很多方法,每一种方法都有着自己的一套开发理念和工具,常见的有:
a. Windows API:直接调用Windows底层绘图函数。涉及到底层的基本用c语言写的,这些API也是如此。
b. MFC:使用Windows API封装成控件类
c. Windows Form:基于.net的GUI开发,完全组件化但是需要.Net运行库支持
…
其中基于Windows API开发的GUI程序,即是函数调用 + Windows消息处理的方法,这是所有GUI程序的原理。
在Qt中,事件被封装成一个个对象,所有的事件均继承自抽象类QEvent. 接下来依次谈谈Qt中有谁来产生、分发、接受和处理事件:
1、谁来产生事件: 最容易想到的是我们的输入设备,比如键盘、鼠标产生的
keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他们被封装成QMouseEvent和QKeyEvent),这些事件来自于底层的操作系统,它们以异步的形式通知Qt事件处理系统。当然Qt自己也会产生很多事件,比如QObject::startTimer()会触发QTimerEvent. 用户的程序可还以自己定制事件
2、谁来接受和处理事件:答案是QObject。在Qt的内省机制剖析一文已经介绍QObject 类是整个Qt对象模型的心脏,事件处理机制是QObject三大职责(内存管理、内省(intropection)与事件处理制)之一。任何一个想要接受并处理事件的对象均须继承自QObject,可以选择重载QObject::event()函数或事件的处理权转给父类。
3、谁来负责分发事件:
对于non-GUI的Qt程序,是由QCoreApplication负责将QEvent分发给QObject的子类即Receiver.对于Qt GUI程序,由QApplication 的QtWndProc来负责 分发 /*!\reimp */ bool QCoreApplication::event(QEvent *e) { if (e->type() == QEvent::Quit) { quit(); return true; } return QObject::event(e); } C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um\WinUser.h /* * Message structure */ typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; #ifdef _MAC DWORD lPrivate; #endif } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG; if (!
在做项目的过程中,遇到页面切换后不会滚动到顶部
解决方案:
在页面使用的layout中或者页面中,使用监听
watch: { '$route': function(to,from){ document.body.scrollTop = 0 document.documentElement.scrollTop = 0 this.$refs.scroll.scrollTop = 0 // 因为我的的滚动层不是body,所以将滚动层的scrollTop 至为0 } }, 还有在官方文档中看到的其他解决方案,大家可以试下
在nuxt.config.js:中配置 module.exports = { router: { scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 } } } } 默认情况下,从当前页面切换至目标页面时,Nuxt.js 会让目标页面滚动至顶部。但是在嵌套子路由的场景下,Nuxt.js 会保持当前页面的滚动位置,除非在子路由的页面组件中将 scrollToTop 设置为 true。 <template> <h1>子页面组件</h1> </template> <script> export default { scrollToTop: true } </script> 我们可以在nuxt.config.js:配置所有页面渲染后滚动至顶部: module.exports = { router: { scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 } } } } 使用路由守卫,在nuxt中配置路由守卫可以在plugins文件下新建router.
pd.readcsv()频繁报这个错误
一开始我天真的以为,加个encoding的事儿(原来是没有encoding的):
结果依旧报错
最后发现是我电脑默认第一次打开csv文件的编码问题。
解决办法如下:
右键以记事本打开csv文件->另存为->修改为utf-8编码->overwrite原文件->大功告成
前言 Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。
问题 本来想在setting中导pandas的包,按照百度的方法却报错:
Could not find a version that satisfies the requtrement pandas
解决方法 打开cmd,采用双保险方法(既延长时间又采用国内镜像源),输入命令:pip install pandas --default-timeout=100 -i https://pypi.tuna.tsinghua.edu.cn/simple
这样就下载成功啦,其他第三方包或库下载方法类似。
Introduction 图像的模糊严重影响图像的本身质量,同时在进行图像的识别和图像中物体识别都会产生影响。图像去模糊旨在从相应的模糊图像中恢复潜在的清晰图像。
大多数传统方法将图像去模糊任务公式化为模糊核估计问题,在过去的十年中,已经开发了各种自然图像和先验核来规范潜在锐利图像的解空间,包括重尾梯度先验,稀疏核先验,梯度先验,归一化稀疏性和暗通道。
然而,这些先验是通过有限的观察来估计的,并且不够准确。结果,去模糊的图像通常欠去模糊(图像仍然模糊)或过度去模糊(图像包含许多伪像)。 近年来深度神经网络和 GAN 的巨大成功,已经提出了一些基于 CNN 的方法用于图像去模糊,例如 Nimisha 在 ECCV 2018 发表的 Unsupervised Class-Specific Deblurring [1] 是一种基于 GAN 的无监督图像去模糊方法,在模型上增加了重复损失和多尺度梯度损失。虽然它们在合成数据集上取得了良好的性能,但它们对一些真实模糊图像的结果并不令人满意。
另一类方法是基于现有的图像到图像的模型,例如 CycleGAN [2] 这类无监督端到端的模型,然而,这些通用方法通常编码其他因素(例如:颜色、纹理)而不是将信息模糊到发生器中,因此不会产生良好的去模糊图像。
文章对这些方法进行了一个可视化结果比对,同时也是展示了自己模型的优越性:
上图最右侧就是这篇文章的实验效果,可以看出对比已有的基于深度神经网络的去模糊模型还是展示了不错的实现效果的。这些效果的实现得益于文章提出了一种基于解缠表示的无监督域特定图像去模糊方法,通过将模糊图像中的内容和模糊特征解开,以将模糊信息准确地编码到去模糊框架中。
我们后续再详细分析,这里总结一下文章的创新和优势所在:
内容编码器和模糊编码器将模糊图像的内容和模糊特征区分开,实现了高质量的图像去模糊;对模糊编码器添加 KL 散度损失以阻止模糊特征对内容信息进行编码;为了保留原始图像的内容结构,在框架中添加了模糊图像构造和循环一致性损失,同时添加的感知损失有助于模糊图像去除不切实际的伪像。 模型详解 我们还是先通过模型框架图去理解文章设计的思路:
我们先把模型中的组间介绍清楚,由于模型的循环一致性设计,网络的左右是基本对称的,我们对左侧组间交代下。
s 代表清晰的真实图像,b 代表模糊的真实图像,是生成的模糊图像,是生成的清晰图像。是清晰图像的内容编码器(可以理解为图像颜色、纹理、像素的编码器),对应的是模糊图像的内容编码器,是模糊图像的模糊编码器(仅用来提取图像的模糊信息)是模糊图像生成器,是清晰图像生成器,经过循环的转换,ŝ 是循环生成的清晰图像,b̂ 是循环生成的模糊图像。 看了这个模型,大家是不是有一些疑问,我们的目的是实现图像的去模糊,为什么要添加模糊编码器?为什么还要主动去生成模糊的图像?怎么保证模糊图像的内容编码器真的提取到图像的内容信息?为什么模糊编码器要同时作用在和上?
这些问题正是这篇文章区别于已有模型的关键,我们按照文章思路一步步去分析。
文章的一大创新就是模糊编码器的设计,它主要的作用是用来捕获模糊图像的模糊特征,如何去保证这个模糊编码器是真的提取到模糊图像的模糊特征了呢?
作者就采用了迂回的思路,既然清晰的图像是不含模糊信息的,如果清晰的图像通过结合模糊编码器模糊特征去生成出模糊图像,是不是可以说,模糊编码器是在对清晰图像做模糊化处理,这个模糊化的前提是什么?那就是模糊编码器确实提取到了图像的模糊特征,所以说由清晰图像生成模糊图像也保证了模糊编码器是对图像的模糊信息进行编码的作用。
同时,由清晰图像到模糊图像的生成过程中,清晰图像的内容编码器我们是有理由相信它是提取到了清晰图像的内容信息(因为清晰图像并不包含模糊信息)。
文章为了保证模糊图像的内容编码器是对模糊图像的内容进行编码,文章将清晰图像内容编码器和模糊图像内容编码器强制执行最后一层共享权重,以指导学习如何从模糊图像中有效地提取内容信息。
为了进一步尽可能多地抑制模糊编码器对内容信息的编码,通过添加一个 KL 散度损失来规范模糊特征的分布,使其接近正态分布 p(z)∼N(0,1)。这个思路和 VAE 中的限制数据编码的潜在空间的分布思路是相近的,这里将模糊编码器的编码向量限制住,旨在控制模糊编码器仅对图像的模糊信息进行编码。
理清了上面的设计思路,这篇文章的实现就已经基本介绍完毕了。由模糊图像去模糊到清晰图像的过程中,将模糊图像内容编码和模糊编码送入清晰图像生成器重构得到去模糊的清晰图像,清晰图像到模糊图像是为了优化模糊编码和模糊图像的内容编码的作用。
通过循环一致性,进行进一步的还原保证模型的鲁棒性。核心的损失是图像生成在 GAN 的对抗损失,结合感知损失达到图像下一些伪影的优化。
模型损失函数 本部分是对模型实现的补充,在上一小节中,也是大致上分析了各类损失的作用,这里做一个简短的展开。
首先是对模糊编码的隐空间分布进行约束,这个约束通过 KL 散度去实现,这个过程和 VAE 的思路是一致的:
这里的 p(z)∼N(0,1),具体的损失可进一步写为: 此时,zb 可表示为 zb=μ+z∘σ。
接下来就是 GAN 的那一套对抗损失,这里写一下清晰图像生成的判别器损失,模糊图像的是一致的:
图像平滑 2D卷积
与一维信号一样,我们也可以对 2D 图像实施低通滤波(LPF),高通滤波(HPF)等。LPF 帮助我们去除噪音,模糊图像。HPF 帮助我们找到图像的边缘
OpenCV 提供的函数 cv.filter2D() 可以让我们对一幅图像进行卷积操作。下面我们将对一幅图像使用平均滤波器。下面是一个 5x5 的平均滤波器核:
操作如下:将核放在图像的一个像素 A 上,求与核对应的图像上 25(5x5)个像素的和,在取平均数,用这个平均数替代像素 A 的值。重复以上操作直到将图像的每一个像素值都更新一遍
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('C:/Users/www12/Desktop/xingkong.jpg',1) kernel = np.ones((5, 5), np.float32)/25 #-1表示深度为-1时输出图像将自动匹配对应的深度 dst = cv2.filter2D(img,-1,kernel) cv2.imshow('img', img) cv2.imshow('dst',dst) cv2.waitKey(0) cv2.destroyAllWindows() 图像模糊(图像平滑)
使用低通滤波器可以达到图像模糊的目的。这对与去除噪音很有帮助。其实就是去除图像中的高频成分(比如:噪音,边界)。所以边界也会被模糊一点。(当然,也有一些模糊技术不会模糊掉边界)。OpenCV 提供了四种模糊技术。
1. 平均
这是由一个归一化卷积框完成的。他只是用卷积框覆盖区域所有像素的平均值来代替中心元素。可以使用函数 cv2.blur() 和 cv2.boxFilter() 来完这个任务。可以同看查看文档了解更多卷积框的细节。我们需要设定卷积框的宽和高。下面是一个 3x3 的归一化卷积框:
(注意:如果你不想使用归一化卷积框,你应该使用 cv2.boxFilter(),这时要传入参数 normalize=False。)
import cv2 import numpy as np img = cv2.
文章目录 前言STM32CubeMX新建工程CAN配置生成代码CAN发送CAN接收CAN3CANFD板子CANFD配置CANFD发送CANFD接收工程代码微信公众号 前言 STM32CubeMX_环境搭建_GPIO_外部中断
STM32CubeMX_定时器中断_PWM
STM32CubeMX_UART_printf_接收中断_DMA空闲中断_LPUART
STM32CubeMX_以太网_RMII_LwIP_UDP
前四节简单的总结了GPIO, EXTI, TIMER, UART, 以太网的相关用法, 本节总结一下STM32的CAN, FDCAN, CAN3的用法. STM32的CAN很多系列都有: F0/1/2/3/4/7, L4/L4+等都能找到CAN的身影, 分别有1路到3路不等. 而FDCAN在STM32G系列/H系列/L5系列中比较常见. 本节我们先从CAN开始, 原理性的东西自己查去, 主要看操作.
用的是下面这个自制的STM32F405RGT6的板子:
CAN的引脚为:
CANSTM32CAN1_TXPB9CAN1_RXPB8CAN2_TXPB13CAN2_RXPB12 然后通过CAN电平转换芯片TJA1051连接到CAN分析仪上去:
MCU本身外接的12MHz的晶振, 硬件连接介绍完毕, 下面开始操作.
STM32CubeMX新建工程 步骤如下:
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32F405RGTx调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial WirePinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic ResonatorClock Configuration:
注意CAN时钟属于APB1 peripheral clocks(MHz), 所以是42MHz.
前因:DSM的手机APP很好用,可以用来在局域网内和外网直接播放存储在DSM硬盘上的视频和音乐。
困难:DSM中的硬盘是需要物理独占的,而且是独占整块盘,并且会把硬盘的格式转换为EXT4。那样这个硬盘取下直接在Windows中是无法读取的。而且平时只能在DSM中对盘上的文件做删减和拷贝处理,不是很方便。
解决方法:通过NFS方法把磁盘的某个目录挂载给DSM,DSM不会独占硬盘,硬盘格式还可以继续为NTFS,文档的移动和删减操作直接在Windows上操作。
那为何要用第三方NFS工具?因为Windows Server 2012 R2自带的NFS组件的UTF-8编码支持不好。
第一步,服务器端设置
安装文件和注册机
安装完后要以管理员身份运行*,不然无法修改配置
打开注册机,获得注册码。
在注册页面,填入注册码。注意用户名和注册码的位置。
修改exports file,一定要按照示例格式修改。
语句的大致意思是,把server 2012上D:\DSM\homes的文件夹,链接给IP地址为192.168.1.12的机器(本人的DSM),链接名称为homes
D:\DSM\homes -name:homes 192.168.1.12 D:\DSM\music -name:music 192.168.1.12 D:\DSM\photo -name:photo 192.168.1.12 D:\DSM\video -name:video 192.168.1.12 D:\DSM\download -name:download 192.168.1.12 E:\pt -name:pt 192.168.1.12 注意,这个页面在DSM的设置之前,或许不会显示内容。再全部设置完毕后,再来查看这页。
**
防火墙添加TCP&UDP端口的入站规则:111,1058,2049 **
TCP
UDP
第二步,客户端设置 文件夹路径为:主机ip+hanewin挂载的文件夹名 我这里是192.168.10.220:/pcd
hanewin工具下载
1、点击工具栏的“虚拟机”,在下拉列表选择“设置”
2、网络连接那一栏中选择“NAT模式”
3、进入Linux系统后,登陆超级用户
# su root
4、切换到存有配置文件的目录
# cd /etc/sysconfig/network-s
5、找到下图ifcfg-eth0文件,一般是在列表的第一个
# ll
6、vi进入该文件编辑
# vi ifcfg-eth0
7、按下图编辑修改
7、eth0是Linux默认的网卡,将它激活
# ifup eth0
8、重启网络服务
# service network restart
9、到这就可以打开游览器上网啦~
论文地址:https://arxiv.org/pdf/1902.01374.pdf
Table of Contents
主要贡献:
缺陷:
0.论文提出的数据集(MRFID)(尚未开源)
1. 论文的主要思路是:
1.1 实现去雾过程:有雾图像 》》》清晰图像
1.2. 逆向生成雾图: 清晰图像 》》》 有雾图像
1.3 训练数据的合成(使用CNN)
2. 实验结果
4. 客观评价指标:
在真实的数据上测评
主要贡献: 该系统使用不成对的雾和无雾训练图像,对抗性鉴别器和循环一致性损失来自动构建除雾系统;通过嵌入大气散射模型的原理和天空先验知识,训练CNN网络进行训练数据的合成;提供一个数据集(MRFID)包含200个自然户外场景的图像;所使用的评价标准是new visible edges e,contrast restoration r, 缺陷: CycleDefog2Refog无法处理大雾;原因是当前大气降解模型在这种情况下不能再准确地描述雾图,在未来的工作中,希望通过专门优化此模型并构建多种多雾的数据集来训练我们的网络来解决这个问题;处理的图像有些过于平滑,损失了图像细节;近景偏暗,远景雾气没有去除的很好。 0.论文提出的数据集(MRFID)(尚未开源) 包含200个自然户外场景
图像是从固定摄像机在一年的过程中拍摄的一系列图像中手动选择的不同雾密度
一个场景 》》》一个清晰图像 》》》四个相应的四个雾密度图像
包括200个清晰的户外图像和800个具有不同雾密度的模糊图像
1. 论文的主要思路是: 1.1 实现去雾过程:有雾图像 》》》清晰图像 采用的方法是两步实现去雾过程,即第一步去除较少的雾,第二步进行加强。
1.2. 逆向生成雾图: 清晰图像 》》》 有雾图像 同样采用两步进行雾气的生成。
1.3 训练数据的合成(使用CNN) 在传统的CycleGAN中,我们可以使用CNN直接生成模糊图像以禁止defog映射功能。 然而,在实践中,由于各种模糊图像内容的多样性和复杂性,仅通过使用卷积神经网络来拟合模糊图像的分布是非常困难的。 相反,我们引入了基于CNN的大气降解模型来合成模糊图像。 具体地,我们使用CNN来估计透射图T并使用sky prior 估计大气光A。
在使用清晰图像生成有雾图像的过程中,使用的方法是:
2. 实验结果 4. 客观评价指标: In this experiment,the synthetic images have come from RESIDE dataset [17].
功能描述:当DPR=2,显示2X图片;当DPR=3,显示3X图片
实现方式:
1、dom结构
<div class="title"> <span class="brand"></span> <span class="name">{{seller.name}}</span> </div> 2、.brand样式
@import "../../common/stylus/mixin"; .brand display: inline-block vertical-align: top width: 30px height: 18px bg-image('brand') background-size: 30px 18px background-repeat: no-repeat 3、 bg-image('brand')是定义在 mixin.styl中的方法,用来实现展示哪张图片,传递一个字符串参数:
bg-image($url) background-image: url($url + "@2x.png") @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) background-image: url($url + "@3x.png") 以上,即可实现根据DPR设置展示的图片是2X还是3X
今天,当我用git进行代码管理的时候,执行git commit -m"样式修改"会出现如下信息:
> running pre-commit hook: lint-staged ❯ Running tasks for *.js ✖ vue-cli-service lint → 2 errors and 2 warnings found. git add ❯ Running tasks for *.vue ✖ vue-cli-service lint → 31 errors found. git add 出现如此状态,真是让人头疼,接下来看看解决方式:
解: 进入 项目所在文件夹>.git>hooks
删除hooks目录下的内容!没错,你没有看错,是删除!
然后再重新执行git commit命令,至此大功告成
原创文章,欢迎转载。转载请注明:转载自 祥的博客
原文链接:https://blog.csdn.net/humanking7/article/details/102939393
word 插入题注快捷键
动机 批量插入题注的时候真的很烦,尤其是这个还没有方便的快捷键,所以就自定义快捷键,有了此教程。
方法1 word原始快捷方式 依次按:Alt-S-P
方法2 设置自定义快捷键 打开键盘快捷键定义对话框:
文件 选项 自定义功能区 键盘快捷方式:自定义 在对话框中找到插入题注的命令,并设置快捷键:
引用选项卡 命令:InsertCaption 我设置的是Ctrl+Q:一来quote有引用的意思,二来Ctrl+E是居中,方便
OK!
以上,Enjoy~
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3ppv3k3uoaqsw
redux的store状态数据不是永久保存的,state只是一个内存机制。
我们知道的本地数据库或者像localstorage之类的缓存系统才有可能长时间的保存数据,redux-persist可以让你的数据从state分离出来,保存到浏览器缓存中,以便实现数据的持久化存储
下面是我自己的代码,没有使用thunk中间件
我圈出的红色部分就是是用persist需要用到元素,其他关于action 都保持不变
cx_Oracle 1、首先要安装cx_Oracle模块,测试在python安装目录下,执行 pip install cx_Oracle 是可以安装的,但是网上说要核对Oracle的版本和python的版本,我安装之后,和python的版本是能对应起来的,可能是巧合,和Oracle的版本也是能对应起来的,如果有对应不起来的情况,建议可以从下面的网址找对应的版本下载 https://oracle.github.io/python-cx_Oracle/
2、然后是操作数据库 import cx_Oracle as ora # 导入模块 conn = ora.connect("用户名/密码@IP:PORT/SERVER_NAME") # 连接数据库 cursor = conn.cursor() # cursor方法相当于设置一个游标,由于对Oracle不是很熟悉,反正就是没有这一步是不可以进行后续操作的 sql = "select * from t_transcode" # 自定义sql语句 cursor.execute(sql) # execUte方法用来执行sql语句 data = cursor.fetchone() # fetchone方法执行结果的第一条数据,返回成一个元组 data_all = cursor.fetchall() # fetchall方法获取sql语句执行结果的所有数据,返回一个列表,每条数据作为一个元组 print(data) print(type(data)) print(data_all) 这个模块的基本所有方法都没有智能提示,很烦
瞎测试,居然可以,记录一下
路径里面有#号特殊字符,好像不行,重写下url好像可以访问。
原地址是 http://xxxxxxx/index.xhtml#/xxxx 里面有#号
用新的地址变成 http://xxxxxxx/test#/xxxx location ^~ /test {
rewrite ^/index.xhtml#/(.*)$ /$1 break;
proxy_pass http://xxxxxxx:8002/index.xhtml#/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
set $flag 0;
if ($http_referer ~ test) {
set $flag "${flag}1";
} if ($flag = "01") {
proxy_pass http://xxxxxxxx:8002;
}
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Web of Science导出的.ciw文件导入endnote X8时选endnote import有时会没有反应,可以选xml,导入成功。
从万方或者知网导出的txt文件导入时会出现乱码,选no translation或者UTF8
前言
无刷直流 (Brushless Direct Current, BLDC)电机是一种正快速普及的电机类型,它可在家用电器、汽车、航空航天、消费品、医疗、工业自动化设备和仪器等行业中使用。正如名称指出的那样,BLDC 电机不用电刷来换向,而是使用电子换向。BLDC 电机和有刷直流电机以及感应电机相比,有许多优点。其中包括:
• 更好的转速-转矩特性
• 快速动态响应
• 高效率
• 使用寿命长
• 运转无噪音
• 较高的转速范围此外,
由于输出转矩与电机体积之比更高,使之在需要着重考虑空间与重量因素的应用中,大有用武之地。
有刷电机 无刷电机 关于BLDC的基本原理与控制控制基础知识上一讲已经介绍,本节将用NUCLEO-F103RB和X-NUCLEO-IHM07M1 3SH快速为大家实现BLDC的转动控制!
本节所用电机为2836无刷电机,电机有两组线(hall传感器线和电机三相线),工作电压24V,最大转速12000rpm:
示例详解
本节用到ST官方推出的NUCLEO-F103RB和X-NUCLEO-IHM07M1 3SH 开发板。
NUCLEO-F103RB对应的大致原理接线图:
X-NUCLEO-IHM07M1 3SH部分原理图:
准备操作 X-NUCLEO-IHM07M1 3SH是一款专门用于PMSM(永磁同步)或BLDC(直流无刷 )的电机驱动板,其电机驱动板驱动芯片型号为L6230(详细数据手册可在st官网下载),本节主要目的是给大家演示BLDC 6步方波控制原理,仅需让BLDC电机实现简单正反转动即可,仅需用到IN1,IN2, IN3和OUT1,OUT2,OUT3以及HALL传感器信号接口H1,H2,H3。 需要用到的信号
对应MCU引脚
EN1
PC10
IN1
PA8
EN2
PC11
IN2
PA9
EN3
PC12
IN3
PA10
H1
PA15
H2
PB3
H3
PB10
为了更加简单地介绍清楚BLDC 6 步方波控制的具体实现,本节直接使用普通IO口方式实现对BLDC电机的6步方波驱,将EN1、EN2、EN3和 IN1、IN2、IN3全部配置成普通输出IO口输出模式,H1,H2,H3配置普通IO口输入模式。
在STM32CubeMX中,有专门的NUCLEO-F103RB工程模板,新建一个Cube工程,芯片型号为st32f103rb: 生成一个简单的工程模板实现了RCC,SYS,USART2接口的配置,同时还实现了LD2(LED)引脚的配置。接下来手动配置IO: 配置PA8,PA9,PA10,PC10,PC11,PC12为GPIO_OUTPUT模式, PA15,PB0,PB10为GPIO_INPUT模式:
生成工程:
打开工程, 在main.
ENOSPC: System limit for number of file watchers reached, watch echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
这里的权限只是局限于前端,只用来控制用户角色在登陆后应当显示哪些菜单,真正的权限校验配置还会在后端维护一套路由表(这里官方文档说是为了摆脱前后端耦合的支配,我觉得没必要,这个可以在开发之前先让后端开发路由增删查改接口,直接暴露给前端配置,应该耗不了多长时间,这样前端只要post个json到后端就可以完成配置。用户的惯性思维是我能看到就应当可以操作,不管是从安全的角度还是用户体验的角度, 权限都理应由后端统一控制。)。
※阅读时主要关注注释点。本文主要记录作者分析过程发现的关键点,如需详细教程请移步Github上的官方文档。
本文基于4.2.1版本国际化分支 i18n Branch代码做分析
(主干在版本v4.1.0之后已不再支持国际化,但仍会保持与主干同步更新该分支。
After the v4.1.0+ version,the default master branch will not support i18n.Please use i18n Branch, it will keep up with the master update)。
1.没登陆之前 没登陆之前只挂载不需要权限的路由,比如login之类的
1.1、main.js引入router.js import router from './router' //这里其实只挂载了不需要权限的路由 new Vue({ el: '#app', router, store, i18n, render: h => h(App) }) 1.2、非权限路由挂载(router.js) export const constantRoutes = [ { path: '/redirect', component: Layout, hidden: true, children: [ { path: '/redirect/:path*', component: () => import('@/views/redirect/index') } ] }, { path: '/login', component: () => import('@/views/login/index'), hidden: true }] //创建路由实例 const createRouter = () => new Router({ // mode: 'history', // require service support scrollBehavior: () => ({ y: 0 }), routes: constantRoutes //不需要权限的路由 }) //初始化路由实例 const router = createRouter() //导出 export default router 2.
1、什么是CUDA
CUDA(ComputeUnified Device Architecture),是显卡厂商NVIDIA推出的运算平台。 CUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。
2、什么是CUDNN
NVIDIA cuDNN是用于深度神经网络的GPU加速库。它强调性能、易用性和低内存开销。NVIDIA cuDNN可以集成到更高级别的机器学习框架中,如谷歌的Tensorflow、加州大学伯克利分校的流行caffe软件。简单的插入式设计可以让开发人员专注于设计和实现神经网络模型,而不是简单调整性能,同时还可以在GPU上实现高性能现代并行计算。
3、CUDA与CUDNN的关系
The NVIDIA CUDA® Deep Neural Network library (cuDNN) is a GPU-accelerated library of primitives for deep neural networks. cuDNN provides highly tuned implementations for standard routines such as forward and backward convolution, pooling, normalization, and activation layers.
Deep learning researchers and framework developers worldwide rely on cuDNN for high-performance GPU acceleration. It allows them to focus on training neural networks and developing software applications rather than spending time on low-level GPU performance tuning.
首先是普通的vant文件上传
<van-uploader multiple v-model="fileList" accept=image/jpeg :max-count="1" :after-read="afterRead" ref="selectfile" /> data(){ return{ filelist:[], } } methods: { // 用表单提交 afterRead(file) { //文件读取完成后的回调函数 let content = file.file; //创建一个新的FormData let formData = new FormData(); // upload这个名字是后台给的 formData.append("upload", content); //获取formdata表单所有的数据 console.log(formData.getAll("")); // axios // .post( //服务器上传地址 // `http://xxxxxxxxxxxx`, //服务器需要的数据,此处是formdata表单 // formData,(名字是后台参数确定的) //如果默认请求头是json,需要改一下请求头数据格式 // { // "Content-Type": "multipart/form-data" // } // ) // .then(res => { // console.log(res); // console.log(res.config.headers); // }); axios({ method: "
效果1:
效果2:
此次开发的工具都用纯原生代码进行Android的应用开发的,其实原理都是用了无障碍功能(AccessibilityService)进行处理。上个版本的工具太麻烦了,还需要进行相应的参数接口破解,获取到相应的值再对H5进行处理,总之叽里呱啦的一连串麻烦,也容易被封号,此次的工具只是作为一个辅助性的,完全不需要对目标应用进行啥破解之类,直接说就是仿真人操作,进行一系列仿真操作。
以下是主要开发流程:
1.使用AccessibilityService最开始的配置
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="" android:canRetrieveWindowContent="true" android:description="@string/app_name" android:canPerformGestures="true" android:notificationTimeout="100" /> 上面是使用配置文件的方式的,不过我比较喜欢用代码的方式进行配置,反正两个都可以一起使用啦,只不过是在代码的时候重新获取一下之前配置文件的东西在进行配置而已,反正看你喜欢。代码配置的话在 onServiceConnected 这个方面里面进行处理就行了
//可用代码配置当前Service的信息 AccessibilityServiceInfo info = getServiceInfo(); //监听过滤的包名 //info.packageNames = new String[]{PackageName.SYSTEMUI.getPackageName()}; //监听响应事件 info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_ALL_MASK; //通知的时间 info.notificationTimeout = 100; //设置标志位,读取webView内容 info.flags = AccessibilityServiceInfo.DEFAULT | AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS | AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS | AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS; setServiceInfo(info); 目前我这里是不做包名的过滤的,如果不配置包名的话,就是全部的应用都会进来的,我这里就是要全部的应用都进来,然后在里层自己做一个目标包的拦截过滤。我这个方法
DataListHelper.isExistPackageName(packageName) 就是过滤我支持的目标的,反正自己意会
2.任何动作的操作都是靠心跳来进行,心跳带动随机时间进行页面的滑动处理,比如说1秒一个心跳, 事先准备一个事件的随机时间,当心跳跳动次数达到随机时间就进行一个事件动作。 随机时间那个,反正就是根据给定一个范围值,至于这个范围值,自己根据相应的动作去估算吧。动作处理时间反正不要每次都相等,一定要随机时间,这个很重要
心跳那个,我用了RxJava的,每秒都执行一个回调
/** * 执行心跳 * * @param handler * @return */ public static Disposable executeHeartBeat(final Handler handler) { return Flowable.
1.简介
CiteSpace 又翻译为“引文空间”,是一款着眼于分析科学分析中蕴含的潜在知识,是在科学计量学、数据可视化背景下逐渐发展起来的引文可视化分析软件。由于是通过可视化的手段来呈现科学知识的结构、规律和分布情况,因此也将通过此类方法分析得到的可视化图形称为“科学知识图谱”。摘自 李杰.CiteSpace中文版指男
2.如何用Citesapce挖掘现有数据,首先对于一些名词进行解释。
①共被引分析
在做学术研究时,我们势必会研究前人在此领域所做的工作,也会引用他人的研究成果。但一开始不同人对于某一新的领域的探究是独立的,发表出来的研究论文处于游离状态。然而随着对该领域研究的的不段深入,人们在做研究时往往会引证前人的文献,每次引用就像扯了一条线,慢慢的越来越多的人引用他人的论文,就会以论文为节点,每次的引用作为线,形成一个引文网络。
共被引分析就诞生在这个引文网络上面,当两篇甚至多篇文献同时出现在第三篇引用文献的参考文献目录中,则这些被引用的论文就形成了共被引关系。像这种满足条件的第三篇论文的个数,就代表了共被引的次数。共被引次数越多,说明这些论文的相似度越大,关联强度也越大。
②共词分析
词频分析:在文献信息中提取能够表达论文核心内容的关键词和主题词频高低分布,来研究该领域发展动向和研究热点的方法。
共词分析则是在词频分析的基础上,对词频网络进行更高层次的分析,原理是对一组词两两统计他们在一组文献中出现的次数,以此来测度他们之间的亲疏关系。
③突现分析
Citespace提供burst detection的功能来探测在某一段时间引用量有较大的变化的情况。用于发现某一个主题词、关键词衰落或兴起的情况。
④聚类分析
指将物理或抽象对象的几何分组为由类似的对象组成的多个类的分析过程,以分析对象的相似性为基础。
⑤操作界面的其他功能
以上内容参考博客:https://www.jianshu.com/p/c3139ee1cf1f
欲详细了解可移步上述博客。
3.练手案例
区块链的总体分析:知网的8345篇生成的区块链的总体趋势图
根据文献发表数量的年度分布趋势,可以将其分为三个阶段,萌芽阶段、发展探索阶段、快速发展阶段、可以看出区块链技术的萌芽萌发于2013---2015年间,在2015到2017年间进入发展阶段,到 2017--2018年间快速发展,但2018--2019至今区块链发展趋于平缓。
主题分布图
将2015---2019年间核心期刊论文作为数据,进行可视化分析。
(1)首先建立四个空文件夹:
(2)将知网2015--2019关于区块链的文献导入到input文件夹(不同数据库导出文献的格式要求同,知网要求如下)
(3)仅可导入2015-2019年的5980篇论文数据
(4)
知网数据库里面的数据进行格式转换时用选择CNKI
将转换完成的output数据copy到data文件夹,如下图output中的数据。
(5)建立一个项目
(5)
4.分析图像(从图上可以获得的信息,暂不赘述)
核心作者分析:
核心机构分析图:
术语、关键字的时间线图
关键词、术语出现超过50次以上的
贪心算法 原理 在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
特性 贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。能够用贪心算法求解的问题一般具有两个重要特性:贪心选择性质和最优子结构性质。
1、贪心选择性质 所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素。贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。证明的大致过程为:首先考察问题的一个整体最优解,并证明可修改这个最优解,使其以贪心选择开始。做了贪心选择后,原问题简化为规模更小的类似子问题。然后用数学归纳法证明通过每一步做贪心选择,最终可得到问题的整体最优解。其中,证明贪心选择后的问题简化为规模更小的类似子问题的关键在于利用该问题的最优子结构性质。
2、最优子结构性质 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
3、贪心算法与动态规划算法的差异 动态规划和贪心算法都是一种递推算法,均有最优子结构性质,通过局部最优解来推导全局最优解。两者之间的区别在于:贪心算法中作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留,贪心算法每一步的最优解一定包含上一步的最优解。动态规划算法中全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解。
4、基本思路: 建立数学模型来描述问题。把求解的问题分成若干个子问题。对每一子问题求解,得到子问题的局部最优解。把子问题的解局部最优解合成原来解问题的一个解。 活动安排问题 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合,是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。
问题描述 设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。
求解思路 将活动按照结束时间进行从小到大排序。然后用i代表第i个活动,s[i]代表第i个活动开始时间,f[i]代表第i个活动的结束时间。按照从小到大排序,挑选出结束时间尽量早的活动,并且满足后一个活动的起始时间晚于前一个活动的结束时间,全部找出这些活动就是最大的相容活动子集合。事实上系统一次检查活动i是否与当前已选择的所有活动相容。若相容活动i加入已选择活动的集合中,否则,不选择活动i,而继续下一活动与集合A中活动的相容性。若活动i与之相容,则i成为最近加入集合A的活动,并取代活动j的位置。
下面给出求解活动安排问题的贪心算法,各活动的起始时间和结束时间存储于数组s和f中,且按结束时间的非减序排列。如果所给的活动未按此序排列,可以用O(nlogn)的时间重排。具体代码如下:
#include "stdafx.h" #include <iostream> using namespace std; template<class Type> void GreedySelector(int n, Type s[], Type f[], bool A[]); const int N = 11; int main() { //下标从1开始,存储活动开始时间 int s[] = {0,1,3,0,5,3,5,6,8,8,2,12}; //下标从1开始,存储活动结束时间 int f[] = {0,4,5,6,7,8,9,10,11,12,13,14}; bool A[N+1]; cout<<"各活动的开始时间,结束时间分别为:"<<endl; for(int i=1;i<=N;i++) { cout<<"["<<i<<"]:"<<"("<<s[i]<<","<<f[i]<<")"<<endl; } GreedySelector(N,s,f,A); cout<<"
Logback 对比 Log4j2 测试分为本地测试端和服务器端,分别对gateway网关进行日志输出的压测
同步日志,不打印日志 logback(150并发,0间隔,循环50次) log4j2(150并发,0间隔,循环50次) 同步日志,打印日志(大小4k,循环输出100次) logback(150并发,0间隔,循环50次) log4j2(150并发,0间隔,循环50次) 异步打印日志(大小4k,循环输出100次,仅输出文件) logback(150并发,0间隔,循环50次) log4j2(150并发,0间隔,循环50次) 测试环境 logback(50并发,0间隔,循环20次) 不打印日志 打印日志 log4j2(50并发,0间隔,循环20次) 不打印日志 打印日志 打印日志每条30k输出1000次(一次请求30M) log4j2(50并发,0间隔,循环20次) logback(50并发,0间隔,循环20次) 测试结果 对比响应时间 本地测试log4j2完爆logback(网关给的是2G堆内存)但是还是以测试环境为准:
在不输出日志和仅输出400k日志的情况下log4j2的99%,95%相比logback的耗时都有所减少;同样开启异步日志的情况下输出30m日志的99%与95%差距在10倍以上. 对比jvm 对比30M日志输出时的JVM情况:
logback进行了大量的YCG去清理临时的临时变量,而log4j2的变化相对稳定;logback的在异步处理的时候使用的是阻塞队列,日志输出量大导致写盘时间长队列堆积大使得处理日志时间过长;对比线程变化logback线程相对变化大于log4j2. 总结 在线上环境关闭控制台输出会对性能有所提升;相同情况下对比,log4j2性能更优;在对日志输出场景比较多的情况下可以考虑将logback更换为log4j2; 附录 附录一 : logback vs log4j2 附录二 : Sync vs Async 附录三:log4j2特性
异常信息如下 _Could not extract response: no suitable HttpMessageConverter found for response type [java.util.List<java.util.Ma p<java.lang.String, java.lang.Object>>] and content type [application/xml;charset=UTF-8] feign.codec.DecodeException: Could not extract response: no suitable HttpMessageConverter found for response type [java.util.List<java.util.Map<java.lang.String, java.lang.Object>>] and content typ e [application/xml;charset=UTF-8] 原因 服务提供者返回值为xml调用服务者没有对应的HttpMessageConverter 解决方案 // feign api 中设置 produces = "application/json;charset=utf-8" @GetMapping(value = "/path", produces = "application/json;charset=utf-8")
在样式中添加:<Thumb x:Name="PART_RightHeaderGripper"
Cursor="SizeWE" HorizontalAlignment="Right" Width="1"
Height="25"
VerticalAlignment="Center" >
<Thumb.BitmapEffect>
<DropShadowBitmapEffect Color="#000"
Direction="-90" ShadowDepth="2" Softness="0.1" Opacity="0.3" />
</Thumb.BitmapEffect>
</Thumb>
注意:如果x:Name="PART_RightHeaderGripper" 不能用, 试试 x:Name="PART_HeaderGripper" 或 x:Name="PART_LeftHeaderGripper"
例子:XMAL中:
<Style TargetType="DataGridColumnHeader">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="Foreground" Value="#666666" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Height" Value="25"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" Background="#FFFFFF" BorderBrush="#CCCACB" Width="Auto">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Margin="
object T1_highOrder01 { def main(args: Array[String]): Unit = { println("---------------------使用高阶函数------------------") val t2: List[Int] = List(4, 6, 23) val list2: List[Int] = t2.map(c2) println(list2) def c2(i:Int):Int={ i*2 } } } 如上述代码运行抛出: forward reference extends over definition of value list2
原因:方法体不能放在main主函数中,也就是c2不能再main中 改为如下:
object T1_highOrder01 { def main(args: Array[String]): Unit = { println("---------------------使用高阶函数------------------") val t2: List[Int] = List(4, 6, 23) val list2: List[Int] = t2.map(c2) println(list2) //---------------------使用高阶函数------------------ //List(8, 12, 46) } //函数体 def c2(i:Int):Int={ i*2 } }
文章目录 配置账号配置view配置log颜色配置 别名配置命令配置配置文件配置 概念澄清常用命令总结fork操作仓库操作分支操作tag操作查看操作提交操作保存操作撤销操作删除操作重命名操作拯救大魔王忽略文件patch操作 功能总结git统计功能 配置 账号配置 对应的文件为~/.gitconfig or ~/.config/git/config
git config --global user.name test
git config --global user.email test@example.com
git config --list # 查看配置信息
view配置 log颜色配置 [color]
diff = auto
status = auto
branch = auto
interactive = true
ui = true
别名配置 命令配置 git config --global alias.st status git config --global alias.ci commit git config --global alias.br branch git config --global alias.co checkout git config --global alias.pl pull --rebase git config --global alias.
package main import ( "context" "log" "time" "go.etcd.io/etcd/clientv3" ) func main() { var conf = clientv3.Config{ Endpoints: []string{"127.0.0.1:2380"}, DialTimeout: 5 * time.Second, } //创建clinetv3 client, err := clientv3.New(conf) defer client.Close() if err != nil { log.Fatal(err.Error()) } //创建租约 lease := clientv3.NewLease(client) //设置租约时间 leaseResp, err := lease.Grant(context.TODO(), 30) if err != nil { log.Fatal(err.Error()) } //设置续租 leaseID := leaseResp.ID ctx, _ := context.WithCancel(context.TODO()) leaseRespChan, err := lease.KeepAlive(ctx, leaseID) if err !
ListView中的setSelection方法 setSelection使用场景 public void setSelection(int position)
当聊天软件中出现很多消息的时候,会如下图顶端显示还有26条新消息,点击会跳转到最早的未读新消息的位置,这就是setSelection的使用场景
setSelectionFromTop 与setSelection类似 public void setSelectionFromTop(int position, int y)
setSelectionFromTop比setSelection多了一个y参数,就是设置该item与顶端的详细距离。
by function in R
by
Apply A Function To A Data Frame Split By Factors
Function by is an object-oriented wrapper for tapply applied to data frames.
usage
by(data, INDICES, FUN, …, simplify = TRUE) Example
7男3,通过下面的函数可以返回的是:男生的平均年龄,女生的平均年龄by(age, gender, function(x), mean(x))
p <- read.csv('age.csv', header = F) p[1,1]=c("female") colnames(p)=c("Gender","Age") attach(p) aver=by(Age, Gender, function(x) mean(x)) print(aver) Gender: female[1] 27.5 --------------------------------------------------------------------------------------- Gender: male[1] 38.57143
前情提示:
Mac OS10.14;
Windows下已自带,而且新版本Windows有单独RD客户端,RD是一款连接远程桌面的软件,如果连接Linux可以用x she l l等,连接Windows图形界面可以使用微软对的RD。
文章更新说明:
1.RD已经更新到10.3.8(20200302),可以在app store中下载:https://apps.apple.com/app/microsoft-remote-desktop/id1295203466?mt=12
或者在我们要在 HockeyApp 上测试我们预览频道中的新功能。 要看看么? 转到适用于 Mac 的 Microsoft 远程桌面并单击“下载” 。 无需创建帐户或登录 HockeyApp,即可下载 beta 版客户端。
Version 10.3.8 (1747)
Feb 11, 2020 at 01:56
23.24 MB
It's 2020 and time for our first release of the year. The key change in this update is the ability to switch between Scancode (CTRL+COMMAND+K) and Unicode (CTRL+COMMAND+U) modes when entering keyboard input. Unicode mode allows extended characters to be typed using the OPTION key on a Mac keyboard.
adb -s ******** shell
转载于: https://www.cnblogs.com/williamjie/p/9200559.html
此问题出现于使用注解 @RequestParam 时,指定参数映射的问题,若为非必填,设置注解属性:required=false
400错误,Required String parameter 'paramter' is not present
1.就拿简单的登录来说吧,这是开始的代码
@RequestMapping(value="/login")
public ModelAndView login(@RequestParam(“loginname”) String loginname,
@RequestParam("password") String password,
HttpSession session,
ModelAndView mv){
// 调用业务逻辑组件判断用户是否可以登录
User user = hrmService.login(loginname, password);
if(user != null){
// 将用户保存到HttpSession当中
session.setAttribute(HrmConstants.USER_SESSION, user);
// 客户端跳转到main页面
mv.setViewName("redirect:/main");
}else{
// 设置登录失败提示信息
mv.addObject("message", "登录名或密码错误!请重新输入");
// 服务器内部跳转到登录页面
mv.setViewName("forward:/loginForm");
}
return mv;
}
在浏览器中输入localhost:8080/xxx/login,爆出了400,Required String parameter 'paramter' is not present。
2.controller类中,在注解@RequestParam,添加value="paramter",required=false.切记,是false.就OK了。
@RequestMapping(value="/login")
public ModelAndView login(@RequestParam(value="loginname",required=false) String loginname,
一.层级展示 二.dao和domain dao:
domain:
三.jdbcutil jdbcutil:
MyBeanUtil:
四.servlet 五.流程 六.关键代码逻辑 查询:
删除:
添加和修改:
UserServlet:
gitee地址
原创文章,欢迎转载。转载请注明:转载自 祥的博客
原文链接:https://blog.csdn.net/humanking7/article/details/102800059
文章目录 @[toc] 动机原理代码 使用方法声明&鸣谢2020.1.7补充 用Python调用adb抢双十一淘宝喵币
动机 每次都要跟傻子一样等个15秒,真的是劳心劳力,时常变动,网上的脚本都得自己改改适应自己的分辨率,故而写了这篇文章
原理 其实就相当于一个按键精灵,用Python调用adb工具去模拟手指点击,退出事件,没什么科技含量,只是对adb命令的熟悉情况
代码 #!/usr/bin/env python # coding: utf-8 import os import time # ================================================= # 模拟滑动 def initlocal(): time.sleep(2) # 滑动前休息2秒,避免网络不好 os.system('adb shell input swipe 900 1200 900 500') # 模拟从下往上滑动 time.sleep(2) # 滑动后休息2秒,避免开始计时延迟 # ================================================= # 返回上一页面 def goback(): os.system('adb shell input keyevent KEYCODE_BACK') # 返回 time.sleep(2) print('退出') # ================================================= def task_end_1(cnt): print('\n====== 浏览最后一个项目 ======') print('一共[%d]次'%cnt) for i in range(1, cnt+1): os.
百度地图API学习总结(一) 说明 公司项目需要一些关于定位和路线规划的功能,需要在网页中嵌入百度地图,这里主要是做一个记录,记录在开发应用中使用过的API,以便以后查询。
官方文档及参考指南下载 百度地图的官方文档写的很详细,但是内容非常多,并且很多是暂时用不到的,看起来稍微有一些麻烦,但是当你需要查找某些功能时,官方文档又是必不可少的
1.首先进入百度地图开放平台
2.找到 开发 选项,选择合适的平台,我选的Web开发——JavaScript API
3.根据说明,需要先申请秘钥才可以使用
4.然后回到之前的页面,左侧导航,有开发所需的所有资源,包括示例,示例相对来说比较重要,因为对新手来讲,示例对功能体现的更为直接,我一般都是看着示例结合着文档来编写代码的。
5.最后就是关键的文档了,在左侧导航的最下边相关下载中下载最新版本的文档,《开发指南文档》主要是一些入门的介绍和功能的举例,《类参考文档》是API的详细使用指南
开发流程
1.首先获取服务,获取秘钥后,在HTML中引入,如下:
<script src="http://api.map.baidu.com/api?v=2.0&ak=yourAppKey" type="text/javascript"></script>
将秘钥yourAppKey替换成你自己的即可
2.定义一个容器,地图会在定义的容器中显示,这个容器要有确定的宽高,如果是移动端还需要加上meta标签<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <title>标题</title> <link rel="stylesheet" href="./css/app.css"> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=yourAppKey"></script> </head> <body> <div id="app"></div> //容器 <script> // 代码 </script> </body> </html> 3.命名空间
API 使用 BMap 作为命名空间,所有类都在命名空间之下,也就是说无论是创建地图,还是创建一个覆盖物或者控件,都需要使用 BMap.[类],下边是一个简易的地图实例(在上边代码的<script></script>标签中实现)
<body> <div id="app"></div> //容器 <script> // 代码 var map = new BMap.
win10 1809 开启文件共享 ios 的nplayer 报错,connection reset by beer ,在系统功能与选项里面开启如下功能:
Linux之systemd服务配置及自动重启 0 背景 在linux上开发时,往往需要将自己的程序做成服务,并且实现服务开机自动重启,以及服务崩溃后自动重启功能,本文就对该功能的实现做简单介绍,实现方法很简单,使用linux系统的systemd即可实现
1 systemd介绍 历史上,linux的启动一直采用init进程,比如
$ sudo /etc/init.d/apache2 start 或者
$ service apache2 start 这种方法有两个缺点。
一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。
Systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。
根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。使用了 Systemd,就不需要再用init了。Systemd 取代了initd,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。
systemctl是 Systemd 的主命令,用于管理系统。对于用户来说,最常用的是下面这些命令,用于启动和停止 Unit(主要是 service)。
-立即启动一个服务 $ systemctl start apache.service -立即停止一个服务 $ systemctl stop apache.service -重启一个服务 $ systemctl restart apache.service -杀死一个服务的所有子进程 $ systemctl kill apache.service -重新加载一个服务的配置文件 $ systemctl reload apache.service -重载所有修改过的配置文件 $ systemctl daemon-reload -显示某个 Unit 的所有底层参数 $ systemctl show httpd.
广义线性模型 二分类问题的输出,二项分布,
多分类问题的输出,多项分布
回归问题的输出,高斯分布
这些任务都可以表示为广义线性模型
线性模型
y = 1 2 π σ 2 e ( z − μ ) 2 σ 2 , z = θ T x y=\frac{1}{\sqrt{2\pi\sigma^2}}e^{\frac{(z-\mu)^2}{\sigma^2}},z = \theta^Tx y=2πσ2 1eσ2(z−μ)2,z=θTx二分类
y 1 = e − z 1 + e − z , z = θ T x y_1 = \frac{e^{-z}}{1+e^{-z}},z=\theta^{T}x y1=1+e−ze−z,z=θTx多分类
y j = e z j ∑ i e z i , z = θ T x y_j=\frac{e^{z_j}}{\sum_ie^{z_i}}, z=\theta^Tx yj=∑ieziezj,z=θTx 指数族 概率分布函数表达式:
iOSHLS M3U8 自定义AES-128钥匙串或链接解密流程(播放,下载,下载本地后播放) 其实理论上来说苹果支持原生直接播放 AES-128加密的,只要符合苹果的加密标准但是在实际使用过程中,因为有安卓、H5、或者基于已有的接口数据,或是想要自定义钥匙串保密方式,在或者想要加密播放加密链接,加密钥匙串链接,基于以上的种种要求,直接用AVPlay 显然不能满足所有的要求,所以苹果在加入了一个新的Api 用来重定向播放链接。
网上对于HLS 加密的资料比较少,尤其是对加密过后的HLS 链接本地下载,本地播放就更少了,我也是摸着石头过河,这些是我总结的一些资料,和我自己整个的学习过程
1、基础篇:如何播放未加密的HLS M3U8 音频或视频 以下我以音频举例子视频其实一样就是把AVPlayer 的layer 加到View上,网上的例子很多不做赘述
我用的七牛的链接作为测试链接理论来说只要你的播放链接能直接放到safri上播放,那么用AVPlayer也可以正常播放
AVURLAsset * asset = [AVURLAsset assetWithURL:[NSURL URLWithString:@"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"]]; AVPlayerItem * item = [AVPlayerItem playerItemWithAsset:asset]; AVPlayer * player = [AVPlayer playerWithPlayerItem:item]; [player play]; 那么看下未加密的M3u8数据的内容格式
#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=232370,CODECS="mp4a.40.2, avc1.4d4015" gear1/prog_index.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=649879,CODECS="mp4a.40.2, avc1.4d401e" gear2/prog_index.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=991714,CODECS="mp4a.40.2, avc1.4d401e" gear3/prog_index.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1927833,CODECS="mp4a.40.2, avc1.4d401f" gear4/prog_index.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=41457,CODECS="mp4a.40.2" gear0/prog_index.m3u8 音频头包含播放的链接和内容AVPlayer会自动匹配
2、进阶篇:如何播放加密的HLS M3U8 音频或视频 其实加密和未加密的区别主要在于头文件的不同
这个是有关苹果对于标准HLS链接的要求
https://developer.apple.com/documentation/http_live_streaming/about_the_common_media_application_format_with_http_live_streaming?language=objc
如果是标准加密的AVPlayer支持原生播放与上面的播放方式相同
以下我将介绍如何播放非标准加密:例如你的密匙是服务保存一部分本地一部分,或者你的key是加密的钥匙串
这里我以七牛链接作为例子
#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-ALLOW-CACHE:YES #EXT-X-TARGETDURATION:11 #EXT-X-KEY:METHOD=AES-128,URI="
首先先创建包的结构
UserController:
22:30:25
?? 2019/10/27 星期日 22:30:25
@Controller
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("/findAll.do")
public ModelAndView findAll(@RequestParam(defaultValue = “1”) int pageNum, @RequestParam(defaultValue = “5”) int size) {
List users=userService.findAll(pageNum,size);
PageInfo pageInfo=new PageInfo<>(users);
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName(“allUser.jsp”);
modelAndView.addObject(“pageInfo”,pageInfo);
return modelAndView;
}
@RequestMapping("/login.do")
public String login(User user){
Boolean flag=userService.login(user.getUsername(),user.getPassword());
if(flag){
return “redirect:/findAll.do”;
}else{
return “failure.jsp”;
}
}
@RequestMapping("/delete.do")
public String deleteById(int id){
userService.deleteById(id);
return “redirect:/findAll.do”;
}
@RequestMapping("/toUpdate.do")
public ModelAndView toUpdate(int id){
两节课合起来做了Springmvc的查询和删除,首先是创建包的结构:
UserController中的代码:
@Controller
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("/findAll.do")
public ModelAndView findAll() {
List users = userService.findAll();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName(“allUser.jsp”);
modelAndView.addObject(“users”, users);
return modelAndView;
}
@RequestMapping("/login.do")
public String login(User user) {
Boolean flag = userService.login(user.getUsername(), user.getPassword());
if (flag) {
return “redirect:/findAll.do”;
} else {
return “failure.jsp”;
}
}
@RequestMapping("/delete.do")
public String deleteById(int id) {
userService.deleteById(id);
return “redirect:/findAll.do”;
}
@RequestMapping("/addUser.do")
public String addById(User user) {
转载自:http://www.winwin7.com/JC/5552.html
ultraiso也算是老牌的光盘镜像工具了,使用ultraiso来制作U盘启动盘非常简单,在之前的《UltraISO制作U盘启动盘》中就有分享,不过鉴于很多朋友反馈4G以上的系统ISO镜像文件无法制作成U盘启动盘,或不能启动,我们也给大家分享了方法。
ultraiso制作超过4G的系统U盘启动盘教程:
首先准备一个8G以上的U盘(建议)
1、首先,用UltraISO打开ISO文件,将里面大于4G的文件删除(如sources目录下的install.wim),然后将ISO文件另存为一个新文件,注意不要覆盖了原文件!保存;
2、接下来就按正常的方法制作U盘启动盘,启动—写入硬盘映像;
先格式化一下U盘
格式化完成。
写入ISO映像
写入完成后关闭;
3、制作完成后,将U盘转换为NTFS文件系统,方法是:管理员身份运行CMD或快捷键WIN+R,然后输入如下命令convert x: /fs:ntfs(x为U盘的盘符),回车运行即可。
4、解压ISO镜像或者通过UltraISO找到ISO中的sources目录里的install.wim,提取到U盘的原来的目录即可!等待写入完成后就可以使用U盘安装新系统了。
通过上面曲线救国的方法我们顺利完成了4G以上ISO镜像文件的U盘启动盘制作过程。
注意:因为主板BIOS的原因,部分电脑可能需要选择不同的“磁盘主引导记录”,如果遇到不能启动的情况,“便捷启动”选择 “写入新的磁盘主引导记录(MBR)”——USB-HDD+(也可选择USB-HDD、USB-ZIP、HDD等,不行可试试其他的)记录即可!
目录
前言
知识直通车
NEON转置指令
右旋90
4x4矩阵右旋实例
灰度图(单通道)右旋90
彩图(RGB三通道)右旋90
左旋90
4x4矩阵左旋实例
灰度图(单通道)左旋90
彩图(RGB三通道)左旋90 RK3288-linux(硬浮点) 耗时对比
前言 图像旋转就是简单的坐标变换,1080p的图像右旋90度耗时时间,在RK3288-linux(硬浮点)板子上,opencv4.1也就17ms搞定,本没啥好讲的,但是凡事追求极致嘛,能加速的就给他加速一把,当然这态度的问题只是其中一个原因;另外一个原因是最近在公司遇到一个对旋转90的加速需求,在某些场景下,需要做图像旋转然后再送入神经网络做人脸检测,而由于整个人脸识别整个工程的运行导致板子的资源极大消耗,使得简单的图像旋转的时间延长至三四十ms,这是很可怕的,人脸检测也就二三十ms左右吧,所以这是写这篇文章的直接导火索。
当然,类似的利用NEON对矩阵旋转加速的解决方案,网上已经有人发表过了,比如最早的文章https://www.cnblogs.com/hrlnw/p/3723072.html,本篇博客会在此基础上进行扩展,增加RGB彩图的加速旋转代码并补充opencv与本篇算法在RK3288上的旋转耗时数据对比。
知识直通车 矩阵右旋90的NEON加速:https://www.cnblogs.com/hrlnw/p/3723072.html
矩阵右旋180度和270(-90)度:https://www.cnblogs.com/hrlnw/p/3767853.html
opencv右旋90、180、270度:https://www.cnblogs.com/alexYuin/p/9493242.html
opencv利用transpose+flip实现图像旋转,虽然比仿射变换函数warpaffine要快不少,但是分步的做法总是没有一步到位的解决方案来得快的,接下来就开始介绍一步到位法了。
NEON转置指令 可以用neon进行旋转加速的关键要感谢arm出品的vtrn_u8/u16/u32..系列的转置指令,虽然是2x2的转置指令,但是对于矩阵旋转完全够用,取决于怎么用了。
转置的具体情况如下示意,应该很清楚就不多少了
uint8x8_t mat0,mat1; uint8x8x2_t result=vtrn_u8(mat0,mat1); 右旋90 4x4矩阵右旋实例 在介绍图形旋转代码之前先用个小矩阵实例说明一下算法的可行性。先说右旋90度:
旋转前矩阵 旋转后矩阵
算法步骤:
1)相邻两行每2x2做转置(但是注意输入顺序是倒的,比如前两行,第二行作为vtrn的第一个参数输入,第一行作为vtrn的第二个参数输入),结果如下:
原矩阵 相邻行倒置 相邻行转置 2)每行两个像素值看做一个整体,隔行转置,依然倒着输入,即2、0行一组输入,3、1行一组输入,这样便可以得到最终的矩阵旋转结果了,过程如下:
上一步结果 隔行倒置 隔行转置
例子看明白了,那下面图像旋转也就很简单了,soeasy啊~
图像旋转与矩阵旋转的区别就是.....嗯.....图像比较大,下就分块喽,那从指令读取数据的角度以及代码量及速度方面的考虑我们将图像分成8x8的小块矩阵一个一个做旋转然后再放到最终图像相应的位置就可以了。
灰度图(单通道)右旋90 static void rotate_pos90_gray(uint8_t* src, size_t sstep, uint8_t* dst, size_t dstep, int w,int h) { uint8x8x4_t mat[2]; uint8x8x2_t temp8x8x2[4]; uint16x4x4_t temp16x4x4[2]; uint16x4x2_t temp16x4x2[4]; uint32x2x4_t temp32x2x4[2]; uint32x2x2_t temp32x2x2[4]; int dw=w&7; int sw=w-dw; int dh=h&7; int sh=h-dh; for(int y=0;y<sh;y+=8) { uint8_t* pIndexY = src+y*sstep; int tr_x = h-y-8; for(int x=0;x<sw;x+=8) { uint8_t* ptr_y = dst+x*dstep; //load 8x8 matrix mat[0].
零、前提
0.1 配置es
解压文件
tar zxvf elasticsearch-6.2.2.tar.gz 由于es不能用root账户启动,所以需要添加一个非root账户
useradd es 修改es文件夹的权限
chown -R es:es elasticsearch-6.2.2 修改配置文件
vi /usr/local/elasticsearch-6.2.2/config/elasticsearch.yml 修改elasticsearch.yml的内容如下
#端口 http.port: 9200 #IP network.host: 0.0.0.0 #外网IP network.publish_host: 121.41.1.1 http.cors.enabled: true http.cors.allow-origin: "*" #data路径 path.data: /usr/local/elasticsearch-6.2.2/data #logs路径 path.logs: /usr/local/elasticsearch-6.2.2/logs 创建data和logs文件夹
mkdir data logs 启动es(为了方便观察日志没有后台启动)
./bin/elasticsearch 0.2 logstash 配置
解压文件
tar zxvf logstash-6.2.2.tar.gz 进入config文件夹新建logstash-spring.conf文件并编写内容
mkdir logstash-spring.conf vi logstash-spring.conf log4j_es.conf内容
input { tcp { port => 5000 codec => json_lines } } output{ elasticsearch { hosts => ["
转载:http://www.nasyun.com/forum.php?mod=viewthread&reload=true&tid=67700,作者:pipideng
折腾NAS快两周,差点一把火烧了我的NAS,最终还是搞出了我想要的播放分类界面,于是随手整理了一些零碎的经验,涉及kodi+emby组建家庭影音服务,以及关于电影和剧集的整理分类方式。
而对我来说,最重要的是实现电影电视剧的管理和播放目录编排,最好能做到像各种盒子那样的播放目录。
网上的教程大多涉及较专业的内容,我是完完全全的小白,从来没有接触过这块,而且有些内容也不符合我最终的需求,所以试着用最浅白,略带啰嗦的语言(其实是我不专业)分享一下我的做法。
以下同样的设置同样适用于其他客户端,比如电脑、盒子等,在我的测试中,使用了海美迪盒子,安卓7.0的系统,同样安装了kodi+emby,效果还是不错的,但是却不完美支持海美迪的遥控器,不能选择字幕和声道,原本是遥控器按“ok”键,出现暂停、停止,字幕、声道等信息,但是在海美迪的遥控逻辑里,按下ok键是直接暂停影片,然后没得选择,而在后来发现,有emby TV的安卓版,不需要安装kodi,安装后可直接使用,下载安装测试,完美解决遥控器选择信息的问题,顺带解决了其他的细节问题。顺手再提供kodi和emby的安装包吧。 需要用到的材料:
kodi的qpkg安装包,提供一个较新的版本:18.4
Emby server的qpkg安装包,提供一个较新的版本:4.2.1
百度网盘: 游客,如果您要查看本帖隐藏内容请回复
kodi 的apk安装包 版本:18.4
emby TV版的apk安装包 版本:1.7.43
百度网盘: 游客,如果您要查看本帖隐藏内容请回复
过程之中需要在kodi中搜索各类插件在线安装,如果嫌麻烦,可以在 http://www.kodiplayer.cn/plugins/ 选择下载插件包,然后在kodi中进行插件的本地安装。
首先,我对于多终端外网远程访问并没有太大需求,主要是本地播放为主,所以我当初选择的机器是威联通(QNAP)的TS-251+,配置可以满足一般的影音播放管理的需求,初学者玩玩也够了,这东西提供HDMI直连电视,可以直接通过电视播放点播NAS存储的影片,这个对我很重要,并且提供遥控器,也可以手机安装Qremote进行遥控。我的电视机较久远,不是智能电视,不能安装任何第三方软件,虽然也可以在盒子上面装,但没有设备直投来的直接和稳定。当然,使用NAS机器的直连,投放出来的画面效果是比不上各种盒子的,毕竟那些都是专门定制,并且有专门的视屏解码硬件,但其实也在可接受范围。
下面开始正式分享
硬件设备安装好,必备软件安装好,网络连接好,这就不多说了。我在这里主要是影音文件的整理分类,不涉及高级网络等的其他设置
我的设备固件在线更新至4.4.1.1064,安装HybirdDesk Station(HD Station),版本4.0.3,要HDMI投屏必须装。其实系统上本来就可以安装Vedio Station、Music Station等用于管理NAS上的各种资源,然后HD Station上安装HD Player进行播放,虽然HD Player是kodi改头换面的版本,但无奈何,官方出品的太糟糕了,很难用,操作界面实在有点不人道,并且运行速度真的不咋样,最重要的是没办法满足我的分类要求,果断放弃。
首先是在组建的过程中我厘清楚了几个概念,这是我从各种盒子得到的启发,比如我们打开小米盒子,里面可以点播电影电视剧,可以选择,选择后有各级菜单,比如选择电影-->大陆-->剧情-->影片-->显示影片信息,喜欢、想看-->点击播放,这个选择播放逻辑是比较清晰的,而我们在电视上看到的呈现的操作界面就是装在小米盒子上的客户端,对应的就会在后台有服务器端,对各种资源进行管理,小米盒子通过互联网与服务器端相连,自动刷新服务器的数据。
比如添加影片,在服务器端添加上新的影片文件后,通过网络,我们就可以在小米盒子上看到影片更新了。而我就是想要这样的效果,包括点播界面,emby就是这么一个东西,只不过本地播放软件或者说客户端,我选择kodi+emby插件,服务器端用emby server。为什么这么选择,官方普通班免费,并且很多大神已有相关说明,在这再简单说一下,就是kodi利用本地资源解码,速度快,性能好,但是资源管理的功能较差,而他可以安装emby插件,emby的资源管理功能强大,我用过之后感觉确实感觉惊喜。
像我家这样的情况,设备直投电视,播放本地存储在NAS硬盘上的影视资源,服务器端装在哪里?客户端又装在哪里?像我这样的超级无敌小白,只能从最简单的层面去理解。
主机NAS就是一台服务器,管理着硬盘信息,所以,emby server就要装在NAS上,通过你电脑或其他终端登录NAS的Web管理界面安装。kodi是客户端,那么就需要装在HD Station上,其实HD Station就相当于虚拟机,也可以理解为一台单独的设备,比如理解为电视盒子,只不过程序都是装在NAS上,服务端系统和HD Station相互独立,然后kodi这个软件通过HD Station投播到电视上,HD Station这个虚拟机与NAS主机已默认设置好关联连接,所以在本地不需要做特别的网络设置。我是这么理解的,因为我理解的层面也只能到此,不知道哪位有关注的大神们可以再专业点解释。
而其他的客户端一样,比如各种安卓智能电视,安卓盒子等,那么这些就是客户端,服务器端装好后,在这些设备装上相应的客户端就行。
废话一箩筐,接下来开始入正题
一、emby server和kodi的安装
1、 先安装embyserver
在电脑上用浏览器打开NAS的管理页面,选择APP center,打开后,记得是在QNAP Store的选项上,然后点击右上角的手动安装
" lazyloaded="true" _load="1" style="overflow-wrap: break-word; object-fit: cover; max-width: 655px; cursor: pointer;">
" lazyloaded="true" _load="1" style="overflow-wrap: break-word; object-fit: cover; max-width: 655px; cursor: pointer;"
欢迎关注公众号,DataDesigner,让我们一起白话机器学习。
一 、安装环境
Citespace下载网址:citespace官方下载网址,需要提前安装jdk环境(官网也提供)
二、web of science 导出数据
三、citespace操作
将output文件夹中文件复制到data文件夹中,并在主界面指定相对应文件夹
直到屏幕变白为止。