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

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

前言

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

一、图像增强

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

1.直方图均衡化

2.直方图正规化

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

cv2.normalize(src,dst,alpha,beta,normType,dtype,mask)
#coding:utf-8

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
img_norm=cv.normalize(img,dst=None,alpha=350,beta=10,norm_type=cv.NORM_MINMAX)
cv.imshow("img",img)
cv.imshow("img_norm",img_norm)
cv.waitKey(0)
cv.destroyAllWindows()

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

#coding:utf-8

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv.imread(r"C:\Users\Administrator\Desktop\dark.jpg")
out_min=0
out_max=255

in_min = np.min(img)
in_max = np.max(img)

a=float(out_max-out_min)/(in_max-in_min)
b=out_min-a*in_min
img_norm = img*a+b
img_norm = img_norm.astype(np.uint8)
cv.imshow("img",img)
cv.imshow("img_norm",img_norm)
cv.waitKey(0)
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格式:

import cv2  
from PIL import Image  
import numpy  

image = Image.open("PIL.jpg")  
# 下面这句是重点
img = cv2.cvtColor(numpy.asarray(image),cv2.COLOR_RGB2BGR)  
cv2.imshow("OpenCV.jpg",img)

2.2 OpenCV转换成PIL.Image格式:

import cv2  
from PIL import Image  
import numpy  

img = cv2.imread("opencv.jpg")  
# 下面这句是重点
image = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))  
image.show()

四、pytorch相关

1. 使用GPU训练前准备

1.1 显卡设置

# 单张显卡
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 指定多张显卡,比如0,1号显卡
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'

# 也可以在命令行运行代码时设置显卡
CUDA_VISIBLE_DEVICES=0,1 python train.py

1.2 清除显存

torch.cuda.empty_cache()

# 也可以使用在命令行重置GPU的指令
nvidia-smi --gpu-reset -i [gpu_id]

2. 使用GPU训练

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

model = Model()
input = dataloader()
output = model(input)

1.2 移动到gpu上:

# solution: 0
device = 'gpu'
model = model.to(device)
data = data.to(device)
 
# solution: 1
model = model.cuda()
data = data.cuda()

1.3 移动到cpu上:

# solution: 0
device = 'cpu'
model = model.to(device)
data = data.to(device)
 
# solution: 1
model = model.cpu()
data = data.cpu()

3. 如何多GPU训练

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

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

import os
import torch
args.gpu_id="2,7" ; #指定gpu id
args.cuda = not args.no_cuda and torch.cuda.is_available() #作为是否使用cpu的判定
#配置环境 也可以在运行时临时指定 CUDA_VISIBLE_DEVICES='2,7' Python train.py
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id #这里的赋值必须是字符串,list会报错
device_ids=range(torch.cuda.device_count())  #torch.cuda.device_count()=2
#device_ids=[0,1] 这里的0 就是上述指定 2,是主gpu, 1就是7,模型和数据由主gpu分发
 
if arg.cuda:
	#这里将模型复制到gpu ,默认是cuda('0'),即转到第一个GPU 2
    model=model.cuda()  
    
if len(device_id)>1:
	#前提是model已经.cuda() 了
    model=torch.nn.DataParallel(model)
 
#前向传播时数据也要cuda(),即复制到主gpu里
for batch_idx, (data, label) in pbar:   
    if args.cuda:
        data,label= data.cuda(),label.cuda();
    data_v = Variable(data)
    target_var = Variable(label)
    prediction= model(data_v,target_var,args)
    #这里的prediction 预测结果是由两个gpu合并过的,并行计算只存在在前向传播里
    #前向传播每个gpu计算量为 batch_size/len(device_ids),等前向传播完了将结果和到主gpu里
    #prediction length=batch_size
 
    criterion = nn.CrossEntropyLoss()
    loss = criterion(prediction,target_var) #计算loss
    optimizer.zero_grad()
    loss.backward()  
    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的随机种子固定。

np.random.seed(0)
torch.manual_seed(0)
torch.cuda.manual_seed_all(0)

torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

5. 张量(Tensor)处理

1.1 张量基本信息:

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

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

# 在PyTorch 1.3之前,需要使用注释
# Tensor[N, C, H, W]
images = torch.randn(32, 3, 56, 56)
images.sum(dim=1)
images.select(dim=1, index=0)

# PyTorch 1.3之后
NCHW = [‘N’, ‘C’, ‘H’, ‘W’]
images = torch.randn(32, 3, 56, 56, names=NCHW)
images.sum('C')
images.select('C', index=0)
# 也可以这么设置
tensor = torch.rand(3,4,1,2,names=('C', 'N', 'H', 'W'))
# 使用align_to可以对维度方便地排序
tensor = tensor.align_to('N', 'C', 'H', 'W')

五、其他常见问题

1. 关于args以及如何使用

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

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

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

2. pytorch之

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

相关文章