Lan小站-嗯，不错！ - 转载文章
type: channel
link: https://www.lanol.cn/category-reprinted/
description: 网上冲浪时看到的有用的文章
items: Chrome：此扩展程序不再受支持，因此已停用，Mac解决方案
items: 哈夫曼树（最优二叉树）的概念以及构造
items: 利用js去除无限debugger
items: 在pycharm中为函数或方法以及参数添加注释
items: 关于Python的面试题
items: Python面试宝典-基础篇-2020
items: 数据库事务的概念及其实现原理
items: vite2.1 最新alias别名设置方式
items: 论文格式
items: python PIL/cv2/base64相互转换

Chrome：此扩展程序不再受支持，因此已停用，Mac解决方案
type: item
date: 2025-07-31T09:55:00+08:00
description: 将浏览器更新到最新版，确保在 v138.0.7204.101（含）以上该选项设置为启用 Enabledchrome://flags/#temporary-unexpire-flags-m137启用后重启浏览器使之前的修改生效以下选项全部设置为禁用 Disabledchrome://flags/#extension-manifest-v2-deprecation-warningchrome://flags/#extension-manifest-v2-deprecation-disabledchrome://flags/#extension-manifest-v2-deprecation-unsupported以下选项设置为启用 Enabled 注意：这是解决方案二的参数，建议顺便开启，不开启也可以正常使用chrome://flags/#allow-legacy-mv2-extensionssudo mkdir -p "/Library/Managed Preferences" && sudo tee "/Library/Managed Preferences/com.google.Chrome.plist" >/dev/null <<EOF <?xml version="1.0" encoding="UTF-8"?> <plist version="1.0"> <dict> <key>ExtensionManifestV2Availability</key> <integer>2</integer> </dict> </plist> EOFFrom LinuxDo

哈夫曼树（最优二叉树）的概念以及构造
type: item
date: 2022-04-08T11:30:00+08:00
description: 哈夫曼树产生的背景在实际生活和生产应用中，我们往往会遇到综合比较一系列的离散量的问题；比如说车站根据包裹的重量以及旅途的长短来确定携带行李的价格，或者我们根据一定的重量范围来给一箱铁球进行分类。这一类问题的解决思路是：1、 根据实际需要划分出分类的标准；2、 按一定的顺序（算法）将实际的数据归到相应的类别里。一般情况下，我们所确定的分类标准并不能保证每一类的数据量是平均分配的；也就是说，由于每一类数据出现的概率不同，造成当采用不同的算法时所需的运算次数的不同。当然，在实际生产生活中，我们更希望得到一种最快，最简洁同时也不会产生歧义的算法。在这个背景下，哈夫曼树以及哈夫曼算法应运而生。准备概念森林：森林由n(n>=2)个二叉树组成，它的遍历可以归结为二叉树的遍历，即以其中一棵二叉树的根结点为森林的“根结点”，之后每一个二叉树的根结点都依次相连，由此组成了一个大的二叉树——森林向二叉树的转化。路径和路径的长度：从树中的一个结点到另一个结点之间的分支构成这两个结点之间的路径，路径上的分支数目称作路径长度。对于一个二叉树，其在第n层上的结点到根结点的路径长度为n-1。结点的权：根据应用的需要给树的结点赋的权值。结点的带权路径长度：从根结点到该结点的路径长度与该几点权的乘积。树的带权路径长度（WPL）：树中所有叶子的带权路径长度之和。哈夫曼二叉树及其构造有了以上的概念，哈夫曼二叉树的定义就变得水到渠成。所谓哈夫曼二叉树（最优二叉树），就是带权路径长度最小的二叉树（注意这里的带权路径）。因为树的带权路径长度只与所有叶子的带权路径长度有关，所以对于一个哈夫曼树，其真正其作用的数据是存在于叶子上。再回到问题产生的根源。我们说在现实的分类中，每一类数据出现的概率不尽相同；这些数据出现的概率可以被看做哈夫曼树中叶子的权值。为了获取最短的路径，也就是带权路径长度最短的二叉树，我们希望那些权值低的数据拥有相对较长的对根结点的路径长度。根据这一思路，我们可以从一群离散的数据中构造出一颗哈夫曼树，具体的算法如下：根据给定的n个权值{w1 ,w2 ,...,wn }构造n棵二叉树的集合F={T1 ,T2 ,...,Tn }，其中每棵二叉树Ti中只有一个带权为wi的根结点，其左右子树均空。在F中选取两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树，且置新的二叉树的根 结点的权值为其左、右子树上根结点的权值之 和。在F中删除这两棵树，同时将新得到的二叉树加入F中。重复2和3，直到F中只含一棵树为止。这棵树便是最优二叉树。例如，有权值分别为 5、10、15、20、25、40的结点，根据以上算法构造出一个哈夫曼树。取这六个树中最小的两个树5、10连成一个二叉树，其权值为15；此时森林里的树变为15（5、10）、15、20、25、40。取这五个树中最小的两个树（15（5、10）、15），构成一个新的二叉树30（（5、10）、15）；此时森立里的树变为20、25、30（（5、10）、15）、40。继续上述过程，得到一个新的二叉树45（20、25）；此时的森林变为30（（5、10）、15）、40、45（20、25）。继续得到二叉树70（（5、10）、15）、40）；则森林里只剩下两棵树：70（（5、10）、15）、40）与45（20、25）。最后将这两棵二叉树合并成为一棵二叉树115（（（5、10）、15）、40）、（20、25）），完成了哈夫曼树的构造。计算WPL=(5+10)4+153+402+(20+25)2=275。以上便是哈夫曼树（最优二叉树）的相关概念和构造方法。根据最后二叉树可以解决类似于文章开头提到的一些实际问题。同时还另外引申出了哈夫曼编码——即不等长编码，实现数据总长度的最优化。

利用js去除无限debugger
type: item
date: 2022-03-14T09:22:13+08:00
description: csdn看见的，还别说，挺好用//去除无限debugger Function.prototype.__constructor_back = Function.prototype.constructor ; Function.prototype.constructor = function() { if(arguments && typeof arguments[0]==='string'){ //alert("new function: "+ arguments[0]); if( "debugger" === arguments[0]){ //arguments[0]="consoLe.Log(\"anti debugger\");"; //arguments[0]=";"; return } } return Function.prototype.__constructor_back.apply(this,arguments); }原文链接：https://blog.csdn.net/qq_39799322/article/details/119275806

在pycharm中为函数或方法以及参数添加注释
type: item
date: 2022-02-25T16:35:44+08:00
description: 一、在函数后换行，然后直接输入三个双引号后回车；二、在函数名中键入数遍光标，左上角亮起小灯泡，点击小灯泡选中第二行内容在"""后添加函数注释，以及参数注释然后再引用函数时，选中函数，Ctrl q 即可显示函数以及参数的注释了原文链接：https://www.cnblogs.com/hls-code/p/14811511.html

关于Python的面试题
type: item
date: 2022-02-22T09:19:00+08:00
description: Python语言特性1 Python的函数参数传递看两个例子:a = 1 def fun(a): a = 2 fun(a) print a # 1a = [] def fun(a): a.append(1) fun(a) print a # [1]所有的变量都可以理解是内存中一个对象的“引用”，或者，也可以看似c中void*的感觉。通过id来看引用a的内存地址可以比较理解：a = 1 def fun(a): print "func_in",id(a) # func_in 41322472 a = 2 print "re-point",id(a), id(2) # re-point 41322448 41322448 print "func_out",id(a), id(1) # func_out 41322472 41322472 fun(a) print a # 1注：具体的值在不同电脑上运行时可能不同。可以看到，在执行完a = 2之后，a引用中保存的值，即内存地址发生变化，由原来1对象的所在的地址变成了2这个实体对象的内存地址。而第2个例子a引用保存的内存值就不会发生变化：a = [] def fun(a): print "func_in",id(a) # func_in 53629256 a.append(1) print "func_out",id(a) # func_out 53629256 fun(a) print a # [1]这里记住的是类型是属于对象的，而不是变量。而对象有两种,“可更改”（mutable）与“不可更改”（immutable）对象。在python中，strings, tuples, 和numbers是不可更改的对象，而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点)当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference2 Python中的元类(metaclass)这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python3 @staticmethod和@classmethodPython其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:def foo(x): print "executing foo(%s)"%(x) class A(object): def foo(self,x): print "executing foo(%s,%s)"%(self,x) @classmethod def class_foo(cls,x): print "executing class_foo(%s,%s)"%(cls,x) @staticmethod def static_foo(x): print "executing static_foo(%s)"%x a=A() 这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.\实例方法类方法静态方法a = A()a.foo(x)a.class_foo(x)a.static_foo(x)A不可用A.class_foo(x)A.static_foo(x)更多关于这个问题:http://stackoverflow.com/que…

Python面试宝典-基础篇-2020
type: item
date: 2022-02-22T09:16:00+08:00
description: Python面试宝典 - 基础篇 - 2020题目001: 在Python中如何实现单例模式。点评：单例模式是指让一个类只能创建出唯一的实例，这个题目在面试中出现的频率极高，因为它考察的不仅仅是单例模式，更是对Python语言到底掌握到何种程度，建议大家用装饰器和元类这两种方式来实现单例模式，因为这两种方式的通用性最强，而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。方法一：使用装饰器实现单例模式。from functools import wraps def singleton(cls): """单例类装饰器""" instances = {} @wraps(cls) def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class President: pass扩展：装饰器是Python中非常有特色的语法，用一个函数去装饰另一个函数或类，为其添加额外的能力。通常通过装饰来实现的功能都属横切关注功能，也就是跟正常的业务逻辑没有必然联系，可以动态添加或移除的功能。装饰器可以为代码提供缓存、代理、上下文环境等服务，它是对设计模式中代理模式的践行。在写装饰器的时候，带装饰功能的函数（上面代码中的wrapper函数）通常都会用functools模块中的wraps再加以装饰，这个装饰器最重要的作用是给被装饰的类或函数动态添加一个__wrapped__属性，这个属性会将被装饰之前的类或函数保留下来，这样在我们不需要装饰功能的时候，可以通过它来取消装饰器，例如可以使用President = President.__wrapped__来取消对President类做的单例处理。需要提醒大家的是：上面的单例并不是线程安全的，如果要做到线程安全，需要对创建对象的代码进行加锁的处理。在Python中可以使用threading模块的RLock对象来提供锁，可以使用锁对象的acquire和release方法来实现加锁和解锁的操作。当然，更为简便的做法是使用锁对象的with上下文语法来进行隐式的加锁和解锁操作。方法二：使用元类实现单例模式。class SingletonMeta(type): """自定义单例元类""" def __init__(cls, *args, **kwargs): cls.__instance = None super().__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super().__call__(*args, **kwargs) return cls.__instance class President(metaclass=SingletonMeta): pass扩展：Python是面向对象的编程语言，在面向对象的世界中，一切皆为对象。对象是通过类来创建的，而类本身也是对象，类这样的对象是通过元类来创建的。我们在定义类时，如果没有给一个类指定父类，那么默认的父类是object，如果没有给一个类指定元类，那么默认的元类是type。通过自定义的元类，我们可以改变一个类默认的行为，就如同上面的代码中，我们通过元类的__call__魔术方法，改变了President类的构造器那样。补充：关于单例模式，在面试中还有可能被问到它的应用场景。通常一个对象的状态是被其他对象共享的，就可以将其设计为单例，例如项目中使用的数据库连接池对象和配置对象通常都是单例，这样才能保证所有地方获取到的数据库连接和配置信息是完全一致的；而且由于对象只有唯一的实例，因此从根本上避免了重复创建对象造成的时间和空间上的开销，也避免了对资源的多重占用。再举个例子，项目中的日志操作通常也会使用单例模式，这是因为共享的日志文件一直处于打开状态，只能有一个实例去操作它，否则在写入日志的时候会产生混乱。题目002：不使用中间变量，交换两个变量a和b的值。点评：典型的送人头的题目，通常交换两个变量需要借助一个中间变量，如果不允许使用中间变量，在其他编程语言中可以使用异或运算的方式来实现交换两个变量的值，但是Python中有更为简单明了的做法。方法一：a = a ^ b b = a ^ b a = a ^ b方法二：a, b = b, a扩展：需要注意，a, b = b, a这种做法其实并不是元组解包，虽然很多人都这样认为。Python字节码指令中有ROT_TWO指令来支持这个…

数据库事务的概念及其实现原理
type: item
date: 2022-02-10T10:13:00+08:00
description: 1.认识事务1.1为什么需要数据库事务转账是生活中常见的操作,比如从A账户转账100元到B账号。站在用户角度而言,这是一个逻辑上的单一操作,然而在数据库系统中,至少会分成两个步骤来完成:将A账户的金额减少100元将B账户的金额增加100元在这个过程中可能会出现以下问题:转账操作的第一步执行成功,A账户上的钱减少了100元,但是第二步执行失败或者未执行便发生系统崩溃,导致B账户并没有相应增加100元。转账操作刚完成就发生系统崩溃,系统重启恢复时丢失了崩溃前的转账记录。同时又另一个用户转账给B账户,由于同时对B账户进行操作,导致B账户金额出现异常。为了便于解决这些问题,需要引入数据库事务的概念。1.2什么是数据库事务定义:数据库事务是构成单一逻辑工作单元的操作集合一个典型的数据库事务如下所示BEGIN TRANSACTION //事务开始 SQL1 SQL2 COMMIT/ROLLBACK //事务提交或回滚关于事务的定义有几点需要解释下：数据库事务可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体。构成逻辑整体的这些数据库操作,要么全部执行成功,要么全部不执行。构成事务的所有操作,要么全都对数据库产生影响,要么全都不产生影响,即不管事务是否执行成功,数据库总能保持一致性状态。以上即使在数据库出现故障以及并发事务存在的情况下依然成立。1.3 事务如何解决问题对于上面的转账例子,可以将转账相关的所有操作包含在一个事务中BEGIN TRANSACTION A账户减少100元 B账户增加100元 COMMIT当数据库操作失败或者系统出现崩溃,系统能够以事务为边界进行恢复,不会出现A账户金额减少而B账户未增加的情况。当有多个用户同时操作数据库时,数据库能够以事务为单位进行并发控制,使多个用户对B账户的转账操作相互隔离。事务使系统能够更方便的进行故障恢复以及并发控制,从而保证数据库状态的一致性。1.4 事务的ACID特性以及实现原理概述原子性(Atomicity):事务中的所有操作作为一个整体像原子一样不可分割，要么全部成功,要么全部失败。一致性(Consistency):事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态。一致性状态是指:系统的状态满足数据的完整性约束(主码,参照完整性,check约束等)系统的状态反应数据库本应描述的现实世界的真实状态,比如转账前后两个账户的金额总和应该保持不变。隔离性(Isolation):并发执行的事务不会相互影响,其对数据库的影响和它们串行执行时一样。比如多个用户同时往一个账户转账,最后账户的结果应该和他们按先后次序转账的结果一样。持久性(Durability):事务一旦提交,其对数据库的更新就是持久的。任何事务或系统故障都不会导致数据丢失。在事务的ACID特性中,C即一致性是事务的根本追求,而对数据一致性的破坏主要来自两个方面事务的并发执行事务故障或系统故障数据库系统是通过并发控制技术和日志恢复技术来避免这种情况发生的。并发控制技术保证了事务的隔离性,使数据库的一致性状态不会因为并发执行的操作被破坏。日志恢复技术保证了事务的原子性,使一致性状态不会因事务或系统故障被破坏。同时使已提交的对数据库的修改不会因系统崩溃而丢失,保证了事务的持久性。2 并发异常与并发控制技术2.1 常见的并发异常在讲解并发控制技术前,先简单介绍下数据库常见的并发异常脏写：脏写是指事务回滚了其他事务对数据项的已提交修改,比如下面这种情况在事务1对数据A的回滚,导致事务2对A的已提交修改也被回滚了丢失更新：丢失更新是指事务覆盖了其他事务对数据的已提交修改,导致这些修改好像丢失了一样事务1和事务2读取A的值都为10,事务2先将A加上10并提交修改,之后事务2将A减少10并提交修改,A的值最后为,导致事务2对A的修改好像丢失了一样脏读：脏读是指一个事务读取了另一个事务未提交的数据在事务1对A的处理过程中,事务2读取了A的值,但之后事务1回滚,导致事务2读取的A是未提交的脏数据。不可重复读：不可重复读是指一个事务对同一数据的读取结果前后不一致。脏读和不可重复读的区别在于:前者读取的是事务未提交的脏数据,后者读取的是事务已经提交的数据,只不过因为数据被其他事务修改过导致前后两次读取的结果不一样,比如下面这种情况由于事务2对A的已提交修改,事务1前后两次读取的结果不一致幻读：幻读是指事务读取某个范围的数据时，因为其他事务的操作导致前后两次读取的结果不一致。幻读和不可重复读的区别在于,不可重复读是针对确定的某一行数据而言,而幻读是针对不确定的多行数据。因而幻读通常出现在带有查询条件的范围查询中,比如下面这种情况事务1查询A<5的数据,由于事务2插入了一条A=4的数据,导致事务1两次查询得到的结果不一样2.2 事务的隔离…

vite2.1 最新alias别名设置方式
type: item
date: 2021-08-28T15:01:43+08:00
description: vite.config.js 别名配置resolve.alias类型： Record<string, string> | Array<{ find: string | RegExp, replacement: string }>将会被传递到 @rollup/plugin-alias 作为 entries 的选项。也可以是一个对象，或一个 { find, replacement } 的数组.当使用文件系统路径的别名时，请始终使用绝对路径。相对路径的别名值会被原封不动地使用，因此无法被正常解析。更高级的自定义解析方法可以通过 插件 实现。import { defineConfig } from 'vite' import path from "path"; import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ resolve: { alias: { "@": path.resolve(__dirname, "src"), "components": path.resolve(__dirname, "src/components"), "styles": path.resolve(__dirname, "src/styles"), "plugins": path.resolve(__dirname, "src/plugins"), "views": path.resolve(__dirname, "src/views"), "layouts": path.resolve(__dirname, "src/layouts"), "utils": path.resolve(__dirname, "src/utils"), "apis": path.resolve(__dirname, "src/apis"), "dirs": path.resolve(__dirname, "src/directives"), }, }, plugins: [vue()], });或者 数组的形式 import { defineConfig } from 'vite' import path from "path"; import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ resolve: { alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }, { find: 'components', replacement: path.resolve(__dirname, 'src/components') } ], }, plugins: [vue()], });注意要导入path啊，还有vite.config配置要关项目重启————————————————版权声明：本文为CSDN博主「yusirxiaer」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。原文链接：https://blog.csdn.net/yusirxiaer/article/details/115440738

论文格式
type: item
date: 2021-07-19T16:56:00+08:00
description: 结构论文一般由题名、作者、目录、摘要、关键词、正文、参考文献和附录等部分组成，其中部分组成（例如附录）可有可无。论文各组成的排序为：题名、作者、摘要、关键词、英文题名、英文摘要、英文关键词、正文、参考文献、附录和致谢。题目题目规范题名应简明、具体、确切，能概括论文的特定内容，有助于选定关键词，符合编制题录、索引和检索的有关原则。命题方式简明扼要，提纲挈领。英文题名方法英文题名以短语为主要形式，尤以名词短语最常见，即题名基本上由一个或几个名词加上其前置和（或）后置定语构成；短语型题名要确定好中心词，再进行前后修饰。各个词的顺序很重要，词序不当，会导致表达不准。一般不要用陈述句，因为题名主要起标示作用，而陈述句容易使题名具有判断式的语义，且不够精炼和醒目。少数情况（评述性、综述性和驳斥性）下可以用疑问句做题名，因为疑问句有探讨性语气，易引起读者兴趣。同一篇论文的英文题名与中文题名内容上应一致，但不等于说词语要一一对应。在许多情况下，个别非实质性的词可以省略或变动。国外科技期刊一般对题名字数有所限制，有的规定题名不超过2行，每行不超过42个印刷符号和空格；有的要求题名不超过14个词。这些规定可供我们参考。在论文的英文题名中。凡可用可不用的冠词均不用。作者书名规范作者署名置于题名下方，团体作者的执笔人，也可标注于篇首页脚位置。有时，作者姓名亦可标注于正文末尾。示例：王军 ××师范大学物理系，北京 100875； 张红 ××教育学院物理系，北京 100011（注释：后面的数字是该学院的邮编号码）目录目录是论文中主要段落的简表。（短篇论文不必列目录）摘要摘要是文章主要内容的摘录，要求短、精、完整。字数少可几十字，多不超过三百字为宜。随着计算机技术和因特网的迅猛发展，网上查询、检索和下载专业数据已成为当前科技信息情报检索的重要手段，对于网上各类全文数据库或文摘数据库，论文摘要的索引是读者检索文献的重要工具，为科技情报文献检索数据库的建设和维护提供方便。摘要是对论文综合的介绍，使人了解论文阐述的主要内容。论文发表后，文摘杂志或各种数据库对摘要可以不作修改或稍作修改而直接利用，让读者尽快了解论文的主要内容，以补充题名的不足，从而避免他人编写摘要可能产生的误解、欠缺甚至错误。所以论文摘要的质量高低，直接影响着论文的被检索率和被引频次。规范摘要是对论文的内容不加注释和评论的简短陈述，要求扼要地说明研究工作的目的、研究方法和最终结论等，重点是结论，是一篇具有独立性和完整性的短文，可以引用、推广。关键词关键词是从论文的题名、提要和正文中选取出来的，是对表述论文的中心内容有实质意义的词汇。关键词是用作计算机系统标引论文内容特征的词语，便于信息系统汇集，以供读者检索。每篇论文一般选取3-8个词汇作为关键词，另起一行，排在“摘要”的左下方。主题词是经过规范化的词，在确定主题词时，要对论文进行主题分析，依照标引和组配规则转换成主题词表中的规范词语。（参见《汉语主题词表》和《世界汉语主题词表》）。规范关键词是反映论文主题概念的词或词组，通常以与正文不同的字体字号编排在摘要下方。一般每篇可选3~8个，多个关键词之间用分号分隔，按词条的外延（概念范围）层次从大到小排列。关键词一般是名词性的词或词组，个别情况下也有动词性的词或词组。应标注与中文关键词对应的英文关键词。编排上中文在前，外文在后。中文关键词前以“关键词：”或“[关键词]”作为标识；英文关键词前以“Key words：”作为标识。关键词应尽量从国家标准《汉语主题词表》中选用；未被词表收录的新学科、新技术中的重要术语和地区、人物、文献等名称，也可作为关键词标注。关键词应采用能覆盖论文主要内容的通用技术词条。关键词方法关键词的一般选择方法是：由作者在完成论文写作后，从其题名、层次标题和正文（出现频率较高且比较关键的词）中选出来。论文正文要点引言：引言又称前言、序言和导言，用在论文的开头。引言一般要概括地写出作者意图，说明选题的目的和意义，并指出论文写作的范围。引言要短小精悍、紧扣主题。论文正文：正文是论文的主体，正文应包括论点、论据、论证过程和结论。主体部分包括以下内容：a.提出问题-论点；b.分析问题-论据和论证；c.解决问题-论证方法与步骤；d.结论。为了做到层次分明、脉络清晰，常常将正文部分分成几个大的段落。这些段落即所谓逻辑段，一个逻辑段可包含几个小逻辑段，一个小逻辑段可包含一个或几个自然段，使正文形成若干层次。论文的层次不宜过多，一般不超过五级。要求以毕业论文为例，现说明论文正文版面格式：①正文部分与“关键词”行间空两行；②汉语正文文字采用小四号宋体；正文英语正文文字采用Times New Roman12号，标题汉语采用四号黑体，标题英语采用Times New Roman14号，每段首起空两格，1.2…

python PIL/cv2/base64相互转换
type: item
date: 2021-05-28T08:36:00+08:00
description: PIL和cv2是python中两个常用的图像处理库，PIL一般是anaconda自带的，cv2是opencv的python版本。base64在网络传输图片的时候经常用到。PIL读取、保存图片方法from PIL import Image img = Image.open(img_path) img.save(img_path2)cv2读取、保存图片方法import cv2 img = cv2.imread(img_path) cv2.imwrite(img_path2, img)图片文件打开为base64import base64 def img_base64(img_path): with open(img_path,"rb") as f: base64_str = base64.b64encode(f.read()) return base64_str1、PIL和cv2转换PIL转cv2import cv2 from PIL import Image import numpy as np def pil_cv2(img_path): image = Image.open(img_path) img = cv2.cvtColor(np.asarray(image),cv2.COLOR_RGB2BGR) return imgcv2转PILimport cv2 from PIL import Image def cv2_pil(img_path): image = cv2.imread(img_path) image = Image.fromarray(cv2.cvtColor(image,cv2.COLOR_BGR2RGB)) return image2、PIL和base64转换##PIL转base64 import base64 from io import BytesIO def pil_base64(image): img_buffer = BytesIO() image.save(img_buffer, format='JPEG') byte_data = img_buffer.getvalue() base64_str = base64.b64encode(byte_data) return base64_strbase64转PILimport base64 from io import BytesIO from PIL import Image def base64_pil(base64_str): image = base64.b64decode(base64_str) image = BytesIO(image) image = Image.open(image) return imagecv2和base64转换import cv2def cv2_base64(image): base64_str = cv2.imencode('.jpg',image)[1].tostring() base64_str = base64.b64encode(base64_str)return base64_str base64转cv2import base64 import numpy as np import cv2def base64_cv2(base64_str): imgString = base64.b64decode(base64_str) nparr = np.fromstring(imgString,np.uint8) image = cv2.imdecode(nparr,cv2.IMREAD_COLOR) return image