Python字符串定义和使用

1、字符串定义方式 a = 'sumscope' #单引号 b = "sumscope" #双引号 c = 'sums\'cope' #\斜杠代表转义 d = "sums'cope" e = """ #三引号(表示多行输出) 1、poss 2、leader 3、slave """ print(a) print(b) print(c) print(d) print(e) print(type(e)) 2、字符串索引 """ 字符串索引 """ num = "0123456" print(num[0]) print(num[1]) print(num[4]) 3、字符串切片 num = "0123456" print(num[:3]) #打印前3个元素不包含3 print(num[3:]) #打印3后边的元素包含3 print(num[::3]) #打印每间隔3的数字 print(num[1:3]) #打印1到3的数字包含1 print(num[:]) #表示打印全部 print(num[-1]) #表示打印最后一个 print(num[::-1]) #逆向打印 4、重复、连接 a = "yes" * 5 print(a) b = "hello" + "

Microsoft.Xaml.Behaviors.Wpf 的使用

System.Windows.Interactivity.WPF这个已经过时,可以使用 Microsoft.Xaml.Behaviors.Wpf ,基本使用查不多, <Window x:Class="TestLoad.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TestLoad" xmlns:behaviour="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" > <behaviour:Interaction.Triggers> <behaviour:EventTrigger EventName="Loaded"> <behaviour:InvokeCommandAction Command="{Binding TestCommand}"/> <behaviour:CallMethodAction MethodName="TestMethod"/> </behaviour:EventTrigger> </behaviour:Interaction.Triggers> <Grid> </Grid> </Window> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace TestLoad { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.

Typora卡顿如何解决

Typora真的好用,但是过了1万字之后就很卡。 解决办法 1.点击文件 文件 2.点击偏好设置 偏好设置 3.将自动保存关掉,亲测有效缓解卡顿,最下面的使用国内服务器也可以勾选上

巧用设计模式实现ETCD客户端自动重连方案

一、背景介绍 之前在设计开发自动限流计数集群系统时,使用了ETCD来实现服务协调和集群选举。去年公司在做断网演练期间发现,ETCD客户端在和服务端断开连接之后,没有办法自动重新连接服务,恢复业务。具体表现如下图,机器心跳正常,但在ETCD上注册的服务离线。 于是需要设计实现ETCD客户端与ETCD服务端的自动重连功能。确保在任何网络闪断或者网络临时中断的情况下,ETCD客户端能够在一定时间内自动注册到ETCD服务端,恢复服务。 本文将和大家分享如何通过代理模式和观察者模式优雅的实现该自动重连方案。 二、知识回顾 在介绍具体方案前,咱们先将本文中涉及到的知识点和大家一起做一个简单的回顾。这些知识点本文不会深入讲解,如果需要深入学习研究,请查询相关文档。 1、ETCD客户端基本实现 首先咱们回顾下ETCD客户端的基本实现。 如上ETC客户端常规使用类图,ETCD客户端持有实现了多个功能客户端,如KvClient、LeaseClient、WatchClient和ElectionClient等等。在实际业务开发过程中,这些客户端会被业务代码(如上图的ElectionBusinessClass和CacheBusinessClass)持有并使用。通常业务代码在初始化(上图中的init方法)的时候就会调用EtcdClient获取到自己需要的功能客户端,并保存到自己的私有域中。后续再执行相关操作时,直接使用自己持有的功能客户端类实现具体业务即可。 2、相关设计模式 本文方案中将使用到的两个设计模式都是比较普通的设计模式,咱们在实际开发过程中应该也经常使用。这里咱们也一起做一个简单的回顾。 A、代理模式(Proxy) 代理模式就是指咱们开发的Proxy代理人接管(代替)了实际功能类的工作。在具体方法执行的过程中,业务直接调用代理类实现业务。但代理类在执行方法时,是否会调用具体功能类的相应方法去实现业务,则由代理类根据自己的设计实现决定。下面,咱们从一个实际开发过程中常用的缓存开发设计的功能来回顾代理模式如何工作。 假设咱们有个ClientInfoFetcher接口,其定义根据名称获取客户端信息的功能。咱们有个实现类ClientInfoFetcherImpl,它通过从数据库查询实现了ClientInfoFetcher接口的功能。另外咱们有个业务类BusinessClient,它需要根据ClientInfoFetcher接口提供的功能查询出客户端信息,并在界面打印出来。 假设上述业务并发量大,咱们需要考虑缓存。为了能有良好的架构和优雅的设计,这里我们使用代理模式来实现该缓存功能。如上缓存功能类图。咱们定义一个代理类ClientInfoFetcherProxy。在业务类BusinessClient中,咱们构建出一个ClientInfoFetcherProxy来实现客户端信息获取功能。在业务执行时,代理类中如果有缓存,则不调用底层具体功能类ClientInfoFetcherImpl实现业务;反之如果没有缓存,则代理类则需要调用底层具体功能类来实现相应的业务。且执行成功之后会将结果缓存到代理类中。 代理模式的回顾咱们就到这里,接下来咱们再一起回顾下一个设计模式:观察者模式。 B、观察者模式(Observer) 观察者模式中,当被观察的对象状态变化时,其会通知所有的观察者执行相应的业务逻辑。这个模式应该是大家在实际开发过程中使用很多的一种设计模式。平时常用的listener就是一种观察者模式。下面咱们通过listener的设计一起来回顾下观察者模式。假设咱们有个客户管理系统。当系统启动成功后,我们要加载客户信息到系统中。加载完毕后,咱们需要通知商品模块,消息模块和权限模块做相应的业务处理。 如上实现类图。咱们定义了一个监听器接口CustomerLoadedListener(观察着模式中的观察者),当客户信息(ClustomerInfo)加载完毕之后负责处理具体业务。由于咱们的商品模块、消息模块和授权模块都需要在客户端信息加载完毕之后处理消息,所以他们分别都是实现接口CustomerLoadedListener,以此来处理各自的业务。咱们得CustomerCacheLoader则负责所有的客户端信息加载和通知操作。所以咱们实例化时会将AuthorityModuleListener、MessageModuleListener和ProductModuleListener三个观察者都添加到CustomerCacheLoader实例中。当咱们系统启动后CustomerCacheLoader负责将客户信息加载到内存中,并调用所有观察者的loaded方法通知大家被观察事件发生变化。 通过一个简单的例子和大家一起回顾了下观察者模式。接下里咱们回到本文的主题,一起看看在实际开发过程中会如何实现ETCD的自动重连功能。 三、实现方案 1、普通方案实现 A、基本实现 其实要实现Etcd客户端自动重连很简单。只需要在调用客户端方法异常之后,重新创建Client(Etcd)实体类与ETCD Server端建立连接即可。但是由于Client客户端还有多个功能客户端(如:KvClient、LeaseClient等),所以我们重新创建Client(Etcd)实例之后,必须让所有的关联功能客户端全部重新通过Client(ETCD)实例化。大致流程如下图,当业务调用功能客户端kvClient.get异常后,其让EtcdClient销毁原有的客户端,然后与服务端重新建立连接并创建新的客户端。接着业务类再调用新的EtcdClient获取到新的功能客户端kvClient。最后业务类使用新的功能客户端进行相应的业务操作即可。 PS:如何判断客户端需要重连,可以有很多实现手段。比如,咱们可以循环调用功能客户端功能(如kvClient.get),超过三次失败,则认为客户端连接断开,需要重连。大家想想还有其他什么处理方法呢? B、进阶设计 上述基本方案中随意可以实现自动重连,但是却存在一个问题。当ETCD客户端重连成功后,业务类需要重新调用新的ETCD客户端创建自己需要的功能客户端。在上述方案中,咱们只考虑了一个业务类。如果有多个业务类,咱们又怎么实现呢?如下图当有多个业务类都使用了ETCD的功能客户端。由于业务类1主动发起了ETCD客户端重连,所以它肯定能够知道需要重新去获取最新的功能客户端。但业务类2和业务类3,它们对ETCD客户端已经重连完成无感知,所以他们持有的功能客户端仍然和旧的ETCD链接关联,此时已经无法使用(旧ETCD客户端连接已经销毁)。那么在这种情况下,咱们如何通知业务类2和业务类3客户端已经重连了呢? 提到通知,咱们自然就能想到了观察者模式。所以这里我们可以定义一个观察者,让所有需要使用ETCD的业务类都实现该观察者。在实例化的之后,全部将自己注册到EtcdClient中。当EtcdClient重连完成后,它就可以一一通知这些观察者“ETCD客户端重连”这个事件。观察者在收到事件通知后,就能用新的EtcdClient去获取自己需要的新的功能客户端,比如业务类2会通过etcdClient.getElectionClient获取electionClient;业务类3会通过etcdClient.getWatchClient获取watchClient。这样所有的业务类在ETCD重连之后,都能够及时恢复业务。 该实现方案的类图如下(图中只画了CacheBusinessClass业务类的完整类关系图,ElectionBusinessClass业务类似,大家对比理解即可): C、存在的问题 通过上面的设计我们已经完全解决了ETCD客户端无法重连的问题。同时我们还巧妙的使用了观察者模式。这个方案看起来挺高级,但却存在如下一些问题。 a、底层设计不够优雅,底层代码入侵业务代码 业务在使用ETCD客户端的时候,需要自己实现观察者接口。以此来重新获取ETCD的功能客户端。这样就相当于底层代码入侵了业务代码。 b、业务使用底层组件学习成本增加 业务在使用ETCD客户的时,需要额外注入实现观察者接口。这对于业务来存在额外的学习成本,新业务开发需要学习为什么需要这个观察者接口、如何实现这个接口,以及如何注册该观察者接口。 c、开发成本会随业务类的增加而增加 每个使用到ETCD客户的业务类,都需要实现并注册该观察者接口。这个部分额外的工作就会随着使用业务类的增加而增加。 D、底层设计基本原则 上述咱们说了那么多问题,那么一个良好的底层(组件、框架等)设计到底应该是怎样的呢?楼主认为一个良好的底层设计需要具备如下特点: a、对业务代码无侵入 b、不额外增加业务开发的学习成本和开发工作量 那么咱们要怎样设计实现,才能在满足上述基本原则基础上,实现ETCD客户端自动重连方案呢?接下来,咱们就一起看看吧。 2、优雅方案实现(设计模式) A、方案介绍 其实在上述方案设计实现过程中,咱们已经理清楚了ETCD客户端自动重连方案的基本思路。首先,在使用功能客户端实现业务时,如果发生异常,需要触发ETCD客户端重新连接。接着重连成功之后,需要通知所有的功能客户端重新通过ETCD客户端创建实例。我们要做的不侵入业务代码,且不给业务开发增加额外的学习成本。那么咱们就必须要保证对于业务使用者来说,其使用ETCD的功能和原生ETCD没有任何区别。即其需要使用原始的接口来实现业务功能。但咱们又需要在方法底层做一些额外操作(重连),此时我们自然能够想到代理模式能帮助咱们实现这样的能力。因此我们需要暴露给业务使用者一个ETCD业务客户端的代理即可。这样对应业务来说,使用没有任何变化。但咱们可以在代理中执行咱们需要的操作。 B、方案实现 PS:1、图中只缓存了KVClient的代理+观察者实现,其他功能客户端(LeaseClient、WatchClient等)类似。2、类图中EtcdClientProxy和RestartedListener之间的关系使用的重数性关联。其实很多书籍都用的聚合(代理模式类图)。小伙伴们思考下,这里到底用怎么表示比较好呢? 整体方案实现的类图如上。其中红色框中的类,则是咱们这个方案使用的设计模式涉及的关键类。 RestartedListener观察者接口,定义了ETCD客户端重启之后的通知方法etcdRestarted。所有观察者实现类,需要注册到EtcdClientProxy(被观察者)中。 EctdClientProxy代理类,其实现了EtcdClient因此其对外提供了和EtcdClient相同的功能。内部其代理了真实的Etcd客户端实现类ClientImp。同时其它内部持有了所有的观察者接口RestartedListener。即所有的观察者实例化之后,都需要注册(addListener)到其中。最后其提供了restart功能,让使用者可以调用该功能重启(重新连接)Etcd客户端连接。重启完成后,Proxy则会调用所有RestartedListener通知所有观察者。 KvClientProxy代理类,其为KvClient功能客户端的代理。它和普通KvClientImpl实现类一样实现了KV接口,但其底层通过代理的方式实现了所有接口方法。最终都是调用KvClientImpl类的实例实现真实的KV功能。同时该Proxy本身实现了RestartedListener,即也是一个观察者。当ETCD客户端重启后,它可以获得通知,重新利用新的EtcdClient获取到最新的功能客户端KvClient。另外,该Proxy代理了所有的KV业务功能,在执行业务时,它会通过异常捕获来判断Etcd客户端是否断开连接,如果断开,则调用EtcdClientProxy.restart方法,让ETCD客户端重新连接。等ETCD客户端连接成功之后,且自己重新获取到新的功能客户端(KvClient)之后,再继续调用真实的KvClientImpl的实例执行真正的业务。 为了方便大家理解,咱们再看看下面的流程图。其大致步骤如下: 1、业务发起请求,业务类CacheBusinessClass承接业务,向KvClientProxy代理类请求获取Value。 2、KvClientProxy代理尝试调用被代理类KvClientImpl获取Value。 3、KvClientProxy代理执行异常之后,直接调用EtcdClientProxy代理重启客户端。 4、EtcdClientProxy代理调用被代理类ClientImpl重启客户端(重新创建一个实例,关闭旧实例)。 5、EtcdClientProxy代理重启客户端完成后,通知所有观察者。 6、KvClientProxy观察者收到通知后,重新调用EtcdClientProxy获取KVClient。 7、EtcdClientProxy代理会调用新的客户端获取KvClient功能客户端。 8、KvClientProxy获取最新KVClient成功后,继续用新的KvClient执行业务get,并返回结果。 9、CacheBusinessClass获取到返回结果,并返回给业务方。 3、方案优劣势 A、优势 通过该方案咱们能比较尤雅的实现整个ETCD客户端自动重连(重启方案)。其优势主要如下: a、整个重启过程,对业务类(CacheBusinessClass)完成无感知。底层代码对业务类完全无侵入。 b、业务使用方(CacheBusinessClass)没有任何额外学习成本。其只需要知道如何使用标准ETCD接口和功能即可。 c、采用设计模式让整个代码设计变得更加优雅、简洁。 B、劣势 上面说了很多优势,其实整个方案还是有它的不足之处。

海康工业相机使用教程

工业相机使用 一、硬件连接1、准备材料2、相机供电(1)区分电源适配器正负极(2)连接相机电源线缆(3)连接完成后,相机蓝色灯常亮则成功 3、软件连接(1)MVS客户端下载地址(下载3.4.3windows)(2)打开安装包默认安装即可(3)双击MVS图标打开客户端软件 一、硬件连接 1、准备材料 准备材料:工业相机、镜头、电源适配器、千兆网线、相机电源线缆 2、相机供电 (1)区分电源适配器正负极 1. 电源适配器连接电源 2. 万用表打开直流模式 3. 电源适配器连接万用表两端 4. 显示12v时,万用表红线连接的为电源适配器正极 5. 显示负数时,交换连接,直到显示12v左右 (2)连接相机电源线缆 电源适配器正极连接相机电源线缆橙色线,负极连灰色线 (3)连接完成后,相机蓝色灯常亮则成功 3、软件连接 (1)MVS客户端下载地址(下载3.4.3windows) MVS客户端官网下载 (2)打开安装包默认安装即可 (3)双击MVS图标打开客户端软件 1. 等10s左右,左侧栏出现相机信息,双击打开 2. 打开后点继界面中间上方开始,显示实时图像 3. 若出现画面暗,调节曝光度为连续即可 4. 可根据自己需求调整相机参数

【Android系统源码修改】OTG U盘插入后,直接弹出指定APP

需修改 vendor/mediatek/proprietary/frameworks/base/storage/java/com/mediatek/storage/StorageDefaultPathDialog.java 在创建对话框之前,调用指定APP,并注释对话框的生成(此对话框是询问用户是否切换默认存储器) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG,"StorageDefaultPathDialog onCreate()"); mSDCardStateFilter = new IntentFilter(SD_ACTION); mSDCardStateFilter.addDataScheme("file"); mReceiver = mSDStateReceiver; mInsertOtg = getIntent().getBooleanExtra(INSERT_OTG, false); // createDialog(); /** 添加: 打开指定APP */ PackageManager manager = getPackageManager(); Intent intent = manager.getLaunchIntentForPackage("com.xxx.xxx"); // 应用包名 if (intent != null) { try { startActivity(intent); } catch (Exception e) { Log.d(TAG, "Exception:" + e.getMessage()); } } finish(); }

mysql添加ROW_NUMBER写法记录

select cs_id,user_id, count(1)as sl, ROW_NUMBER() OVER(ORDER BY cs_id asc, count(1) desc) as rownumber from sys_customer_mx where shenhe_state=1 group by cs_id,user_id order by cs_id asc,sl desc

Ubuntu环境下利用Stress对CPU进行满载及半载压力测试

文章目录 1.概述2.strss工具的使用2.1 CPU满载2.2 CPU半载 3.htop工具的使用4.总结 1.概述 下文主要介绍在Ubuntu环境下,stress工具以及htop工具在CPU压力测试中的应用,以树莓派4B作为实操示例。 2.strss工具的使用 2.1 CPU满载 (1)安装stress工具时,只需要打开终端,输入如下命令: sudo apt-get install stress (2)使用stress工具时,本次使用的开发板时树莓派4B,为了使其达到满载状态,首先需要知道自己开发板的CPU有多少个核心,在网上查到相关的处理器参数如下图: 从上图的信息来看,树莓派4B处理的核心数是4,当然也能通过命令自行查看CPU的核心数,我们仅需用如下命令: cd /sys/devices/system/cpu 此时我们就进入到了CPU所在的目录,使用ls命令后,可以在该目录下看到该处理器拥有的CPU核心,如下图: 这里也就确认我们该处理器,确实拥有4个CPU核心,此时我们为了4个CPU核心都处于满载状态,只需要使用如下命令: stress --cpu 4 运行该命令后,四个CPU将进入满载状态。 2.2 CPU半载 CPU半载测试,我依旧使用的Stress工具,因为上面提到树莓派4B有四个核心,我的思路是让4个核心两两交替处于满载状态,这里就需要准备一个脚本,交替的使能和禁用其中两个核心,具体实现如下: (1)新建一个文件 touch test (2)编辑新建的文件 nano test (3)将下面的内容添加到test中 #!/bin/bash while [ 1 ] do echo 1 > /sys/devices/system/cpu/cpu0/online echo 1 > /sys/devices/system/cpu/cpu1/online echo 0 > /sys/devices/system/cpu/cpu2/online echo 0 > /sys/devices/system/cpu/cpu3/online sleep 2 echo 1 > /sys/devices/system/cpu/cpu2/online echo 1 > /sys/devices/system/cpu/cpu3/online echo 0 > /sys/devices/system/cpu/cpu0/online echo 0 > /sys/devices/system/cpu/cpu1/online sleep 2 done *通过给每个核心下的online位写0和写1,实现对CPU对应核心的使能和禁用

联系互联网和汽车的纽带:国内车载小程序市场现状和发展趋势

随着智能汽车的普及和发展,车载小程序已成为汽车信息娱乐的一种新方式。车载小程序可以为驾驶员和乘客提供更加智能化、便捷的交互方式,让人们在驾车过程中享受更加丰富的服务。本文将从车载小程序的使用环境、用户体验、应用场景、未来趋势以及国内车载小程序厂商的发展现状等方面进行详细阐述。 一、使用环境 车载小程序是指在车载系统上运行的小程序,一般需要车辆内置支持的操作系统作为平台。目前市面上主流的车载操作系统包括车载 Android 系统、CarPlay、Baidu CarLife、华为 HiCar 等。在使用车载小程序之前,车主需要先将手机与车载系统连接,通过手机端将需要的应用下载到车载系统中。车载小程序相比于传统应用的优势在于更加便捷、实用,驾驶员可以更加方便地获取路况、气象信息等实时数据,同时也可以更加便捷地使用音频、视频等多媒体服务。 二、用户体验 车载小程序的用户体验是衡量车载小程序质量的重要指标。良好的用户体验可以提高用户对车载小程序的满意度和使用率。在设计车载小程序时,需要注意以下几点: 1、界面设计简单明了 车载小程序的界面设计需要简单明了,易于操作。在车辆行驶时,驾驶员需要时刻保持对路况的关注,因此车载小程序的界面不能过于繁琐复杂,最好采用大按钮、简单图标等方式进行设计,使驾驶员一目了然。 2、功能设计合理 车载小程序的功能设计需要合理,满足用户需求。在车辆行驶时,驾驶员需要快速获取相关信息,车载小程序需要提供实时、准确的数据,如路况信息、天气信息、油耗等。同时,车载小程序还可以提供音频、视频等娱乐服务,为乘客提供更加舒适的体验。 3、语音识别交互友好 车载小程序需要支持语音识别交互,以方便驾驶员的使用。在车辆行驶时,驾驶员需要保持双手在方向盘上,因此语音识别交互可以大大提高驾驶员的使用便利性。同时,车载小程序的语音识别交互需要友好、智能,可以识别驾驶员的语音指令,并且给出相应的回复和操作提示,以提高用户体验。 三、应用场景 车载小程序可以在车辆驾驶过程中为驾驶员和乘客提供多种服务。以下是几种常见的应用场景: 1、路况导航 车载小程序可以通过地图服务提供实时的路况信息和导航服务,让驾驶员更加方便地规划路线,避免拥堵和堵车。 2、天气预报 车载小程序可以通过天气服务提供实时的天气信息和预报,让驾驶员和乘客了解当前和未来的天气状况,提前做好准备。 3、油耗查询 车载小程序可以通过车载系统提供实时的油耗数据和油耗统计分析,让驾驶员更加方便地掌握车辆燃油消耗情况,提高驾驶经济性。 4、娱乐服务 车载小程序可以提供音频、视频等多媒体服务,为乘客提供更加丰富的娱乐体验,缓解驾驶员和乘客的疲劳感。 四、未来趋势 随着智能汽车的不断普及和发展,车载小程序也将会有更加广泛的应用。以下是几种可能的未来趋势: 1、智能化程度提高 车载小程序将会更加智能化,可以通过数据分析和机器学习等技术,为驾驶员和乘客提供更加个性化、智能化的服务。 2、应用场景更加丰富 车载小程序将会在更加广泛的场景中应用,如智能停车、远程车辆控制、车辆保险等,为驾驶员和乘客提供更加便捷的服务。 3、与其他服务的融合 车载小程序将会与其他服务进行更加紧密的融合,如智能家居、在线支付等,为用户提供更加便捷的服务体验。 五、国内车载小程序厂商的发展现状 目前,国内的车载小程序厂商主要有百度、阿里巴巴、腾讯等互联网公司,以及车厂自身研发的车载系统。以下是几家国内车载小程序厂商的发展现状: 百度 百度的车载系统 CarLife 已经与多个汽车品牌合作,支持百度地图、百度音乐、百度 AI 等车载小程序,为用户提供多样化的服务。在用户体验方面,百度在 CarLife 中加入了语音交互、手势控制等功能,提高了用户的使用体验。 阿里巴巴 阿里巴巴的车载系统 AliOS Car 已经与多个汽车品牌合作,支持支付宝、高德地图、淘宝、天猫等车载小程序。阿里巴巴还推出了自己的 AI 语音助手 Tmall Genie,可以通过语音指令操作车载系统。在用户体验方面,阿里巴巴加入了手势识别、全息显示等功能,提高了用户的使用体验。 腾讯 腾讯的车载系统 TAI 融合了腾讯的音乐、视频、聊天、游戏等车载小程序,支持腾讯地图、微信、QQ 等服务。在用户体验方面,腾讯加入了语音识别、手势控制等功能,提高了用户的使用体验。 车厂自身研发 除了互联网公司,许多车厂也在自身研发车载系统和车载小程序。例如比亚迪的 DiLink 系统、长城汽车的 WEY Smart 3.0 系统等。这些车载系统和车载小程序也具有丰富的功能,如车辆控制、智能停车、远程控制等,提供了更加个性化、智能化的服务。 第三方服务商 为了帮助车企都能拥有自己的车联网小程序生态圈,FinClip 小程序容器技术目前在一些车载设备领域也广受欢迎 ,FinClip 可以让各种 IOT 终端设备(智能车载、智能电视、智能手表等)快速具备运行小程序的能力。

【t-SNE可视化CNNs特征向量-代码】

t-SNE可视化CNNs特征向量-代码 本博客主要是自己学习记录,参考网络,欢迎指正 整体代码 ModelPath是存放训练好的模型参数的路径 DatasetPath是存放数据集的文件夹的路径,其中不同类别放在不同的子文件夹里 也可以参考【t-SNE可视化-代码】 import os import torch as t from torch import nn from torch.utils.data import DataLoader as DL from torch import optim import torchvision.datasets as datasets from torchvision import transforms as T import torchvision.models as models import numpy as np import matplotlib.pyplot as plt from sklearn.manifold import TSNE from Config.config import ConfigCLS from Classification.Dataset.ChestXRayCLS.chestxray import ChestXRay from Classification.Dataset.RefugeCLS.refuge import REFUGE from Classification.TrainFunc.runner import NetRunner ModelPATH = 'resnet18/checkpoint/best_f1score.

多线程 | FutureTask实践

FutureTask是多线程编程中经常用到的一个类,在线程池中,它常常以 executor.submit() 方法调用,它返回了一个Future对象,从而实现了多线程编程中获取异步结果的一种途径。 FutureTask是一个封装了任务的类,可以理解成是Runnable/Callable的包装类。原生的Runnable/Callable都是同步执行,FutureTask像是一个单独的容器,通过持有任务的成员变量,并获取执行该任务的线程,让任务在这FutureTask中运行,然后将运行结果存放在容器中。调用者可以在不同的阶段获取这个结果。 1、线程池创建 public class ThreadPoolUtils { //可用处理器的Java虚拟机的数量 private static int CORE_SIZE = Runtime.getRuntime().availableProcessors(); private static int CORE_MAX_SIZE = Runtime.getRuntime().availableProcessors()*2; // volatile 保证线程的存可见性 private static volatile ExecutorService executorService ; private static ExecutorService getInstance(){ synchronized (ThreadPoolUtils.class){ if(executorService == null){ synchronized (ThreadPoolUtils.class){ return executorService = new ThreadPoolExecutor(CORE_SIZE, CORE_MAX_SIZE , 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); } } return executorService; } } public static void submit(Runnable runnable) { getInstance().submit(runnable); } public static <T> Future<T> submitCall(Callable<T> callable) { return getInstance().

Redis基础数据类型和命令

1、Redis通用命令 通用指令是部分数据类型的,都可以使用的指令,常见的有,通过help [command] 可以查看一个命令的具体用法: KEYS:查看符合模板的所有key,匹配查询的所有的KEY,可以使用通配符 * ? [] ,不建议在生产上面使用这个命令,会阻塞进程。*模糊匹配、?匹配一个字符、[]匹配括号里面的字符 。 DEL:删除一个指定的key。 EXISTS:判断key是否存在。 EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除。 TTL:查看一个KEY的剩余有效期。 2、String类型 字符串类型是Redis中最基本的存储类型【key-value】,value根据字符串的格式不同分为3类: string:普通字符串。 int:整数类型,可以做自增、自减操作。 float:浮点类型,可以做自增、自减操作。 String类型是二进制安全的,意思是redis的string可以包含任何数据,不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大默认空间不能超过512m。 内部实现 String 类型的底层的数据结构实现主要是 int 和 SDS(简单动态字符串)。 SDS 和我们认识的 C 字符串不太一样,之所以没有使用 C 语言的字符串表示,因为 SDS 相比于 C 的原生字符串: SDS 不仅可以保存文本数据,还可以保存二进制数据。因为 SDS 使用 len 属性的值而不是空字符来判断字符串是否结束,并且 SDS 的所有 API 都会以处理二进制的方式来处理 SDS 存放在 buf[] 数组里的数据。所以 SDS 不光能存放文本数据,而且能保存图片、音频、视频、压缩文件这样的二进制数据。 SDS 获取字符串长度的时间复杂度是 O(1)。因为 C 语言的字符串并不记录自身长度,所以获取长度的复杂度为 O(n);而 SDS 结构里用 len 属性记录了字符串长度,所以复杂度为 O(1)。 Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。因为 SDS 在拼接字符串之前会检查 SDS 空间是否满足要求,如果空间不够会自动扩容,所以不会导致缓冲区溢出的问题。

【Unity】 PlayerPrefs 保存本地数据和持久化用法

unity3d提供了一个用于本地持久化保存与读取的类——PlayerPrefs。工作原理非常简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值。 PlayerPrefs类支持3中数据类型的保存和读取,浮点型,整形,和字符串型。 分别对应的函数为: SetInt();保存整型数据; GetInt();读取整形数据; SetFloat();保存浮点型数据; GetFlost();读取浮点型数据; SetString();保存字符串型数据; GetString();读取字符串型数据; 这些函数的用法基本一致使用Set进行保存,使用Get进行读取。 PlayerPrefs.SetString("_NAME", set_NAME); 这个方法中第一个参数表示存储数据的名称,第二的参数表示具体存储的数值。 get_NAME=PlayerPrefs.GetString("_NAME"); 这个方法中第一个数据表示读取数据的名称,本来还有第二的参数,表示默认值,如果通过数据名称没有找到对应的值,那么就返回默认值,这个值也可以写,则返回空值。 在PlayerPrefs 类中还提供了 PlayerPrefs.DeleteKey (key : string)删除指定数据; PlayerPrefs.DeleteAll() 删除全部键 ; PlayerPrefs.HasKey (key : string)判断数据是否存在的方法;

漏洞介绍及修复建议(漏洞汇总,建议收藏后期会不断更新)

目录 未分类 Host 头攻击(高危) 域名访问限制不严格(高危) URL 重定向(中危) 会话劫持漏洞(中危) 会话固定漏洞(中危) DNS 域传送漏洞(中危) 检测到网站被黑痕迹(高危) 传输层保护不足漏洞(中危) 服务器启用了 TRACE Method 方法 (中危) 点击劫持漏洞(X-Frame-Options 头缺失)(中危) 启用了不安全的 HTTP 方法(启用了 OPTIONS 方法)(中危) Tomcat 版本过低漏洞 (中危) Apache Tomcat 示例目录漏洞 (中危) SpringBlade 框架默认 SIGN_KRY 秘钥(CVE-2021-44910)(高危) SSL/TLS 服务器 Diffie-Hellman 公共密钥过弱漏洞(高危) OpenSSL 远程内存泄露漏洞(心脏滴血漏洞)(高危) Apache apisix 默认密钥漏洞(CVE-2020-13945)(高危) 弱口令登录类 弱口令(高危) FTP 弱口令(高危) 任意用户密码重置漏洞(高危) 验证码漏洞(高危) 暴力破解漏洞(中危) 短信轰炸漏洞(中危) 用户名猜解漏洞(中危) SNMP 默认团体名漏洞(高危) 敏感信息泄漏 源码信息泄漏(高危) 错误页面信息泄露(应用程序错误信息)(中危) 目录遍历(高危) IIS 短文件名漏洞(中危) robots.txt 文件泄露(中危) PHP 探针信息泄露(中危) PHPINFO 页面泄露(中危) 未加密的登录请求(低危)

跨平台桌面应用的开发框架——Electron

一、背景 在团队中,我们因业务发展,需要用到桌面端技术,如离线可用、调用桌面系统能力。什么是桌面端开发?一句话概括就是:以 Windows 、macOS 和 Linux 为操作系统的软件开发。对此我们做了详细的技术调研,桌面端的开发方式主要有 Native 、 QT 、 Flutter 、 NW 、 Electron 、 Tarui 。其各自优劣势如下表格所示: 我们最终的桌面端技术选型是 Electron ,Electron 是一个可以使用 Web 技术来开发跨平台桌面应用的开发框架。 其技术组成如下: Electron = Chromium + Node.js + Native API 各技术能力如下图所示: 整体架构如下图所示: Electron 是多进程架构,架构具有以下特点: 由一个主进程和 N 个渲染进程组成主进程承担主导作用,用于完成各种跨平台和原生交互渲染进程可以是多个,使用 Web 技术开发,通过浏览器内核渲染页面主进程和渲染进程通过进程间通信来完成各种功能 这里说下 Electron 进程间通信技术原理: electron 使用 IPC (interprocess communication) 在进程之间进行通信,如下图所示: 其提供了 IPC 通信模块,主进程的 ipcMain 和渲染进程的 ipcRenderer。 从 electron 源码中可以看出, ipcMain 和 ipcRenderer 都是 EventEmitter 对象,源码如下图所示: 看到源码实现,是不是觉得 IPC 不难理解了。知其本质,方可游刃有余。

《PyTorch深度学习实践9》——卷积神经网络-高级篇(Advanced-Convolution Neural Network)

一、 1 ∗ 1 1*1 1∗1卷积 由下面两张图,可以看出 1 ∗ 1 1*1 1∗1卷积可以显著降低计算量。 通常 1 ∗ 1 1*1 1∗1卷积还有以下功能: 一是用于信息聚合,同时增加非线性, 1 ∗ 1 1*1 1∗1卷积可以看作是对所有通道的信息进行线性加权,即信息聚合,同时,在卷积之后可以使用非线性激活,可以一定程度地增加模型的表达能力;二是用于通道数的变换,可以增加或者减少输出特征图的通道数。 二、Inception Module Inception V1首次使用了并行的结构。每个Inception块使用多个大小不同的卷积核,与传统的堆叠式网络每层只用一个尺寸的卷积核的结构完全不同。 Inception块的多个不同的卷积核可以提取到不同类型的特征,同时,每个卷积核的感受野也不一样,因此可以获得多尺度的特征,最后再将这些特征拼接起来。同时,为了降低计算成本,可以使用 1 ∗ 1 1*1 1∗1卷积进行降维。 import torch import torch.nn as nn from torchvision import transforms from torchvision import datasets from torch.utils.data import DataLoader import torch.nn.functional as F import torch.optim as optim # prepare dataset batch_size = 64 transform = transforms.Compose([transforms.ToTensor(), transforms.

按键修改阈值功能、报警功能、空气质量功能实现(STM32)

按键修改阈值功能 要使用按键,首先要定义按键。通过查阅资料,可知按键的引脚如图所示:按键1(S1)通过KEY0与PA0连接,按键2(S2)通过KEY1与PE2连接,按键3(S3)通过KEY2与PE3连接,按键4(S4)通过KEY3与PE4连接。 key.c 这段代码主要是对四个按键进行了初始化配置,使其能够进行读取输入操作。 #include "key.h" void Key_Init() { GPIO_InitTypeDef GPIO_InitStructure; /*四个按键*/ /* GPIOA 引脚的时钟使能 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* 配置PA0引脚为输出模式 s1*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //配置的引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度为100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上下拉电阻:无上下拉电阻 GPIO_Init(GPIOA, &GPIO_InitStructure); /* 配置PE2引脚为输出模式 s2*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //配置的引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度为100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上下拉电阻:无上下拉电阻 GPIO_Init(GPIOE, &GPIO_InitStructure); /* 配置PE3引脚为输出模式 s3*/ GPIO_InitStructure.

22款常用微信小程序UI框架推荐!

22个好看、常用的微信小程序UI组件库推荐! 1. WeUI 地址:https://developers.weixin.qq.com/miniprogram/dev/extended/weui/ 预览码: 2. ColorUI 地址:https://github.com/weilanwl/ColorUI 预览码: 3. vantUI 地址:https://youzan.github.io/vant-weapp/#/intro 预览码: 4. MinUI 地址:https://meili.github.io/min/docs/minui/index.html 预览码: 5. iview-weapp 地址:https://weapp.iviewui.com/docs/guide/start 预览码: 6. WXRUI 地址:https://github.com/Rattenking/WXRUI 预览码: 7. WuxUI 地址:https://www.wuxui.com/#/introduce 预览码: 8. WussUI 地址:https://phonycode.github.io/wuss-weapp/quickstart.html 预览码: 9. TouchUI 地址:https://github.com/uileader/touchwx 预览码: 10. Hello UniApp 地址:https://m3w.cn/uniapp 预览码: 11. TaroUI 地址:https://taro-ui.jd.com/#/docs/introduction 预览码: 12. Thor UI 地址 http://www.donarui.com/guide.html 预览码: 13. GUI 地址:https://github.com/Gensp/GUI 预览码: 14. kaiUI github地址:https://github.com/Chaunjie/kai-ui 组件库文档:https://chaunjie.github.io/kai-ui/index.html#/components 预览码: 15. BeeUI git地址:http://ued.local.17173.com/gitlab/wxc/beeui.git 预览码: 16. easyUI 地址:https://github.com/qq865738120/easyUI 预览码:

CMAKE---- 控制编译

1.Introduction 根据CMKAE官网的介绍,主要是用来管理编译和单元测试。我们第一部分总结CMAKE如何进行管理编译的。 C M a k e i s a n o p e n − s o u r c e , c r o s s − p l a t f o r m f a m i l y o f t o o l s d e s i g n e d t o b u i l d , t e s t a n d p a c k a g e s o f t w a r e .

[Vue3] Wangeditor富文本实现将粘贴中包含的图片自动上传后台,并替换src

前言 因为老大突然说 网站后台负责维护的人员 上传到富文本(为了SEO就不用贴图)的内容, 一些图片显示失败,我一看还真是 之前好不容易弄好这个富文本的图片上传功能(就是点击图片, 选择上传) 还真没有想到他们直接扒过来别的网站内容(尤其里面包含图片) 这时候加入这个网站设置跨域, 图片就会因为跨域显示403失败,无法加载出来. 吐槽: 还以为他们富文本把文字写好, 在一个个上传图片, 组成一片文章. 那就没有办法了, 只能修改下代码增加下自动上传图片功能. 后来写到一半才发现html 有个属性好像可以让跨域的图片 显示出来. <meta name="referrer" content="no-referrer" /> 暂时不太理解这个代码, 也不清楚有没有副作用, 希望有懂的大佬说下. 以为这样就可以不用写了, 但是老大说 万一以后别人网站的图片不维护了, 那这个引用还是导致图片显示失败, 还是上传到后台保险. 嘚, 代码还是要写. 1. 具体思路 ​ 因为自己代码写得很烂, 就把关键的代码贴出来供大家参考, 当然不止WangEditor富文本编辑器能用, 其他地方需要粘贴时候自动上传图片也能实现, 原理都是一样的 ​ (无非其他地方需要 自己选择DOM节点, 触发粘贴事件, 然后具体完成后, 在这个DOM节点插入 处理好的内容) 1.1 介绍过程 概念会如下再介绍, 先说说具体过程, 就是 首先通过粘贴事件触发, 停止默认粘贴事件, 获取其text/html的内容使用字符串正则 match匹配 内容中符合 <img … src= “…”>这样的内容, 获得匹配字符串数组对数组遍历, 传入url在图片onload加载好后触发回调函数, 会将图片转为base64base64 转 BlobBlob 转 file将file 传入请求上传后台函数当全部图片上传后, 我是创建一个Map类型, 通过replace去匹配替换html中的src的内容将其insert 插入 1.

Spring Boot、Spring Cloud、Spring Cloud Alibaba 版本依赖关系

由于 Spring Boot 2.4+ 和以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 2.4 为分界线,同时维护 2.2.x 和 2021.x 两个分支迭代。 2021.x 分支 适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): (注意,该分支 Spring Cloud Alibaba 版本命名方式进行了调整,未来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最后一位为扩展版本,比如适配 Spring Cloud 2021.0.1 版本对应的 Spring Cloud Alibaba 第一个版本为:2021.0.1.0,第个二版本为:2021.0.1.1,依此类推) Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2021.0.4.0* Spring Cloud 2021.0.4 2.6.11 2021.0.1.0 Spring Cloud 2021.

钉钉小程序使用iconfont

进入iconfont官网,点击第二个选项font class 中的链接打开样式表 将样式ctrl+A 全选粘贴在app.acss中使用:<text class="iconfont icon-jiantou1"></text> 或者新建一个acss文件,将第2步骤粘贴在xxx.acss,在app.acss中引入 @import "/static/iconfont/xxx.acss";

C# Task.Factory.StartNew和Task.Run的坑点

目录 一、说明二、代码 一、说明 初学Task时,几乎所有的资料都说Task.Factory.StartNew和Task.Run是一样的,只不过Task.Run是简版,Task.Factory.StartNew可以设置更多参数。 可万万没想到,我在实际使用时,却发现了一个运行不一致的小“bug”。 二、代码 static void Main(string[] args) { TestStartNew(); TestRun(); Console.ReadKey(); } static async void TestStartNew() { Console.WriteLine($"[{DateTime.Now:HH:mm:ss ffff}]准备执行Task.Factory.StartNew"); await Task.Factory.StartNew(async () => { for (int i = 0; i < 2; i++) { await Task.Delay(1000); } }); Console.WriteLine($"[{DateTime.Now:HH:mm:ss ffff}]结束执行Task.Factory.StartNew"); } static async void TestRun() { Console.WriteLine($"[{DateTime.Now:HH:mm:ss ffff}]准备执行Task.Run"); await Task.Run(async () => { for (int i = 0; i < 2; i++) { await Task.Delay(1000); } }); Console.

如何判断数据是否为空

判断对象为空,就使用 for in 或者 Object.keys 来判断,尽量不要使用 JSON.stringify。 1.for in 首先可以用遍历解决,用的是 for in,思路如下: 遍历这个对象 如果能被遍历,说明这个对象有属性,返回 false否则说明对象为空,返回 true 2.Object.keys() 还有一种方式就是使用 Object.keys(),先把对象转化为数组,然后再根据数组的长度是否为零来判断对象是否为空。 但是传入 null 或 undefined,就会出问题,如下代码所示: function isEmptyObject(obj) { return Object.keys(obj).length === 0; } isEmptyObject(null); // Uncaught TypeError: Cannot convert undefined or null to object isEmptyObject(undefined); // Uncaught TypeError: Cannot convert undefined or null to object 所以在实际项目中,可以用如下方式实现本函数: function isEmptyObject(obj) { return Object.keys(obj || []).length === 0; } 3.JSON.stringify() 还可以使用 JSON.stringify() 来解决本题,只需要判断对象转为 JSON 字符串之后,是不是等于 {} 即可,代码如下:

[XNUCA2019Qualifier]EasyPHP

知识点: .htaccess 利用 代码主要有两个过滤: 一个是文件名:以 a-z 以及 . 开头,这里就很巧妙了,什么文件以点开头,配置文件啊。 另一个就是对文件内容的过滤,基本等于没有,可以用注释和行拼接绕过。 php 的 .htaccess 文件中可以用 # 号注释某行,也可以用 \ 拼接上下两行,那么我们可以直接在 .htaccess 里写 shell,加上 auto_prepend_file 设置把 shell 包含到 index.php 中。 <?php $files = scandir('./'); foreach($files as $file) { if(is_file($file)){ if ($file !== "index.php") { unlink($file); } } } include_once("fl3g.php"); if(!isset($_GET['content']) || !isset($_GET['filename'])) { highlight_file(__FILE__); die(); } $content = $_GET['content']; if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) { echo "

用原生js手写分页功能

分页功能如下: 数据分页显示,每页显示若干条数据,默认当前页码为第一页。例如:每页5条数据,则第一页显示 1-5 条,第二页显示 6-10 条,依此类推。当页码为第一页时,上一页为禁用状态,点击无任何变化。当页码为最后一页时,下一页为禁用状态,点击无任何变化。正确显示当前页数和总页数。 首先,要显示的数据如下: // 课外书列表 const bookList = [{ "name": "带你从入门到实战全面掌握 uni-app", "price": 8900 }, { "name": "初中级前端工程师面试宝典", "price": 4900 }, { "name": "微信公众号开发入门", "price": 3900 }, { "name": "从零入门 React 通关指北", "price": 8900 }, { "name": "Flask 框架基础", "price": 9800 }, { "name": "JavaScript 从零构建音乐播放器", "price": 8900 }, { "name": "微信小程序开发入门", "price": 1490 }, { "name": "SpringBoot+Thymeleaf 开发 BBS 论坛", "price": 13900 }, { "

毕设--基于深度学习的人脸识别(详细步骤+代码)

最近闲来无事,想写一个本人毕设基于深度学习的人脸识别文章。我主要利用两个不同的神经网络进行实现,分别是一个简单三层的卷积神经网络和结构复杂的VGG16神经网络,并比对了两种网络训练出的模型的识别效果。从最终的结果来看,与预想的一样结构更复杂的VGG16的效果更胜一筹。下面我就来具体介绍一下其实现过程。 (鉴于很多小伙伴私聊我对这个项目感兴趣,我将代码链接附在评论区了,有需要的小伙伴请自取,觉得有用的话记得点赞哦,栓Q~~~) 接下来我将从以下的顺序来进行讲解: 环境配置 人脸检测部分 训练模型部分 人脸识别部分 1. 环境配置 ①Python3.6 (尽管现在的 python 以经更新到了 3.9 版本了,但是由于 tensorflow 框架和 Anaconda 的需求这里还是选择 3.6 版本) ②opencv (opencv_python-4.4.0-cp36-cp36m-win_amd64,这里面版本号没有具体限制, 但是必须要支持 python3.6) ③scipy1.2.0(这个一定要注意呀,使用pip install scipy安装这个包的时候,一般都会安装1.3+的版本,在我这个程序里面就会报错了,因为我是使用了1.2版本里面的方法,在1.3版本里面该方法舍弃了) ④tensorflow1.9 ⑤keras2.2.0 ⑥sklearn(scikit_learn-0.24.1 版本) ⑦tkinder(没有具体要求,此设计使用的最新版) 对了还有就是在安装这些库的时候,如果是使用pip install的方法,建议就都使用这个方法,不然使用不同方法安装到时就会报错(一条来自踩坑者的忠告哈哈),配置大概是这些了,可能有的没写出来,可能就需要大家踩一些坑配置了(此处是不是要啪啪打脸了啊) 2. 人脸检测 此部分主要采用的是opencv来调用摄像头并进行图像处理,然后使用基于级联分类器+haar特征的方法进行人脸检测。opencv使用起来非常方便,这里使用到的函数很少,也就普通的读取图片,灰度转换,显示图像,简单的编辑图像罢了。 1)读取图片 只需要给出待操作的图片的路径即可。 import cv2 image = cv2.imread(imagepath) 2)灰度转换 灰度转换的作用就是:转换成灰度的图片的计算强度得以降低。因为现在的彩色图片都是三通道的数据,不做任何处理,数据量会很大,对于我们学生用的机子来说hold不住。 import cv2 gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) 灰色图片大概就是这样的。 3)画图 opencv 的强大之处的一个体现就是其可以对图片进行任意编辑,处理。 下面的这个函数最后一个参数指定的就是画笔的大小。其实就是要把检测到的人脸边框给描出来。 import cv2 cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2) 4)显示图像 编辑完的图像要么直接的被显示出来,要么就保存到物理的存储介质。 import cv2 cv2.imshow("Image Title",image) 5)获取人脸识别训练数据 看似复杂,其实就是对于人脸特征的一些描述,这样opencv在读取完数据后很据训练中的样品数据,就可以感知读取到的图片上的特征,进而对图片进行人脸识别。 import cv2 face_cascade = cv2.

基于stm32的所有嵌入式项目代码

本人本科和硕士阶段的专业都是嵌入式方向,做了许许多多的项目,包括51、stm32、freeRTOS、linux操作系统、多进程线程实现功能,包括裸机开发,驱动开发,系统开发,同时在整机器学习,模式识别,图像处理这些东西。 因此我整理了我以前做的一些小玩意和一些比赛包括本科电子设计大赛、研电赛等嵌入式比赛等,很多作品获得国家省奖等,在这里分享出来,希望能帮助到大家。 当然如果大家也可以找我代写一些嵌入式程序,多给我点点赞加个关注就行,一些简单的程序可以免费帮大家做哈。 以下仅列出部分参考项目,程序实在太多了,懒得列出来了。 可进入主页联系作者huo取 含有完整文档及代码: 1、电子设计大赛备赛工程模板(这个对于我以前电赛备赛帮了我大忙) STM32F1单片机综合功能程序(电子设计大赛备赛工程)-智慧城市文档类资源-CSDN文库 2、STM32平衡小车 3、自定义串口通信协议 4、robomaster自瞄视觉及与下位机通信程序 5、基于stm32-dma-cubemx-pid工程 6、基于stm32的电动车跷跷板 (2021年电子设计大赛-电动车跷跷板(省一程序)-智能家居文档类资源-CSDN文库) 7、基于stm32的独轮机器人 8、基于stm32的循迹及抓取程序 9、基于stm32的WIFI蓝牙无线控制小车 10、基于ROS与stm32的智能小车 11、基于ROS和SLAM激光雷达控制源程序 12、基于树莓派的电机倒立摆控制系统 13、基于stm32、openmv的非接触式物体尺寸形态测量仪 14、基于工业派的自动水果贩卖机(Linux系统多线程实现) 15、基于51单片机相关几乎所有的控制程序 16、基于stm32的库函数和HAL库函数的所有例程 17、基于linux多线程图像处理的自助水果售卖机 18、基于stm32的风力摆程序 51单片机程序:

从基础学习深度学习——手写字符识别

PS:第一次写博客,请见谅。 一、深度学习 深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向,它被引入机器学习使其更接近于最初的目标——人工智能(AI, Artificial Intelligence)。 深度学习是学习样本数据的内在规律和表示层次,这些学习过程中获得的信息对诸如文字,图像和声音等数据的解释有很大的帮助。它的最终目标是让机器能够像人一样具有分析学习能力,能够识别文字、图像和声音等数据。 深度学习是一个复杂的机器学习算法,在语音和图像识别方面取得的效果,远远超过先前相关技术。 深度学习在搜索技术,数据挖掘,机器学习,机器翻译,自然语言处理,多媒体学习,语音,推荐和个性化技术,以及其他相关领域都取得了很多成果。深度学习使机器模仿视听和思考等人类的活动,解决了很多复杂的模式识别难题,使得人工智能相关技术取得了很大进步。 (以上均来自百度百科) 二、手写字符识别 手写识别涉及到模式识别,神经元网络以及人工智能的知识,基础是数字图像处理。手写识别(HandWritingRecognition)是指将在手写设备上书写时产生的有序轨迹信息化转化为汉字内码的过程,实际上是手写轨迹的坐标序列到汉字的内码的一个映射过程,是人机交互最自然、最方便的手段之一。 三、代码调试 源码下载地址(开源):https://github.com/mivlab/AI_course 数据集下载地址:https://pan.baidu.com/s/18Fz9Cpj0Lf9BC7As8frZrw 提取码:xhgk 下载完整压缩包以及数据集 解压压缩包,打开pycharm,选择打开项目,直接打开解压之后的文件夹,配置相应的环境 随后打开classify_pytorch中的train_mnist.py,运行该文件正常会出现以下报错: 这是由于未将运行参数配置,我们需要找到工具栏中的运行--编辑配置 找到解压之后数据集所在的路径位置并将其输入在参数一栏, 如:--datapath=D:\BaiduNetdiskDownload\MNIST_Dataset\train_images(如下图所示) 此时注意,因为各人电脑所配置的环境不同,运行代码时可能会出现以下问题, 以上出现的问题是Input type和weight type数据类型不匹配,因为我的电脑环境本身是支持GPU的,报错显示Input type是在GPU训练的,而weight type却是在CPU运行的,数据类型不匹配,因此出现问题,回头检查代码,会发现下图箭头处的False表明了没有使用CUDA 进行训练,这里需要将其更改为True。 此外,还需要将本网络模型放到GPU上训练,将model = Net(10)更改为 model = Net(10).cuda(),这个代码表明的意思就是将模型放到cuda上进行训练。 更改完之后发现代码已经可以正常运行,进行训练了。 测试结果: 训练完成之后打开同路径下的tes_mnist.py进行结果测试,得出的结果如下图: 题外话:若想知道自己的电脑是否支持GPU训练,可以在将鼠标放置在电脑下方右击点击任务管理器--性能,即可看电脑是否带有GPU

CSS 实现input自定义样式--文本框

边框 设置边框颜色 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>input文本框样式自定义</title> </head> <style> form { padding: 20px; background-color: #fffceb; } div { margin-top: 20px; } label { padding-right: 6px; } input { width: 200px; height: 26px; line-height: 26px; padding-left: 1em; font-size: 12px; } .box{ border :1px solid red; } .boc{ border :1px solid #16a085; } </style> <body> <form> <div> <label>文本框1</label><input class="box" type="text" > <label>文本框2</label><input class="boc" type="text" > </div> </form> </body> </html> 页面效果:

ElementUi 表格自动滚动

目录 概要 相关资源 关键点 实现原理 核心代码 异常情况 相关链接 概要 本文主要讲解如何在elmentui的table组件上实现表格内容自动滚动。表格背景已通过css修改为透明背景。话不多说,直接进入正题。 相关资源 资源类型资源名称JQUERY jquery-3.1.1.min.js VUE vue.js VUE vue-resource.js ElementUI elementui.min.js ElementUI elementui.css 关键点 1.创建html页面引入相关资源 2.创建el-table表格 ref="datalist" 表格元素的标记,用于获取到这个元素,用法:$.refs.datalist @mouseover.native 鼠标移入表格事件 移入表格时滚动暂停 @mouseout.native 鼠标移出表格事件 移除表格时滚动恢复 @row-click 表格每行的点击事件 :data="tableData" 表格绑定的数据源名称 height="420" 设置表格高度为420,必须,否则表格无法滚动 <div id="App"> <div class="warp"> <div class="close" onclick="closePage">X</div> <div class="list"> <el-table ref="datalist" @mouseover.native="mouseEnter()" @mouseout.native="mouseLeave()" @row-click="tableRowClick" :data="tableData" height="420" border style="width: 100%" > <el-table-column prop="time" align="center" label="时间" width="150"> </el-table-column> <el-table-column prop="title" align="left" label="事件" > </el-table-column> </el-table> </div> </div> </div> 实现原理 通过获取表格的实际高度、可视高度、滚动距离,利用定时器按照设置的速度和每帧滚动距离不断重新设置滚动距离达到滚动的效果。到达底部后滚动距离重置为0.

postgres 日期字符串转换及月份补0处理

目录 引言 需求分析 数据处理 结束 引言 工作中经常涉及到对时间类型的各种处理和转换,现记录一下pg中如何进行补0操作。涉及函数LPAD、CAST、POSITION、SUBSTR、SPLIT_PART 需求分析 现库中存在一张停车记录表,需统计最新一天各类型车辆停车记录数,并返回实际出入时间(天)。数据中包含每辆车出入闸机时间,为varchar类型的时间字符串。源数据如下所示,现需将时间类型转换为YYYY-MM-DD格式。 表结构 i_id主键cpys车牌颜色(车辆类型)crcsj出入车时间(出入闸机时间)crfx出入方向tclx 停车类型 s_createtime数据入库时间 数据处理 1.按类型统计最新一天各类型车辆停车记录数。结果如下 -- 通过进入计算 只进不出算1次 同一辆车多次进入进几次算几次 select count(i_id) cls,cpys from resafety_jtzt.a_mx_cgj_hs_cg_tcjl where S_CREATETIME=(select max(S_CREATETIME) from resafety_jtzt.a_mx_cgj_hs_cg_tcjl) and crfx='入车' group by cpys 2.出入时间处理。通过substr和position函数截取年月日部分 select count(i_id) cls,cpys,substr(crcsj,1,position(' ' in crcsj)-1) as sj from resafety_jtzt.a_mx_cgj_hs_cg_tcjl where S_CREATETIME=(select max(S_CREATETIME) from resafety_jtzt.a_mx_cgj_hs_cg_tcjl) and crfx='入车' group by cpys,substr(crcsj,1,position(' ' in crcsj)-1) 3. 通过SPLIT_PART函数通过斜杠拆分字符串 -- split_part(字符串,'拆分字符',返回拆分后地几个下标的字符串 从1开始) -- SPLIT_PART('5/14/23', '/', 3) 返回23 -- SPLIT_PART('5/14/23', '/', 2) 返回14 -- SPLIT_PART('5/14/23', '/', 1) 返回5 SPLIT_PART(substr(crcsj,1,position(' ' in crcsj)-1), '/', 3) 4.

C语言 找第一个只出现一次的字符

Description 给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no。 Input 一个字符串,长度小于100000。 Output 输出第一个仅出现一次的字符,若没有则输出no。 Sample Input abcdbd Sample Output c Source Code #include <stdio.h> #include <string.h> int main() { char a[100000]; int c[100000]={0}; //存放每个字符出现的次数,初始时全为0 gets(a); int length = strlen(a); for(int i=0;i<length;i++) //遍历字符串中每一个字符 { for(int j=0;j<length;j++)//遍历第二次让a[j]和a[i]对比 { if(a[i]==a[j]) c[i]++; //如果相同c[i]++ } if(c[i]==1) { printf("%c\n",a[i]); return 0; } } printf("no\n"); return 0; } Computational Results

C语言中“##“的用法介绍

市面上有很多比较火的编程语言,比如Python、 JAVA、 Go等,你可能觉得C语言很古老、很落后。如果你有这种想法,那可能你只是一个初学的菜鸟。之前给大家分享《C语言中几种特殊标准定义和用法》忘记了C语言中一个重要的内容,就是 ## 的用法,可能绝大部分 C 程序员都不知道"##"隐藏用法,下面微点阅读小编就来给大家讲讲。 一、##的“表”用法 想必很多人都知道"##"的用法——它本质上是一个“胶水运算”(连接字符串的作用),用于把参数宏中的“形参”与其它没有天然分割的内容粘连在一起,例如: #define def_u32_array(__name, __size) uint32_t array_##__name[__size]; 实际中,我们可以这样使用: def_u32_array(sample_buffer, 64) 宏展开的效果是: uint32_t array_sample_buffer[64]; 可以看到,"array__"与形参“__name”是没有天然分割的,因此要想将"array_"与"__name"所代表的内容(而不是__name本身)粘连在一起,就需要“##”运算的帮助。 另一方面,"__name"与"["是具有天然分隔的——编译器不会认为"__name"与"["是连接在一起的,因此这里并不需要画蛇添足的使用"##"运算——如果你这么做了,预编译器会毫不犹豫的告诉你语法错误。——这是"##"运算的普通用法,在过去转载的文章《C语言#和##连接符在项目中的应用(漂亮)》中也有详细介绍,这里就不再赘述。 二、## 的官方“里”用法 “##”还有一个很少为人所知的“里”用法,在介绍它之前,不得不首先说说由ANSI-C99标准引入的另外一个参数宏扩展——可变参数宏。举个例子: #define safe_atom_code(...) \ { \ uint32_t int_flag = __disable_irq(); \ __VA_ARGS__ \ __set_PRIMASK(int_flag); \ } 这里定义了一个宏"safe_atom_code()",在括号内,无论你填写任何内容,都会被无条件的放置到“__VA_ARGS__”所在的位置,你可以认为括号里的“...”实际上就是对应"__VA_ARGS__"。比如,我们可以写下这样的代码: /** \fn void wr_dat (uint16_t dat) \brief Write data to the LCD controller \param[in] dat Data to write */ static __inline void wr_dat (uint_fast16_t dat) { safe_atom_code( LCD_CS(0);

sql-labs靶场练习

目录 less-11 less-12 less-13 less-14 less-15 less-16 less-17 less-18 less-19 less-20 less-21 less-22 less-23 less-24 less-25 less-25a less-26 less-26a less-27 less-27a less-28 less-28a less-29 less-30 less-31 less-32 less-33 less-34 less-35 less-36 less-37 less-38 less-39 less-40 less-41 less-42 less-43 less-44 less-45 less-46 less-47 less-48 less-49 less-50 less-51 less-52 less-53 less-54 less-55 less-56 less-57 less-58 less-59 less-60 less-61 less-62 less-63 less-64 less-65 less-11 这一关开始发现是post传参,是在输入框中输入,但总体思路不变 一般POST型使用1' or 1=1 -- #和1" or 1=1 -- # 来判断闭合方式,成功的概率最大因单双引号引起的闭合问题更大点

centos安装rocketmq

centos安装rocketmq 1 下载rocketmq二进制包2 解压二进制包3 修改broker.conf4 修改runbroker.sh和runserver.sh的JVM参数5 启动NameServer和Broker6 安装rockermq dashboard(可视化控制台) 1 下载rocketmq二进制包 点击rocketmq二进制包下载地址,下载完成之后通过ftp工具上传到云服务器 2 解压二进制包 unzip rocketmq-all-5.1.0-bin-release.zip 3 修改broker.conf vi rocketmq-all-5.1.0-bin-release/conf/broker.conf # nameServer地址,如果有多个nameServer用分号分割 namesrvAddr=你的ip地址:9876 # 当前broker监听的IP brokerIP1:你的ip地址 esc :wq 保存退出 4 修改runbroker.sh和runserver.sh的JVM参数 vi rocketmq-all-5.1.0-bin-release/bin/runbroker.sh 设置-Xms256m -Xmx256m(根据服务器内存大小设置) vi rocketmq-all-5.1.0-bin-release/bin/runserver.sh 设置-Xms256m -Xmx256m -Xmn200m(根据服务器内存大小设置) 5 启动NameServer和Broker !!前提,已安装Java运行环境 如未安装Java环境 yum install -y java-1.8.0-openjdk 进入解压好的文件夹 cd rocketmq-all-5.1.0-bin-release/ 启动NameServer nohup sh bin/mqnamesrv & 如遇到如下图情况 直接输入如下命令 cat nohup.out 查看nohup.out文件,若如下图,则NameServer启动成功 启动broker nohup sh bin/mqbroker -n localhost:9876 --enable-proxy & 6 安装rockermq dashboard(可视化控制台) 点击rockermq dashboard源码下载地址,下载完成之后通过ftp工具上传到云服务器

Zookeeper集群安装与配置

1、解压apache-zookeeper-3.8.0-bin.tar.gz解压到/opt/目录下 tar -zxvf /root/experiment/tools/apache-zookeeper-3.8.0-bin.tar.gz -C /opt 2、修改apache-zookeeper-3.8.0-bin的名称为zookeeper mv /opt/apache-zookeeper-3.8.0-bin /opt/zookeeper 3、复制Zookeeper配置文件zoo_sample.cfg名为zoo.cfg cp /opt/zookeeper/conf/zoo_sample.cfg /opt/zookeeper/conf/zoo.cfg 4、编辑zoo.cfg vi /opt/zookeeper/conf/zoo.cfg 配置如下参数: dataDir=/opt/zookeeper/zkdata dataLogDir=/opt/zookeeper/zkdatalog server.1=node01:2888:3888 server.2=node02:2888:3888 server.3=node03:2888:3888 5、创建Zookeeper数据文件夹zkdata和日志文件夹zkdatalog mkdir -p /opt/zookeeper/zkdata mkdir -p /opt/zookeeper/zkdatalog 6、修改文件夹zkdata和zkdatalog读写权限 chmod 700 /opt/zookeeper/zkdata chmod 700 /opt/zookeeper/zkdatalog 7、配置并刷新环境变量 export ZK_HOME=/opt/zookeeper export PATH=$ZK_HOME/bin:$PATH 刷新环境变量 souce /etc/profile 8、拷贝node01主机/etc/profile文件到node02、node03主机。 scp /etc/profile node01:/etc scp /etc/profile node02:/etc 9、拷贝node01主机/opt/zookeeper文件到node02、node03主机。 scp -r /opt/zookeeper node01:/opt scp -r /opt/zookeeper node02:/opt 10、当前主节点node01机上,将字符串“1”写入文件myid。 echo "1" > /opt/zookeeper/zkdata/myid cat /opt/zookeeper/zkdata/myid 11、当前主节点node02机上,将字符串“2”写入文件myid

Volatile 和CAS实现原理及使用场景

Volatile Volatile的作用 Volatile的作用:具有多线程间内存可见性,禁止指令重排序,但不具备原子性,在我们的认知中,多线程场景下通常使用锁来实现,但是Java为我们提供了Volatile关键字,在某些场景下比锁使用的更加方便。 下面就Volatile的几个特性来说明其用处: 1、多线程环境下内存可见性 package com.test; import java.util.concurrent.TimeUnit; public class ThreadDemo extends Thread { //声明一个变量 private boolean result = false; public boolean getResult(){ return result; } @Override public void run() { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //在线程运行时改变其变量值 result = true; System.out.println(result); } } package com.test; public class VolatileDemoOne { public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); while (true){ if(threadDemo.

MySQL45讲笔记04深入浅出索引上

索引的目的: 索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。常见索引模型: hash表,以K-V键值对的形式的一种数据结构,底层是数组加链表形式。通过一定的hash运算找到数据合适的位置放入,如果放入的位置相同时,则拉出一个链表保存。 缺点就是,由于上图中的数据不是顺序排列的,所以查找的时候需要对数据进行遍历,造成了查询较慢的问题。 有序数组形式:顾名思义是有序的数组,这样可以使用二分查找去搜索,速度非常快。缺点是,当数组内数据变化时,需要挪动位置。这样的效率就很低,所以只适用于静态数据,一些不会再变化的数据。 二叉树: 在mysql中使用的是B+树,与B树的区别如下: b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”; b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢); 对于范围查找来说,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历 回表概念 每一个索引都是一颗B+树,索引分为普通索引,主键索引。 推荐使用主键索引,原因是主键索引不需要回表(详情?)回表导致查询效率降低的问题。 使用主键索引才能查询出完整表数据,非主键索引只能查出主键和对印的索引列数据。所以需要进行回表。 当然如果你要查询的列就是主键和索引列就不需要回表,直接可以查出来。这就是索引覆盖。 索引维护 插入或删除数据时,可能需要对B+树进行维护,涉及到数据页的分裂或合并。 当我们设置自动递增的主键索引时,这些增加的操作都是对B+树的追加,不会触发到叶子节点的分裂。 使用业务逻辑字段做主键时,往往不需要保证有序插入,遮掩的成本有点高。 主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。 尽量使用主键查询 总结: Innodb采用B+树结构,减少查询次数。建议使用自增主键索引,这样可以减少普通索引的叶子节点大小,但是还是需要根据业务来进行分析。没有主键innodb会自动创建一个主键RowId 问题:重建索引,重建主键索引?说出你的理解以及不合适的地方?为什么? alter table T drop index k; alter table T add index(k); alter table T drop primary key; alter table T add primary key(id);

相机标定详解

相机标定: 目的: 还原摄像头成像的物体在真实世界的位置就需要知道世界中的物体到计算机图像平面是如何变换的,相机标定的目的之一就是为了搞清楚这种变换关系,求解内外参数矩阵 摄像机的透视投影有个很大的问题——畸变。摄像头标定的另一个目的就是求解畸变系数,然后用于图像矫正 坐标系介绍: 世界坐标系(Xw,Yw,Zw):目标物体位置的参考系。除了无穷远,世界坐标可以根据运算方便与否自由放置,单位为长度单位如mm。在双目视觉中世界坐标系主要有三个用途: 标定时确定标定物的位置 作为双目视觉的系统参考系,给出两个摄像机相对世界坐标系的关系,从而求出相机之间的相对关系; 作为重建得到三维坐标的容器,存放重建后的物体的三维坐标。世界坐标系是将看见中物体纳入运算的第一站。 摄像机坐标系(Xc,Yc,Zc):摄像机站在自己角度上衡量的物体的坐标系。摄像 机坐标系的原点在摄像机的光心上,z轴与摄像机光轴平行。它是与拍摄物体发生联系的桥头堡,世界坐标系下的物体需先经历刚体变化转到摄像机坐标系,然后在和图像坐标系发生关系。它是图像坐标与世界坐标之间发生关系的纽带,沟通了世界上最远的距离。单位为长度单位如mm。 图像坐标系(x,y):以CCD 图像平面的中心为坐标原点,为了描述成像过程中物体从相机坐标系到图像坐标系的投影透射关系而引入,方便进一步得到像素坐标系下的坐标。图像坐标系是用物理单位(例如毫米)表示像素在图像中的位置。 像素坐标系(u,v):以 CCD 图像平面的左上角顶点为原点,为了描述物体成像后的像点在数字图像上(相片)的坐标而引入,是我们真正从相机内读取到的信息所在的坐标系。像素坐标系就是以像素为单位的图像坐标系。 图像坐标系转换像素坐标系: 像素坐标系和图像坐标系都在成像平面上,如图。 以图像左上角为原点建立以像素(pixel)为单位的像素坐标系u-v。像素的横坐标u与纵坐标v分别是在其图像数组中所在的列数与所在行数,描述一个像素点都是几行几列。图像坐标系的原点为相机光轴与成像平面的交点O(u0,v0),通常情况下是成像平面的中点或者叫principal point。图像坐标系的单位是mm,属于物理单位。dx,dy表示每个像素在横轴x和纵轴y上的物理尺寸(单位为:mm/像素,单位像素的距离)。 则图像中的每个像素在u-v坐标系中的坐标和在x-y坐标系中的坐标之间都存在如下的关系(为了方便使用,用齐次坐标与矩阵形式表示): 例如:设CCD大小为8 x 6mm,拍摄的图像大小为640 x 480,则dx = 1/80(mm/像素)dy = 1/80(mm/像素), u0=320,v0=240 三大坐标系: 世界坐标系通过刚体变换到达摄像机坐标系,然后摄像机坐标系通过透视投影变换到达图像坐标系。可以看出,世界坐标与图像坐标的关系建立在刚体变换和透视投影变换的基础上。 世界坐标系转换摄像机坐标系: 刚体变换(regidbody motion):三维空间中, 当物体不发生形变时,对一个几何物体作旋转, 平移的运动,称之为刚体变换。 世界坐标系和摄像机坐标都是右手坐标系,所以其不会发生形变。我们想把世界坐标系下的坐标转换到摄像机坐标下的坐标,如下图所示,可以通过刚体变换的方式。空间中一个坐标系,总可以通过刚体变换转换到另外一个个坐标系的。 世界坐标系与摄像机坐标系之间的刚体转换表达式为: R是3×3的正交单位矩阵(即旋转矩阵),t为平移向量,R、t与摄像机无关,所以称这两个参数为摄像机的外参数(extrinsicparameter),可以理解为两个坐标原点之间的距离,因其受x,y,z三个方向上的分量共同控制,所以其具有三个自由度。假定在世界坐标系中物点所在平面过世界坐标系原点且与Zw轴垂(也即棋盘平面与Xw-Yw平面重合,目的在于方便后续计算),Zw=0。 摄像机坐标系转换图像坐标系: 透视投影(perspective projection): 用中心投影法将形体投射到投影面上,从而获得的一种较为接近视觉效果的单面投影图。有一点像皮影戏。它符合人们心理习惯,即离视点近的物体大,离视点远的物体小,不平行于成像平面的平行线会相交于消隐点(vanish point) 透视投影与小孔成像相似,下图为针孔摄像机的模型,平面π称为摄像机的像平面,点Oc称为摄像机中心(或光心),f成为摄像机的焦距,Oc为端点且垂直于像平面的射线成为光轴或主轴,主轴与像平面的交点p是摄像机的主点 图像坐标系为O-xy,摄像机坐标系为Oc-XcYcZc。记空间点Xc摄像机坐标系中的齐次坐标为: 像点m在图像坐标系中的齐次坐标为: 根据三角形相似原理: 矩阵表示为(齐次坐标伸缩不变性Zc[x y 1]T和[x y 1]T表示同一点): 合并: 将世界坐标系转换到像素坐标系,将上诉式子联系起来,写在一起得到如下矩阵(注意符号对应u—>像素坐标、x—>图像坐标、Xc—>摄像机坐标、Xw—>世界坐标): 世界坐标到像素坐标变换矩阵P如下: P表示一个投影相机: 总结:世界坐标系到像素坐标系(不考虑畸变)的转换关系 图片矫正: 我们在摄像机坐标系到图像坐标系变换时谈到透视投影。摄像机拍照时通过透镜把实物投影到像平面上,但是透镜由于制造精度以及组装工艺的偏差会引入畸变,导致原始图像的失真。因此我们需要考虑成像畸变的问题。 透镜的畸变主要分为径向畸变和切向畸变,还有薄透镜畸变等等,但都没有径向和切向畸变影响显著,所以我们在这里只考虑径向和切向畸变 径向畸变: 径向畸变就是沿着透镜半径方向分布的畸变,产生原因是光线在远离透镜中心的地方比靠近中心的地方更加弯曲,这种畸变在普通廉价的镜头中表现更加明显,径向畸变主要包括桶形畸变和枕形畸变两种。以下分别是枕形和桶形畸变示意图: 像平面中心的畸变为0,沿着镜头半径方向向边缘移动,畸变越来越严重。畸变的数学模型可以用主点(principle point)周围的泰勒级数展开式的前几项进行描述,通常使用前两项,即k1和k2,对于畸变很大的镜头,如鱼眼镜头,可以增加使用第三项k3来进行描述,成像仪上某点根据其在径向方向上的分布位置,调节公式为: 式中(x0,y0)是畸变点在像平面的原始位置,(x,y)是畸变较正后新的位置,下图是距离光心不同距离上的点经过透镜径向畸变后点位的偏移示意图,可以看到,距离光心越远,径向位移越大,表示畸变也越大,在光心附近,几乎没有偏移。 切向畸变:

从0到1实现单机记账APP原理与细节uniApp内含源码 (二)

单机记账APP演示及源码 具体演示如下面视频所示。免费下载地址:点击进入 预览APP下载地址:http://8.142.10.182:8888/down/aWHWeGaEQE2W.apk (带宽很小所以下载速度慢) 由于资源已经通过了,页面的样式这里就不写了,主要把方法还有思路写下来。 第一章记账功能实现 单机记账APP 单机记账APP演示及源码一、记账功能实现1.首页实现2.全部账单实现3.个人中心 小总结 一、记账功能实现 1.首页实现 界面效果如下: 上面的支出、收入、预算的就不说了。预算其实可以考虑本地缓存一个数据用于存储变量,将预算设置为活的。我这里面没有设置。 在onshow里面调用getBook方法,然后取到本地缓存数据,先通过sort将数据进行排序,随后通过map方法算出支出/收益,将同一天的统计在一起。 方法如下。 // 查询本月账单 getBook() { let accName = this.yearTime + '-' + this.monthTime let resList = uni.getStorageSync(accName).list || [] //指定排序列 function orderBy(name) { return function(object1, object2) { var val1 = object1[name]; var val2 = object2[name]; if (val1 < val2) return 1; else if (val1 > val2) return -1; else return 0; } } resList.sort(orderBy('datetime')); this.costMoney = 0 // 花费 this.

【问题及解决】训练一段时间卡住GPU Memory Usage满但是GPU-Util 是0%

【问题描述】 扩充了数据集的种类并且整合之后使用yolov7nohup挂起训练,结果到了epoch45的时候卡住了,一直不动。 并且观察显卡使用情况: 可以看到显存使用几乎是满的,但是GPU使用率一直是0. 【尝试解决】 nohup python train.py --workers 8 --device 0,1 --batch-size 64 --data data/construction_site.yaml --img 640 640 --cfg cfg/training/yolov7-tiny.yaml --weights ‘’ --name yolov7-tiny --hyp data/hyp.scratch.tiny.yaml >> kk-output-0302.log 2>&1 & 猜测这次的无故卡死是因为多线程读取数据导致内存爆炸,大内存很重要,这里8和4都试过了,因此选择调小num_works:8->4->2 Workers继续调小,变成2,结果还是会出现一样的情况。 【问题原因】 结果卡了好久,我发现出现报错了! 居然是因为找不到图像,应该是我数据处理步骤较多,有的没检查清楚,结果导致了这样的结果,万万没想到啊无语死了。 【参考】 出现这个问题首先检查数据标签是否有问题,也有一些其他原因导致的,列出来链接可以参考: 1.https://www.zhihu.com/question/584925830?utm_id=0 2.https://github.com/bubbliiiing/yolov4-pytorch/issues/49 3.https://blog.csdn.net/weixin_57234928/article/details/123557131 4.https://blog.csdn.net/qq_24407657/article/details/103992170

python学习之定制发送带附件的电子邮件

Python SMTP发送邮件 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。 Python创建 SMTP 对象语法如下: import smtplib smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] ) 参数说明: host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名如:runoob.com,这个是可选参数。 port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下SMTP端口号为25。 local_hostname: 如果SMTP在你的本机上,你只需要指定服务器地址为 localhost 即可。 Python SMTP对象使用sendmail方法发送邮件,语法如下: SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options] 参数说明: from_addr: 邮件发送者地址。 to_addrs: 字符串列表,邮件发送地址。 msg: 发送消息 这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。 导入模块如果没有错误,表示已经安装成功。 Python发送带附件的电子邮件基本思路如下: 构造MIMEMultipart对象做为根容器构造MIMEText对象做为邮件显示内容并附加到根容器构造MIMEBase对象做为文件附件内容并附加到根容器 a. 读入文件内容并格式化 b. 设置附件头设置根容器属性得到格式化后的完整文本用smtp发送邮件 import smtplib from email.mime.multipart import MIMEMultipart from email.header import Header from email.

Android NestedScrollView嵌套RecyclerView滑动卡顿问题终极解决方案

如果是如下的页面布局:NestedScrollView嵌套RecyclerView 随着recyclerVIew的加载,item越多,会发现滑动卡顿;大致解决方案有以下两种: 方案1:取消recyclerVIew的滑动 mRecyclerView.setNestedScrollingEnabled(false); 这种方案可能解决绝大部分问题。但是如果item中是加载的图片。但是可能就不起作用了。 可以尝试方案二; 方案2:采用 CoordinatorLayout + AppBarLayout解决 即用AppBarLayout包裹列表以外需要滑动的view。这样就可以实现联动了;注意此时一定不能设置 mRecyclerView.setNestedScrollingEnabled(false); 核心代码如下: <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/layout_data" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:scrollbars="none"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/mAppBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:fadingEdge="none" app:elevation="0dp"> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:overScrollMode="never" android:scrollbars="none" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/iv_top" android:layout_width="match_parent" android:layout_height="76dp" android:scaleType="fitXY" android:src="@mipmap/ic_estimate_title" /> </androidx.core.widget.NestedScrollView> <View android:layout_width="match_parent" android:layout_height="0dp"/> </com.google.android.material.appbar.AppBarLayout> <RelativeLayout android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="-8dp" android:layout_marginRight="-8dp" android:background="@color/color_bg" android:divider="@color/trans" android:horizontalSpacing="0dp" android:listSelector="@color/trans" android:overScrollMode="never" android:scrollbars="none" android:verticalSpacing="12dp" /> </RelativeLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout> 大功告成!

MySQL实战45讲深入浅出索引下

select * from T where k between 3 and 5 这个语句的执行流程是: 在 k 索引树上找到 k=3 的记录,取得 ID = 300;再到 ID 索引树查到 ID=300 对应的 R3;在 k 索引树取下一个值 k=5,取得 ID=500.再回到 ID 索引树查到 ID=500 对应的 R4;在 k 索引树取下一个值 k=6,不满足条件,循环结束。 进行了两次回表,这是因为有些数据只在主键索引上存在。 索引覆盖 由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的 性能优化手段。 在一个市民信息表上,是否有必要将身份 证号和名字建立联合索引? CREATE TABLE `tuser` ( `id` int(11) NOT NULL, `id_card` varchar(32) DEFAULT NULL, `name` varchar(32) DEFAULT NULL, `age` int(11) DEFAULT NULL, `ismale` tinyint(1) DEFAULT NULL, PRIMARY KEY (`id`), KEY `id_card` (`id_card`), KEY `name_age` (`name`,`age`) ) ENGINE=InnoDB 如果说有一个需求时根据身份证号码查询他的名字,这个联合索引就有意义。查询这个联合索引就不需要进行回表。

【SpringCloud Alibaba系列】Dubbo基础入门篇

文章目录 Dubbo-基础入门篇一、分布式系统中的相关概念1. 大型互联网项目架构目标(1)特点(2)衡量网站的性能指标(3)目标 2. 集群和分布式3. 架构演进(1)单体架构(2)垂直架构(3)分布式架构(4)SOA架构(5)微服务架构 二、Dubbo概述1. Dubbo概念2. Dubbo架构3. Dubbo运行流程 三、dubbo快速入门1. Zookeeper安装(1)下载安装(2) 配置启动 2. Spring和SpringMVC整合-本地调用3. 服务提供者4. 服务消费者 Dubbo-基础入门篇 学习目标 分布式系统中的相关概念Dubbo概述Dubbo快速入门Dubbo高级特性 Dubbo是一款高性能、轻量级的开源Java RPC框架,提供面向接口代理的高性能RPC调用、智能负载均衡、服务自动注册和发现、运行期流量调度、可视化服务治理和运维等功能。 一、分布式系统中的相关概念 1. 大型互联网项目架构目标 (1)特点 互联网项目特点: 用户多流量大并发高海量数据易受攻击功能繁琐变更快 (2)衡量网站的性能指标 响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间。并发数:指系统同时能处理的请求数量。 并发连接数:指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器连接的总TCP数量。请求数:也称为QPS(Query Per Second)指每秒多少请求。并发用户数:单位时间内有多少用户。 吞吐量:指单位时间内系统能处理的请求数量。 Qps:Query Per Second每秒查询数。TPS:Transactions Per Second每秒事务数。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。一个页面的一次访问,只会形成一个TPS;但一次页面请求,可能产生多次对服务器的请求,就会有多个QPS。QPS>=并发连接数>= TPS (3)目标 高性能:提供快速的访问体验。高可用:网站服务一直可以正常访问。可伸缩:通过硬件增加/减少,提高/降低处理能力。高可扩展:系统间耦合低,方便的通过新增/移除方式,增加/减少新的功能/模块。安全性:提供网站安全访问和数据加密,安全存储等策略。敏捷性:随需应变,快速响应。 2. 集群和分布式 集群:很多“人”一起,干一样的事。 一个业务模块,部署在多台服务器上。集群就是同一个业务模块搭载到多个服务器上,配合负载均衡,一个服务器坏了,另一个服务器依旧可以使用这个部署的模块。 分布式:很多“人”一起,千不一样的事。这些不一样的事,合起来是一件大事。 一个大的业务系统,拆分为小的业务模块,分别部署在不同的机器上。 3. 架构演进 (1)单体架构 单体架构:把所有的功能模块都放在一起,部署在服务器上,形成一个app。 部署在一个tomcat服务器上,叫做单机单体架构;也可以部署在多个服务器上,称为多机单体架构。 优点: 简单:开发部署都很方便,小型项目首选。 缺点: 项目启动慢:同时启动所有模块,项目启动时间长。可靠性差:所有模块部署在一起,一个功能模块挂了,其他相关模块也跟着挂。可伸缩性差:如果某个模块访问量很大,期望对该模块进行扩展,但所有模块部署在一起没法扩展,只能部署两台服务器才可扩展。扩展性和可维护性差性能低 (2)垂直架构 垂直架构是指将单体架构中的多个模块拆分为多个独立的项目。形成多个独立的单体架构。垂直架构存在的问题:重复功能太多。(各模块之间无法通信,无法远程调用) (3)分布式架构 分布式架构是指在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其他调用者消费,以实现服务的共享和重用。分布式架构:将重复的公共模块服务抽取出来,形成一个独立的服务。需要用到该功能模块的服务直接调用它即可。此时这个公共模块被称为服务提供者,而调用它的app模块被称为服务消费者。RPC:Remote Procedure Call 远程过程调用。有非常多的协议和技术来都实现了RPC的过程。比如:HTTPREST风格,JavaRMl规范、WebService SOAP协议.Hession等等。 分布式架构存在的问题: 服务提供方一旦产生变更,所有消费方都需要变更。 (4)SOA架构 SOA:(Service-Oriented Architecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。ESB:(Enterparise Servce Bus) 企业服务总线,服务中介。主要是提供了一个服务与服务之间的交互和治理功能。ESB包含的功能如:负载均衡,流量控制,加密处理,服务的监控,异常处理,监控告急等等。 (5)微服务架构 微服务架构是在SOA上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。微服务架构=80%的SOA服务架构思想+100%的组件化架构思想+80%的领域建模思想 特点:

项目配置Babel

当前@babel/core最新版本是:7.20.12 当前@babel/preset-env最新版本是:7.20.2 我们知道:core-js是一种polyfill,它提供了旧版本浏览器缺失的所有的ES6+ API的方法与实现。 在这里,以及下文,我们把通过引入core-js的某个模块,来实现旧版本浏览器不支持的某个ES6+ API的过程,叫做垫平。 我们看看core-js这个包里面的主要一些模块: pic_5.png es:里面只包含有稳定的ES功能。 proposals:里面包含所有stage阶段的API stable:它里面包含了,只有稳定的ES功能跟网络标准 所以,我们可以这么使用: 当我们只需要垫平某个稳定的ES6+ API,我们可以用es这个文件夹里的polyfill来垫平 (import X from 'es/xx') 当我们需要用到提案阶段的API时,我就用proposals这个文件夹里的polyfill来垫平(import X from 'proposals/xx') 当我们想垫平所有稳定版本的ES6+ API,可以导入用stable文件夹(import 'core-js/stable') 当我们想垫平所有的ES6+ API(包括提案阶段),可以直接import 'core-js' Babel大体由两个功能组成: 编译ES6+最新语法(let、class、() => {}等) 实现旧版本浏览器不支持的ES6+的API(Promise、Symbol、Array.prototype.includes等) @babel/preset-env有以下两个功能: 它只编译ES6+语法 它并不提供polyfill,但是可以通过配置我们代码运行的目标环境,从而控制polyfill的导入跟语法编译,使ES6+的新特性可以在我们想要的目标环境中顺利运行 @babel/plugin-transform-runtime也有以下两个功能: @babel/runtime跟@babel/plugin-transform-runtime两者配合,可以减少打包体积 也有一个配置功能,用来处理polyfill如何垫平 如果我们想要在旧浏览器用到ES6+ API时,我们应该安装3版本的core-js(或者后续更高版本的); 那我们可以很清楚的知道: 实现Babel第一个功能:我们用@babel/preset-env就可以了 实现Babel第二个功能:我们就需要用core-js这个包来提供polyfill,并与@babel/preset-env或者@babel/plugin-transform-runtime的配置功能相互配合使用 我们先来看看@babel/preset-env的配置项有哪些: // babel.config.js const presets = [ [ '@babel/preset-env', { modules, targets, corejs, useBuiltIns, spec, loose, debug, bugfixes, include, exclude, forceAllTransforms, configPath, ignoreBrowserslistConfig, browserslistEnv, shippedProposals } ] ]; module.

服务器安装配置lldp协议

服务器安装配置lldp协议 1.安装lldp:yum install –y lldpad 2.启动lldpad服务:systemctl start lldpad | 开机启动:systemctl enable lldpad 3.启动网卡脚本: #!/bin/bash for i in $(ls /sys/class/net/ | grep “em|eth|p”);do echo “enabling lldp for interface: $i”; lldptool set-lldp -i $i adminStatus=rxtx; lldptool -T -i $i -V sysName enableTx=yes; lldptool -T -i $i -V portDesc enableTx=yes ; lldptool -T -i $i -V sysDesc enableTx=yes; lldptool -T -i $i -V sysCap enableTx=yes; lldptool -T -i em1 -V mngAddr ipv4=‘hostname -I’;