计算机视觉常见问题以及对应代码段

x33g5p2x  于2021-12-06 转载在 其他  
字(5.3k)|赞(0)|评价(0)|浏览(312)

前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。

一、图像增强

图像增强:目的是改善的图像基础画质和视觉效果,主要包括图像去噪、提亮、超分辨率、去模糊等。

1.直方图均衡化

2.直方图正规化

opencv提供灰度图的直方图正规化api,如下所示:

  1. cv2.normalize(src,dst,alpha,beta,normType,dtype,mask)
  1. #coding:utf-8
  2. import cv2 as cv
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
  6. img_norm=cv.normalize(img,dst=None,alpha=350,beta=10,norm_type=cv.NORM_MINMAX)
  7. cv.imshow("img",img)
  8. cv.imshow("img_norm",img_norm)
  9. cv.waitKey(0)
  10. cv.destroyAllWindows()

RGB图像需要自己写,如下所示:

  1. #coding:utf-8
  2. import cv2 as cv
  3. import matplotlib.pyplot as plt
  4. import numpy as np
  5. img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
  6. out_min=0
  7. out_max=255
  8. in_min = np.min(img)
  9. in_max = np.max(img)
  10. a=float(out_max-out_min)/(in_max-in_min)
  11. b=out_min-a*in_min
  12. img_norm = img*a+b
  13. img_norm = img_norm.astype(np.uint8)
  14. cv.imshow("img",img)
  15. cv.imshow("img_norm",img_norm)
  16. cv.waitKey(0)
  17. cv.destroyAllWindows()

二、图像扩增

图像扩增:是属于数据增广大范畴内,主要用于增加训练数据集,让数据集尽可能的多样化,使得训练的模型具有更强的泛化能力,其中图像扩增常用的方式:水平/垂直翻转,旋转,缩放,裁剪,剪切,平移,对比度,色彩抖动,增加噪声等.

1.引入库

代码如下(示例):

2.读入数据

代码如下(示例):

三、OPENCV与PIL

1.cv2.imread()

cv2.imread()。需要注意的是,cv2.imread()以BGR色彩空间而不是RGB返回图像,这意味着您必须重新排列通道轴,例如通过cv2.imread(path)[:, :, ::-1]。

2.PIL读取的图片与OPencv读取的图片格式互转

2.1 PIL.Image转换成OpenCV格式:

  1. import cv2
  2. from PIL import Image
  3. import numpy
  4. image = Image.open("PIL.jpg")
  5. # 下面这句是重点
  6. img = cv2.cvtColor(numpy.asarray(image),cv2.COLOR_RGB2BGR)
  7. cv2.imshow("OpenCV.jpg",img)

2.2 OpenCV转换成PIL.Image格式:

  1. import cv2
  2. from PIL import Image
  3. import numpy
  4. img = cv2.imread("opencv.jpg")
  5. # 下面这句是重点
  6. image = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
  7. image.show()

四、pytorch相关

1. 使用GPU训练前准备

1.1 显卡设置

  1. # 单张显卡
  2. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  3. # 指定多张显卡,比如0,1号显卡
  4. import os
  5. os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
  6. # 也可以在命令行运行代码时设置显卡
  7. CUDA_VISIBLE_DEVICES=0,1 python train.py

1.2 清除显存

  1. torch.cuda.empty_cache()
  2. # 也可以使用在命令行重置GPU的指令
  3. nvidia-smi --gpu-reset -i [gpu_id]

2. 使用GPU训练

1.1 假设模型和数据定义如下

  1. model = Model()
  2. input = dataloader()
  3. output = model(input)

1.2 移动到gpu上:

  1. # solution: 0
  2. device = 'gpu'
  3. model = model.to(device)
  4. data = data.to(device)
  5. # solution: 1
  6. model = model.cuda()
  7. data = data.cuda()

1.3 移动到cpu上:

  1. # solution: 0
  2. device = 'cpu'
  3. model = model.to(device)
  4. data = data.to(device)
  5. # solution: 1
  6. model = model.cpu()
  7. data = data.cpu()

3. 如何多GPU训练

步骤总结(仅针对单服务器多gpu 数据并行 而不是多机器分布式训练):
每次前向传播的时候都会分发模型,用不着反向传播时将梯度loss分发到各个GPU,单独计算梯度,再合并模型。可以就在主GPU 上根据总loss 更新模型的梯度,不用再同步其他GPU上的模型,因为前向传播的时候会分发模型。

DataParallel并行计算只存在在前向传播

  1. import os
  2. import torch
  3. args.gpu_id="2,7" ; #指定gpu id
  4. args.cuda = not args.no_cuda and torch.cuda.is_available() #作为是否使用cpu的判定
  5. #配置环境 也可以在运行时临时指定 CUDA_VISIBLE_DEVICES='2,7' Python train.py
  6. os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id #这里的赋值必须是字符串,list会报错
  7. device_ids=range(torch.cuda.device_count()) #torch.cuda.device_count()=2
  8. #device_ids=[0,1] 这里的0 就是上述指定 2,是主gpu, 1就是7,模型和数据由主gpu分发
  9. if arg.cuda:
  10. #这里将模型复制到gpu ,默认是cuda('0'),即转到第一个GPU 2
  11. model=model.cuda()
  12. if len(device_id)>1:
  13. #前提是model已经.cuda() 了
  14. model=torch.nn.DataParallel(model)
  15. #前向传播时数据也要cuda(),即复制到主gpu里
  16. for batch_idx, (data, label) in pbar:
  17. if args.cuda:
  18. data,label= data.cuda(),label.cuda();
  19. data_v = Variable(data)
  20. target_var = Variable(label)
  21. prediction= model(data_v,target_var,args)
  22. #这里的prediction 预测结果是由两个gpu合并过的,并行计算只存在在前向传播里
  23. #前向传播每个gpu计算量为 batch_size/len(device_ids),等前向传播完了将结果和到主gpu里
  24. #prediction length=batch_size
  25. criterion = nn.CrossEntropyLoss()
  26. loss = criterion(prediction,target_var) #计算loss
  27. optimizer.zero_grad()
  28. loss.backward()
  29. optimizer.step()

之后调用model里的函数 继承的函数可以直接调用 例如model.state_dict() ,model.load_state_dict(torch.load(model_path)…不受影响。但是自己写的函数 要加上.module才行 model.module.forward_getfeature(x)。自己写的函数 不可以并行运算 ,只能在主gpu中运算。DataParallel并行计算仅存在在前向传播。但可以换个思路 写进forward 里或者被forward调用,多返回几个参数不就得了 return feature,predict。
另外需要注意的是当我们需要加载单gpu训练的模型,然后用多gpu训练,这个时候需要在加载模型之后使用DaraPparrarallel,同样的加载多gpu训练得模型需要在加载模型之前就使用DaraPparrarallel。

4. 可复现性

在硬件设备(CPU、GPU)不同时,完全的可复现性无法保证,即使随机种子相同。但是,在同一个设备上,应该保证可复现性。具体做法是,在程序开始的时候固定torch的随机种子,同时也把numpy的随机种子固定。

  1. np.random.seed(0)
  2. torch.manual_seed(0)
  3. torch.cuda.manual_seed_all(0)
  4. torch.backends.cudnn.deterministic = True
  5. torch.backends.cudnn.benchmark = False

5. 张量(Tensor)处理

1.1 张量基本信息:

  1. tensor = torch.randn(3,4,5)
  2. print(tensor.type()) # 数据类型
  3. print(tensor.size()) # 张量的shape,是个元组
  4. print(tensor.dim()) # 维度的数量

1.2 命名张量:
张量命名是一个非常有用的方法,这样可以方便地使用维度的名字来做索引或其他操作,大大提高了可读性、易用性,防止出错。

  1. # 在PyTorch 1.3之前,需要使用注释
  2. # Tensor[N, C, H, W]
  3. images = torch.randn(32, 3, 56, 56)
  4. images.sum(dim=1)
  5. images.select(dim=1, index=0)
  6. # PyTorch 1.3之后
  7. NCHW = [‘N’, C’, H’, W’]
  8. images = torch.randn(32, 3, 56, 56, names=NCHW)
  9. images.sum('C')
  10. images.select('C', index=0)
  11. # 也可以这么设置
  12. tensor = torch.rand(3,4,1,2,names=('C', 'N', 'H', 'W'))
  13. # 使用align_to可以对维度方便地排序
  14. tensor = tensor.align_to('N', 'C', 'H', 'W')

五、其他常见问题

1. 关于args以及如何使用

argparse是一个Python模块:命令行选项、参数和子命令解析器。
主要有三个步骤:

  1. 创建 ArgumentParser() 对象 ,ArgumentParser 对象包含将命令行解析成 Python 数据类型所需的全部信息。
  1. # description用来描述
  2. parser = argparse.ArgumentParser(description="PyTorch DeeplabV3Plus Training")
  1. 调用 add_argument() 方法添加参数
  1. parser.add_argument('--batch-size', type=int, default=512,
  2. help='base image size')
  1. 使用 parse_args()
  1. # 解析
  2. args = parser.parse_args()
  3. # 使用
  4. args.batch-size

在实际代码中,我们使用args = parser.parse_args()来将解析的参数都赋值给args,然后在代码中直接使用args.batch-size即可。

2. pytorch之

  1. 替换numpy数组中的值
  2. out = np.where(arr>4, randint(90, 99), arr)
  1. 矩阵点乘(1
  2. List1 = [1,2,3,4]
  3. List2 = [5,6,7,8]
  4. List3 = map(lambda (a,b):a*b,zip(List1,List2))
  5. print List3
  1. 矩阵点乘(2
  2. List = [1,2,3]
  3. List2 = [5,6,7]
  4. List3 = np.multiply(np.array(List1),np.array(List2))
  5. print List3.tolist()

相关文章