opencv与matplotlib在Python下读入图片的区别
1.翻转numpy矩阵。这种做法不太直观,平时建议不要这么使用。但是很有学习的必要,因为对于矩阵操作的时候,进行翻转是很常见的。因此有必要学习下:
import matplotlib.pyplot as plt
import cv2
img = cv2.imread("./lena.jpeg")
img = img[:,:,::-1]
# img = img[..., ::-1]
plt.imshow(img)
plt.show()
2.利用cv2提供的BGR2RGB方式:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
def normal(x, mu, sigma):
p = 1 / math.sqrt(2 * math.pi * sigma**2)
return p * np.exp(-0.5 / sigma**2 * (x - mu)**2)
x = np.arange(-7, 7, 0.1)
# 均值和标准差对
params = [(0, 1), (0, 2), (3, 1)]
res = len([normal(x, mu, sigma) for mu, sigma in params])
y = [normal(x, mu, sigma) for mu, sigma in params]
plt.plot(x, y[0])
plt.plot(x, y[1])
plt.plot(x, y[2])
plt.legend([f"mean {mean}, std {std}" for mean, std in params])
plt.show()
# plt.savefig("normal.jpg")
labelme标注快捷键
A 上一张图片
D 下一张图片
ctrl + E 换标签
ctrl + J 调整标签
broadcasting操作,Numpy规定,两个数组的shape必须相等或者其中一个为1才可以执行广播操作。
Numpy中的切片和golang中的切片比较像,它代表原数组一段区间的引用,而不是拷贝。也就是说我们修改切片中的内容是会影响原数组的,我们对一个切片赋值,明显可以发现原数组的对应位置发生了改变。
如果想要拷贝一份切片出来,可以使用 arr[3:10].copy()
numpy的索引:
拿3维数组举例,如果我们访问的时候只用一个下标,那么我们获得的是一个二维数组。如果使用两个下标,则获得的是一个一维数组。对于更高的维度也是同样。
https://zhuanlan.zhihu.com/p/125696272
# 生成 2行2列 [0, 1)均匀分布的随机数组
np.random.rand(2, 2)
# 生成 标准正态分布 的数组,均值为0,方差为1
np.random.randn(3,2)
# 生成可以指定范围的随机整数数组
np.random.randint(2,10,size=(2,2))
# 生成数值成正态分布(可指定平均值、标准差)的数组
np.random.normal(loc=1,scale=2,size=(2, 2))
a = np.arange(60).reshape((1, 2, 3, 10))
print(a)
# 意思是只取维度为10的索引为0, 1的这两个元素
print(a[..., :2])
print("-"*30)
print(a[..., 2])
# 输出为:
[[[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]]
[[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]]]]
[[[[ 0 1]
[10 11]
[20 21]]
[[30 31]
[40 41]
[50 51]]]]
------------------------------
[[[ 2 12 22]
[32 42 52]]]
x = np.random.randint(50, size=(3, 4, 5))
print("x:\n", x)
print("axis=2: \n", np.amax(x, 2))
print("axis=1: \n", np.amax(x, 1))
print("axis=0: \n", np.amax(x, 0))
"""
axis=2:
[[48 44 47 41]
[43 21 48 30]
[48 47 44 47]]
axis=1:
[[46 44 48 47 32]
[48 32 43 30 45]
[45 31 47 44 48]]
axis=0:
[[29 42 48 43 48]
[45 44 37 27 47]
[48 23 31 47 45]
[37 41 47 30 19]]
"""
注释的一般规则是参数名后跟一个冒号(:),然后再跟一个expression,这个expression可以是任何形式。 返回值的形式是 -> int,annotation可被保存为函数的attributes
# 注意b,a两个参数必须要放在c参数的前面,因为c属于关键字参数
def func(b: str, a: int, c: int = 10) -> "Nothing to see here":
print("Annotations:", func.__annotations__)
func_a = a
func_b = b
func_c = c
print("a = {}, b = {}, c = {}".format(func_a, func_b, func_c))
func("wei", 12)
调用函数时根据函数定义的参数位置来传递参数
def user_info(name, age, gender):
print("姓名:{}, 年龄:{}, 性别:{}".format(name, age, gender))
user_info("张三", 25, "男")
# 输出为:
# 姓名:张三, 年龄:25, 性别:男
通过 “键 = 值” 的形式加以指定
user_info(age=21, name="李四", gender="男")
需要注意的是:函数调用时,如果有位置参数,位置参数必须放在关键字参数的前面,但关键字参数之间不存在先后顺序
包裹(packing)位置传递 / 包裹(packing)关键字传递
def total(a=5, *args, **kwargs):
print('a = ', a)
# 遍历tuple中的所有元素
for i in args:
print(i)
# 遍历dict中的所有元素
for key, value in kwargs.items():
print(key, value)
total(10, "wei", 20, "Tom", 25, Name="Nick", Age=25)
# 或者可以这样写,效果是一样的
kw = {"Name":"Nick", "Age":25} # 要注意此处的 Name 和 Age要写成加引号,而上面是不用加的;而且中间是冒号
total(10, "wei", 20, "Tom", 25, **kw)
# 输出为:
a = 10
wei
20
Tom
25
Name Nick
Age 25
当我们声明一个诸如 *args
的星号参数时,从此处开始直到结束的所有位置参数(Positional Arguments)都将被收集并汇集成一个称为“param”的元组(Tuple)。
类似地,当我们声明一个诸如 **kwargs
的双星号参数时,从此处开始直至结束的所有关键字参数都将被收集并汇集成一个名为 param
的字典(Dictionary)。
使用 assert 可以在出现有异常的代码处直接终止运行,而不用等到程序执行完毕之后抛出异常
多任务的概念:
多任务是指同一时间执行多个任务
多任务的执行方式:
re.match( pattern, string, flags=0 )
match函数从头开始匹配,如果不是起始位置匹配成功的话,match函数的匹配结果就为none。匹配成功,re.match方法返回一个匹配的对象。
pattern:需要匹配的正则表达式;
string:在哪个字符串中进行匹配 ;
flags:标志位(默认为0),它可以控制正则表达式的匹配方式
astr = '11you are 3344 my apple\n 11开心果,you\n66a77'
a = re.match("11", astr)
print(a) #
print(a.group()) # 11
print(a.start()) # 0
print(a.end()) # 2
print(a.span()) # (0, 2)
b = re.match("you", astr)
print(b) # None
re.search(pattern, string, flags=0)
搜索整个字符串,并返回第一个成功的匹配。具体用法同上
re.findall(string)
搜索整个字符串,返回一个list
astr = '11you are 3344 my apple\n 11开心果,you\n66a77'
a = re.findall("\d\d", astr) # 列表形式显示所有的两个数字
print(a)
# ['11', '33', '44', '11', '66', '77']
b = re.findall('\d{2,4}',astr) # 列表形式显示所有的2——4个数字,默认贪婪匹配
print(b)
# ['11', '3344', '11', '66', '77']
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象。
import re
astr = '11you are 3344 my apple\n 11开心果,you\n66a77'
a = re.compile(r"\d\d\d")
print(a.search(astr).group())
# 334
在python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式
进程:一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也即每启动一个进程,操作系统都会给其分配一定的运行资源。
注意:一个程序运行后,至少有一个进程,一个进程默认有一个线程,进程里可以创建多个线程
# 导入进程包
import multiprocessing
import time
def dance():
for i in range(3):
print("跳舞...")
time.sleep(0.5)
def sing():
for i in range(3):
print("唱歌...")
time.sleep(0.5)
# 创建子进程
# group: 进程组
# target: 进程执行的目标任务
# name: 进程名,如果不设置,默认是Precessing_1
dance_process = multiprocessing.Process(target=dance) # 不是target=dance()
dance_process = multiprocessing.Process(target=sing)
# 启动子进程
dance_process.start()
sing_process.start()
# 进程执行是无序的,具体哪个进程先执行是由操作系统决定
调用父类的构造方法
通常情况下,我们在子类中定义了和父类同名的方法,那么子类的方法就会覆盖父类的方法。而super关键字实现了对父类方法的改写,或者说super关键字帮助我们实现了在子类中调用父类的方法
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print("Hello, I am {}".format(self.name))
class Dog(Animal):
def greet(self):
super(Dog, self).greet()
print("wang wang ...")
dog = Dog("Mike")
dog.greet()
os.listdir( ) 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表,其中的参数只有一个,如需要路径叠加,可以用 ( os.path.join( 路径1, 路径2 ) )
import os
path = "D:\\test"
info_1 = os.listdir(path)
print(type(info_1))
# 输出为:,相当于把名字全部放在一个list中
# 只是将path路径下的子文件或子目录的名字放到一个列表中,不去遍历子目录中的文件或目录
for info_2 in os.listdir(path):
print(info_2)
print(type(info_2))
# 输出为:,就相当于是遍历输出列表中的每一元素
# 如果需要检查文件夹下有多少文件,可以用
l = len(os.listdir(path))
from turnsole import paths
import cv2
for fn in paths.list_images(img_dir):
# 这里的 fn 是img_dir下的所有图片路径,包括子文件,已经子目录当中的文件
# 这是方便调用opencv的接口
image = cv2.imread(fn)
返回所有匹配的文件路径列表
import glob
#获取指定目录下的所有图片,list列表中存放的是路径
fn_list = glob.glob(r"/home/qiaoyunhao/*/*.png") #加上r让字符串不转义
#获取上级目录的所有.py文件
f_list = glob.glob(r'../*.py') #相对路径
实现python对象的永久化存储
以存储列表为例:
import pickle
list1 = ["A", "B", "C", "D"]
# 要以 二进制只读 模式打开
with open("./list1.pkl",'wb') as f:
pickle.dump(list1, f)
# 加载,要以 二进制写 的模式
with open("./list1.pkl",'rb') as f:
l_1 = pickle.load(f)
https://zhuanlan.zhihu.com/p/56922793
argparse基本用法_骑着蜗牛向前跑的博客-CSDN博客_argparsehttps://blog.csdn.net/yy_diego/article/details/82851661
描述
Python split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串
语法
str.split(str="", num=string.count(str))
参数
返回值
返回分割后的字符串列表。
for info_2 in os.listdir(path):
print(info_2.split("."))
print(type(info_2.split(".")))
# 输出为:
# ['001', 'txt']
#
# ['002', 'txt']
#
import os
path = "D:\\test"
info_name = sorted(file.split(".")[0] for file in os.listdir(path))
print(info_name)
# 注意这里的 sorted() 函数
dict1 = {"egg": 10, "apple": 20, "orange": 15}
new_dict = {v: k for k, v in dict1.items()}
print(new_dict)
# 输出为:
# {10: 'egg', 20: 'apple', 15: 'orange'}
dict1 = {"apple": 15, "orange": 12}
print(dict1)
dict1["banana"] = 18
print(dict1)
# 输出为:
# {'apple': 15, 'orange': 12}
# {'apple': 15, 'orange': 12, 'banana': 18}
list1 = []
list1.append({})
list1[-1]["banana"] = 10
list1.append({})
list1[-1]["apple"] = 12
print(list1)
# 输出为:
[{'banana': 10}, {'apple': 12}]
temp = {}
for fn in os.listdir("../1025/dir_nosub42"):
temp[fn] = []
for image in os.listdir(os.path.join("../1025/dir_nosub42", fn)):
temp[fn].append(image)
# ------------------------
temp = {
"image" : list(),
"label" : list()
}
temp["image"].append()
dict1 = {"A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70}
dict2 = {"G": 71, "H": 72, "A": "a"}
print(dict1.update(dict2)) # 字典1合并了字典2
print(dict1)
None
{'A': 'a', 'B': 66, 'C': 67, 'D': 68, 'E': 69, 'F': 70, 'G': 71, 'H': 72}
sample(list, k)返回一个长度为k新列表,新列表存放list所产生k个随机唯一的元素,这里的唯一指的是下标索引唯一
import random
list = [1, 2, 3]
print(random.sample(list ,2))
list = ["china","python","sky"]
print(random.sample(list ,2))
list = range(1, 10000)
print(random.sample(list ,5))
输出:
[1, 2]
['python', 'sky']
[6912, 1869, 5991, 721, 3388]
Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
b = ["w", "c", "e", "i"]
print("==".join(b))
# 输出为 w==c==e==i
注意
b = ["w", "c", "e", "i", 1]
print("==".join(b))
# 出现报错信息:
# TypeError: sequence item 4: expected str instance, int found
# 也就是说 b 中不能有int型元素
json_path = "./pascal_voc_classes.json"
assert os.path.exists(json_path), "not found {} path".format(json_path)
# 读取一个 .json 文件
with open(json_path, "r") as json_file:
class_dict = json.load(json_file)
# 这里读到的class_dict是一个字典形式
# 写入一个 .json 文件
results = [{"A": 1}, {"B": 2}, {"C": 3}]
# results = {"A": {"aa": 1, "aa1": 2}, "B": {"bb": 1, "bb1": 2}}
json_str = json.dumps(results, indent=4)
with open(json_path, "w") as json_file:
json_file.write(json_str)
__call__
方法__call__()
。该方法的功能类似于在类中重载 () 运算符,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。
class CLanguage:
# 定义__call__方法
def __call__(self,name,add):
print("调用__call__()方法",name,add)
clangs = CLanguage()
clangs("C语言中文网","http://c.biancheng.net")
# 输出为:调用__call__()方法 C语言中文网 http://c.biancheng.net
random() 方法返回随机生成的一个实数,它在[0,1)范围内。
import random
random.random()
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
我们可以使用 list() 转换来输出列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 ***** 号操作符,可以将元组解压为列表。
>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 返回一个对象
>>> zipped
<zip object at 0x103abc288>
>>> list(zipped) # list() 转换为列表
[(1, 4), (2, 5), (3, 6)]
>>> list(zip(a,c)) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> a1, a2 = zip(*zip(a,b)) # 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式
>>> list(a1)
[1, 2, 3]
>>> list(a2)
[4, 5, 6]
>>>
isinstance()函数来判断一个对象是否是一个已知的类型,类似type()
isinstance() 与 type() 区别:
如果要判断两个类型是否相同推荐使用 isinstance()。
语法:``isinatance(object, classinfo)
参数:
返回值:
如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
>>>a = 2
>>> isinstance (a,int)
True
>>> isinstance (a,str)
False
>>> isinstance (a,(str,int,list)) # 是元组中的一个返回 True
True
python staticmethod 返回函数的静态方法。
该方法不强制要求传递参数,如下声明一个静态方法:
class C(object):
@staticmethod
def f():
print('runoob');
C.f(); # 静态方法无需实例化
cobj = C()
cobj.f() # 也可以实例化后调用
# 输出为:
runoob
runoob