前言

最近在面试,每天会被考到很多知识点,这些知识点有些我已经看了十几遍,还是会反应慢或者记不住。回想我在学习过程中,也是学了忘忘了学,没有重复个几十遍根本难以形成永久记忆。这次我复习和整理面试知识点的时候决定把CNN里面的关键创新点、容易疏忽的点都记录下来,方便快速查找回顾,于是就有了这篇像词典一样的永久更新的文章。

因为知识点过多,导致文章过长,目前已拆分为三篇:

1.基础知识篇

2.轻量化网络篇

3.通用模型篇

一.基础知识

1.1 BatchNorm/LayerNorm/InstanceNorm/GroupNorm

基础知识点 记忆点 备注
Batch Norm 达到的效果 BatchNorm就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同分布。
出发点

解决covariate shift:如果ML系统实例集合<X,Y>中的输入值X的分布老是变,这不符合IID假设,网络模型很难稳定的学规律。

问题:分布变化=>非线性输出向两端移动=>梯度消失=>网络收敛慢

解决:BN=>将隐藏层的输入拉回到(0,1)正态分布=>使激活值落在非线性区域=>使得梯度变大=>加快网络收敛

保障非线性

BN为了保证非线性的获得,对变换后的满足均值为0方差为1的x又进行了scale加上shift操作(y=scale*x+shift)

核心思想应该是想找到一个线性和非线性的较好平衡点,既能享受非线性的较强表达能力的好处,又避免太靠非线性区两头使得网络收敛速度太慢。

推理时的参数

推理的时候可能bs是1,那么α,γ,μ和σ从何而来呢?

参数α和γ是最后收敛的参数,而μ和σ则在训练的时候记住每个batch内的参数,然后求出平均值和方差的期望,这样在全局上估计的这组参数更加准确。

如何减少这些参数的存储量?

可以采用训练收敛最后几批mini batch的 μ和σ的期望,作为预测阶段的μ和σ

正则化作用 在BN层中,每个batch计算得到的均值和标准差是对于全局均值和标准差的近似估计,这为我们最优解的搜索引入了随机性,从而起到了正则化的作用。
BN的缺陷 带有BN层的网络错误率会随着batch_size的减小而迅速增大,当我们硬件条件受限不得不使用较小的batch_size时,网络的效果会大打折扣。
BN/LN/IN/GN 示意图
均值方差的作用位置
  • BN:固定C,对H,W和N求均值方差。
  • LN:固定N,对C和H,W求方差。
  • IN:固定C和N,对H,W求均值和方差。
  • GN:固定N,对C分组,每组内对C',H,W求均值和方差。
相比BN为什么好? LN/IN和GN都没有对batch作平均,所以当batch变化时,网络的错误率不会有明显变化
经验表现 LN和IN 在时间序列模型(RNN/LSTM)和生成模型(GAN)上有很好的效果,而GN在视觉模型上表现更好。

1.2 关于dropout

基础知识点 记忆点 备注
dropout 概念

在每个训练批次中,神经元的激活值以一定的概率p停止工作

目的 起到正则化作用,可以使模型泛化性更强,因为模型不会太依赖某些局部的特征。
示意图

面试问到是冻结权重还是冻结神经元? 答冻结神经元。

为什么缓解过拟合?

为什么有人说dropout类似model ensemble的效果?

  1. dropout每次隐藏部分神经元,就像是在训练不同的模型,因为每次网络的结构都不同。整个dropout就像是在对多个模型进行了ensemble。不同模型可能产生不同的过拟合,互相之间进行ensemble,就会起到平均效果更好。
  2. dropout有可能减少密集的局部连接,迫使模型去学习更为全局更为robust的特征,而模型不应该因为局部的细节而产生大的变化。

二.常见难点解决思路

2.1 如何解决小目标的检测问题

如何解决小目标的检测问题
方法 知识点 备注
输入数据 增大采集图像分辨率 相当于给框增加更为丰富的信息,以便提取到更复杂的特征。
增大模型图像输入分辨率 增大输入分辨率来提升小目标的检测能力。
模型与模块 图像金字塔 MTCNN使用了图像金字塔;缺点是多次特征提取,慢。
FPN/PAN/BiFPN 一次forward就可以识别多个尺度,可以提升小尺度的识别。
ASPP/SPP/RFBNet 不同尺度的特征融合,在扩大感受野的同时,也融合多个尺度的特征,增强了模型对于小目标的检测能力。
2-stage目标检测 ROI pooling => ROI Align  ,因为ROI pooling对于小目标的定位损失是巨大的。
Perceptual Generative Adversarial Networks for Small Object Detection Perceptual Generative Adversarial Networks for Small Object Detection中用使用感知生成式对抗网络(Perceptual GAN)提高小物体检测率,generator将小物体的poor表示转换成super-resolved的表示,discriminator与generator以竞争的方式分辨特征。Perceptual GAN挖掘不同尺度物体间的结构关联,提高小物体的特征表示,使之与大物体类似。包含两个子网络,生成网络和感知分辨网络。生成网络是一个深度残差特征生成模型,通过引入低层精细粒度的特征将原始的较差的特征转换为高分变形的特征。分辨网络一方面分辨小物体生成的高分辨率特征与真实大物体特征,另一方面使用感知损失提升检测率。在交通标志数据库Tsinghua-Tencent 100k及Caltech上实验。
Data Augmentation 《Augmentation for small object detection》
  1. 小目标的over sampling。
  2. 针对同一张图片里面包含小目标数量少的问题,在图片内用分割的Mask抠出小目标图片再使用复制粘贴的方法(当然,也加上了一些旋转和缩放,另外要注意不要遮挡到别的目标)。
anchor anchor-based
  1. 增加小anchor(配合FPN)。
  2. 降低小目标过滤阈值。
自适应Anchor阈值调整
finetune 对小分辨率单独finetune 在正常数据上做训练,再在小目标上做微调。
一种自己独创的方法 根据mask来识别小目标,做loss加权
  1. 对mask图使用opencv来标记轮廓。
  2. 对每个轮廓计算面积。
  3. 对面积小于阈值的标记为小物体,并且填充特殊的flag像素值。
  4. 针对得到的新mask做交叉熵加权损失。
import cv2
import numpy as np
import random
import torch
import matplotlib.pyplot as plt
AREA_THS = 30def mask_small_object(mask, area_thresh, pixels=[0, 1, 2], weights=[0.5, 1.0, 10.0]):""":param mask: 输入mask掩码:param area_thresh: 小物体的阈值,面积小于该值认为是小物体:param pixels: 背景 小物体 大物体的mask值:param weight: 背景,前景大物体,前景小物体的权重:return: 权重图"""contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)area = []for i in range(len(contours)):area.append(cv2.contourArea(contours[i]))for i in range(len(area)):if area[i] < area_thresh:cv2.fillPoly(mask, [contours[i]], (2, ))for i in range(len(pixels)):mask[mask==[pixels[i]]] = weights[i]return maskdef mask_cross_entropy(y, y_hat, weight):n = 1e-7# return -np.sum(y * np.log(y_hat + n) + (1 - y) * np.log(1 - y_hat + n), axis=1)assert y.shape == y_hat.shapeentro = (y * np.log(y_hat + n) + (1 - y) * np.log(1 - y_hat + n))mask_entro = entro * weightres = -np.mean(mask_entro)return round(res, 5)if __name__ == '__main__':AREA_THS = 30img = np.zeros(shape=(512, 512, 3), dtype=np.uint8)label = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)for i in range(10):x, y = random.randint(10, 500), random.randint(10, 500)r = random.randint(1, 10)cv2.circle(label, (x, y), radius=r, color=(1), thickness=-1)weight = mask_small_object(label, area_thresh=AREA_THS)pred = np.abs(np.random.rand(512, 512))print(mask_cross_entropy(label, pred, weight))

三.常见loss函数

loss函数 记忆点 备注
CE  交叉熵的推理

1.信息量的表示

2.熵是信息量的期望

3.相对熵(KL散度)表示两个分布的差异

4.交叉熵是相对熵的数学变形

前面是p(x)的熵,是一个常量。后面就是交叉熵。

loss的形式
分类loss为什么prefer交叉熵than MSE? MSE不能保证误差越大,梯度越大,学习越快。而交叉熵可以,因此收敛更好更快。
Focal  解决的问题

1.解决类别不平衡

2.难易样本分布不平衡

loss的形式
loss的参数

基于交叉熵演变而来。

γ用来调节样本难易程度,一般取2。γ提升了预测与GT差距大的样本对loss的贡献比(困难样本)。

α用来调节样本类别的比例,默认α=0.25,将前景的loss放大而背景的loss缩小。

Dice 解决的问题 语义分割中正负样本不平衡
loss的形式

Dice系数:

Dice loss:

Laplace Smoothing:

Dice的优势劣势
  1. GIOU paper 提出给定优化指标本身与代理损失函数之间的选择,最优选择就是指标本身。所以Dice本身更贴合语义分割常用的评价指标iou。
  2. Dice的问题是求导在极端情况下会导致梯度陡增,使训练难以收敛震荡,不稳定。

四.常见衡量指标

指标名称 记忆点 备注
MAP(目标检测) TP、TN、FP、FN
Precision & Recall Precision = TP / (TP + FP)   Recall = TP / (TP + FN)
AP

按照模型给出的置信度,对每个类的所有预测框进行排序:

逐个计算Precision 和 Recall,绘制PR曲线,AP就是PR曲线上的Precision值求均值。

实际应用中就会对PR曲线最做平滑:

MAP MAP就是对所有类的AP做平均值。
MIOU(语义分割) IOU

IOU的定义:计算真实值和预测值两个集合的交集和并集之比

IOU=TP/(FP+FN+TP)

MIOU 对于不同类别的IOU求平均值
MIOU的数学表达

pij表示真实值为i,被预测为j的数量, K+1是类别个数(包含空类)。pii是真正的数量。pij、pji则分别表示假正和假负。

补充篇一:opencv(python)知识点

0.1 图像基础知识点

图像&opencv基础知识点
基础知识点 记忆点 备注
图像基础知识 数字图像 数字图像又称数码图像或者数位图像,是二维图像用有限数字数值像素的表示,由数组或者矩阵表示。数字图像可以理解为一个二维函数f(x, y),其中x,y是空间的坐标,而任意位置的幅值f称为图像在该点的强度或者灰度。

常见的电磁波成像特点

(按照频率从高到低)

  • γ射线成像:波长最短,频率最高,是由原子核内发射出来的电磁波。放射性物质或者原子核反应中常有这种辐射。γ射线穿透力强,对生物破坏性大。
  • x射线成像:CT就是用x射线照射物体。由于生物组织或者工程组件的不同部位对x射线的吸收率不同,从而得到不同的衰减以成像(密度越高,吸收的越多)。
  • 紫外线成像:具备化学效应和荧光效应,常用于生物医学。
  • 可见光波段成像
  • 红外线成像:一切物体都可以辐射出红外线,可利用探测仪测量目标本身与背景间的红外线差得到红外图像。
  • 微波成像:用于雷达以及生成地表情报图。
  • 射频成像:电视、无线电、手机的波段。也可以用于医学,比如磁共振。
常见的图像格式
读取图像
# cv2读取 & 直接呈现
img = cv2.imread("../test.jpg", flags=1)
print(img.shape)
cv2.imshow("test.jpg", img)
key = cv2.waitKey(0)
if key == ord('q'):cv2.destroyAllWindows()
elif key == ord('s'):cv2.imwrite("test_bak.jpg", img)# cv2读取后需转换为RGB,再由matplotlib呈现
img = cv2.imread("../test.jpg", flags=1)
print(img.shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(img.shape)
plt.figure(figsize=(12, 6))
plt.imshow(img)
plt.show()# PIL 读取
img = Image.open("../test.jpg")
print(img)
print(np.asarray(img).shape)# matlpotlib读取
img = plt.imread("../test.jpg")
print(img.shape)
  • flags=0代表灰度图,flages=1代表彩图,默认是三通道彩图。
  • cv2.imread()、PIL.Image.open()、matplotlib.imread()读取的默认shape都是【H,W,C】,与pytorch的默认顺序不同,需要转换为【C, H, W】。
  • opencv读取是默认的BGR,直接用opencv呈现是没问题的。但是后面处理或者用matplotlib呈现就需要转换为RGB。
  • 灰度 = B * 0.114 + G * 0.587 + R * 0.299
图像直方图

图像直方图是以表示数字图像中亮度分布的直方图,表达了图像亮度的整体分布。常用来二值化。

img = cv2.imread("../test.jpg", flags=1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist(img, channels=[0], mask=None, histSize=[256], ranges=[0, 256])
plt.figure(figsize=(12, 6))
plt.plot(hist)
plt.xlabel("bins")
plt.ylabel("num of pixels")
plt.title("histgram of grayscale")
plt.show()

颜色空间
  • RGB:依据人眼的颜色空间。有RGB三通道,范围都是0-255。
  • HSV:H(色调),代表色彩;S(饱和度),取值是0-100%,值越大,颜色越饱和;V(明度),从0%(黑)到100%(白)。
  • HSI:H(色调),S(饱和度),I(强度)。
  • CMYK:C(青)、M(品红)、Y(黄),常用于印刷行业。

opencv中颜色空间的改变也是cv2.cvtcolor()

图像基础处理 opencv绘图
# 1,绘制线段
if show_control == 1:img = np.zeros((512, 512, 3))cv2.imshow("origin photo", img)cv2.waitKey(2000)cv2.line(img, (0, 0), (250, 250), color=(0, 0, 255), thickness=1)cv2.imshow("photo with a line", img)cv2.waitKey(2000)cv2.destroyAllWindows()#2. 绘制矩形 需要左上角 右下角的坐标
if show_control == 2:img = cv2.imread("../test.jpg", flags=1)cv2.rectangle(img, (251, 402), (373, 464), color=(0, 0, 255), thickness=2)cv2.putText(img, "bobbies", (253, 400), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(25, 0, 0), thickness=2)cv2.imshow("rectangle photo", img)cv2.waitKey(2000)cv2.destroyAllWindows()#3. 绘制圆形 需要圆心和半径
if show_control == 3:img = np.zeros((512, 512, 3))cv2.circle(img, (100,100), 20, color=(0, 0, 255))cv2.imshow("circle", img)cv2.waitKey(2000)cv2.destroyAllWindows()
图像平移
img = cv2.imread("../test.jpg")
# x方向移动多少, y方向移动多少
H = np.float32([[1, 0, 50], [0, 1, 25]])
rows, cols = img.shape[: 2]
# 注意这里rows和cols需要反置,先列后行
res = cv2.warpAffine(img, M=H, dsize=(cols, rows))
cv2.imshow("origin pic", img)
cv2.imshow("affine pic", res)
cv2.waitKey(0)
图像缩放

常见的插值方法:

  • 最近邻插值:效果不好,放大后有严重的马赛克,缩小后的图像有严重的失真。

  • 线性插值

  • 三次样条插值
  • LANCZOS插值(效果还不错)
图像旋转
# 旋转
if control == 2:img = cv2.imread("../test.jpg")h, w  = img.shape[:2]# scale >0 逆时针旋转  scale<0 顺时针旋转 angle旋转角度H = cv2.getRotationMatrix2D(center=(h/2, w/2), angle=45, scale=0.5)res = cv2.warpAffine(img, M=H, dsize=(w, h))cv2.imshow("rotation", res)cv2.waitKey(0)cv2.destroyAllWindows()
仿射变换
if control == 3:img = cv2.imread("../test.jpg")h, w  = img.shape[:2]# 用三个点来确定仿射变换pos1 = np.float32([[50, 50], [200, 50], [50, 200]])pos2 = np.float32([[10, 100], [200, 50], [100, 250]])H = cv2.getAffineTransform(pos1, pos2)res = cv2.warpAffine(img, M=H, dsize=(w, h))cv2.imshow("affine", res)cv2.waitKey(0)cv2.destroyAllWindows()
透视变换
img = cv2.imread("../test.jpg")
h, w = img.shape[:2]
pos1 = np.float32([[114, 82],[287, 156], [8, 100], [143, 177]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])H = cv2.getPerspectiveTransform(pos1, pos2)
#图像透视变换
result = cv2.warpPerspective(img, H, dsize=(w, h))
cv2.imshow("origin pic", img)
cv2.imshow("warp pic", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像滤波操作 滤波基本原理
  • 基本原理:图像可以看作是二维的信号,像素点的灰度值代表着信号的强弱。图像中变化强烈的部分称为高频部分,图像中变化缓慢的部分称为低频部分。可以根据图像的高低频,设置高通或者低通滤波器。高通可以检测变化尖锐明显的部分,低通可以让图像变得平滑,消除噪声。高通滤波器常用于边缘检测,低通滤波器常用于图像平滑去噪。
方框滤波
img = cv2.imread("../test.jpg", flags=1)
# 不加normalize会使得很多pixel超过255 导致全图变白
filter = cv2.boxFilter(img, ddepth=-1, ksize=(3, 3), normalize=True)
cv2.imshow("original", img)
cv2.imshow("box filter", filter)
cv2.waitKey(0)
cv2.destroyAllWindows()

kernel内元素全部是1。

注意进行normalize,否则图像会因为超过255,变白,另外kernel越大,模糊的效果越明显。

均值滤波(平均模糊)
if control == 2:img = cv2.imread("../test.jpg", flags=1)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)blur = cv2.blur(img, ksize=(3, 3))plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(blur)plt.show()

kernel内元素全部是1。

等同于加了normalize的方框滤波。

高斯滤波
if control == 3:img = cv2.imread("../cat.jpg", flags=1)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)blur = cv2.GaussianBlur(img, ksize=(3, 3), sigmaX=0)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(blur)plt.show()

高斯滤波卷积核内参数并不相同,而是呈现高斯分布的,中间高,两边低。高斯滤波可有效去除高斯噪声,保留更多的图像细节。

中值滤波

中值滤波是一种非线性滤波,是用像素点邻域灰度的中值代替该点的灰度值。,中值滤波可以取出椒盐噪声和斑点噪声。

if control == 4:img = cv2.imread("../luna.jpg", flags=1)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)blur = cv2.medianBlur(img, ksize=3)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(blur)plt.show()
双边滤波

双边滤波是一种非线性滤波,是结合像素的空间邻近度和像素值相似度的一种折中处理。同时考虑空间信息和灰度的相似性,达到保边去噪的目的。具有简单、非迭代、局部处理的特点。双边滤波可以有效保证边缘信息。

# 双边滤波
if control == 5:img = cv2.imread("../luna.jpg", flags=1)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)blur = cv2.bilateralFilter(img, d=-1, sigmaColor=15, sigmaSpace=10)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(blur)plt.show()
图像增强 灰度直方图均匀化

直方图均匀化就是将原图像经过某种变化,得到一副灰度直方图均匀的图像。直方图均匀化的思想就是对图像中像素个数较多的灰度级进行展宽,从而对像素较少的灰度级进行缩减。从而达到清晰图像的目的。工业上常用来解决过曝的情况。

img = cv2.imread("../dark_girl.jpg",flags=0)
print(img.shape)
img_equal = cv2.equalizeHist(img)
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.title("origin")
plt.imshow(img)
plt.subplot(122)
plt.title("equalize")
plt.imshow(img_equal)
plt.show()
彩色直方图均匀化
if control == 2:img = cv2.imread("../dark_girl.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)r, g, b = cv2.split(img)equal_r = cv2.equalizeHist(r)equal_g = cv2.equalizeHist(g)equal_b = cv2.equalizeHist(b)img_equal = cv2.merge((equal_r, equal_g, equal_b))plt.figure(figsize=(12, 6))plt.subplot(121)plt.title("origin")plt.imshow(img)plt.subplot(122)plt.title("equalize")plt.imshow(img_equal)plt.show()
Gamma变化

Gamma变化是对输入图像灰度值进行的非线性操作。使输出图像的灰度值和输入图像的灰度值呈现指数的关系。

Gamma变化用来进行图像增强,让图像从曝光强度的线性响应变得更接近人眼感受的响应。既对相机曝光或者光照不足的情况进行调节。

img = cv2.imread("../guobao.jpg")def adjust_gamma(image, gamma=1.0):invGamma = 1.0 / gammatable = []for i in range(256):table.append(((i / 255) ** invGamma) * 255)table = np.array(table).astype("uint8")return  cv2.LUT(image, table)def equalize(img):b, g, r = cv2.split(img)equal_r = cv2.equalizeHist(r)equal_g = cv2.equalizeHist(g)equal_b = cv2.equalizeHist(b)img_equal = cv2.merge((equal_b, equal_g, equal_r))return img_equalimg_gamma = adjust_gamma(image=img, gamma=0.35)
img_equalize = equalize(img=img)
cv2.imshow("original", img)
cv2.imshow("gamma", img_gamma)
cv2.imshow("equalize", img_equalize)
cv2.waitKey(0)
cv2.destroyAllWindows()
形态学操作 什么是形态学? 形态学是最为常见的图像技术,主要从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质的形状特征,如边界和连通区域。
腐蚀

针对图像的白色部分,膨胀进行扩张,白色区域变大,腐蚀进行收缩,白色区域变小。

腐蚀:用模板B来腐蚀A就是用B来逐步卷积A,模板B有一个锚点和锚框,如果锚点落在前景内,且锚框都落在前景内,则保留锚点像素。如果锚点落在前景内,锚框没有完全包含在前景内,则去除锚点像素改为背景。

img = cv2.imread("../erode.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_erode = cv2.erode(img, kernel=(3, 3))
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.imshow(img)
plt.subplot(122)
plt.imshow(img_erode)
plt.show()
膨胀

腐蚀的对偶运算。

同样使用模板B来卷积A,模板内包含锚点和锚框。如果锚框和前景有交集,如果此时锚点对应着背景,那么就把背景膨胀为前景。

开运算

先腐蚀后膨胀,把细微连在一起的物体分开,把物体的表面进行平滑。

换句话说开运算能够去除孤立的小点,毛刺和小桥,但总的位置和形状不变。

if control == 3:img = cv2.imread("../mor-open.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(5, 5))img_erode = cv2.morphologyEx(img, op=cv2.MORPH_OPEN, kernel=kernel, iterations=1)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(img_erode)plt.show()
闭运算

先膨胀运算再腐蚀运算。

闭运算能够将两个细微连接的图封闭到一起,可以去除孔洞和弥补小裂缝,并且保持整体的位置形状不变。

if control == 4:img = cv2.imread("../mor-close.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(7, 7))img_erode = cv2.morphologyEx(img, op=cv2.MORPH_CLOSE, kernel=kernel, iterations=3)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(img_erode)plt.show()
形态学梯度
顶帽和黑帽
  • 顶帽:原图像与开运算的插值,突出原图像中比周围亮的区域。
  • 黑帽:闭运算与原图像差值,突出原图像比周围暗的区域。
# 形态学梯度  膨胀-腐蚀
if control == 5:img = cv2.imread("../haizei.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(7, 7))img_erode = cv2.morphologyEx(img, op=cv2.MORPH_GRADIENT, kernel=kernel, iterations=1)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(img_erode)plt.show()# 顶帽 原图-开运算  突出原图中亮的地方
if control == 6:img = cv2.imread("../haizei.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(9, 9))img_erode = cv2.morphologyEx(img, op=cv2.MORPH_TOPHAT, kernel=kernel, iterations=2)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(img_erode)plt.show()# 黑帽 闭运算-原图  突出原图中暗的地方
if control == 7:img = cv2.imread("../haizei.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(9, 9))img_erode = cv2.morphologyEx(img, op=cv2.MORPH_BLACKHAT, kernel=kernel, iterations=3)plt.figure(figsize=(12, 6))plt.subplot(121)plt.imshow(img)plt.subplot(122)plt.imshow(img_erode)plt.show()
图像分割 分割原则 分割的原则就是使划分后的子图在内部保持相似度最大,而子图之间的相似度保持最小。
固定阈值分割

if control == 1:img = cv2.imread("../2bin.jpg", flags=0)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 大于thresh 置为maxval; 小于thresh,置为0ret1, th1 = cv2.threshold(img, thresh=100, maxval=255, type=cv2.THRESH_BINARY)# 小于thresh 置为maxval; 大于thresh,置为0ret2, th2 = cv2.threshold(img, thresh=127, maxval=255, type=cv2.THRESH_BINARY_INV)# 大于thresh 置为thresh, 小于thresh,不处理ret3, th3 = cv2.threshold(img, thresh=127, maxval=255, type=cv2.THRESH_TRUNC)# 大于thresh 不做处理, 小于thresh,置为0ret4, th4 = cv2.threshold(img, thresh=127, maxval=255, type=cv2.THRESH_TOZERO)ret5, th5 = cv2.threshold(img, thresh=127, maxval=255, type=cv2.THRESH_TOZERO_INV)ths = [img, th1, th2, th3, th4, th5]plt.figure(figsize=(12, 6))for i in range(6):plt.subplot(2, 3, i+1)plt.imshow(ths[i])plt.show()
自适应阈值分割

自适应阈值法会每次取出图像的一小部分计算阈值,这样不同区域的阈值就不尽相同,适用于明暗分布不均的图片。

# 自适应阈值分割
if control == 2:img = cv2.imread("../black_white.jpg", flags=0)print(img.shape)# 分成blockSize的小区域,其中使用均值来计算阈值th1 = cv2.adaptiveThreshold(img, maxValue=255, adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C,thresholdType=cv2.THRESH_BINARY, blockSize=11, C=4)# 分成blockSize的小区域,其中使用高斯加权来计算阈值th2 = cv2.adaptiveThreshold(img, maxValue=255, adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,thresholdType=cv2.THRESH_BINARY, blockSize=17, C=6)ths = [img, th1, th2]plt.figure(figsize=(12, 6))for i in range(3):plt.subplot(1, 3, i+1)plt.imshow(ths[i], cmap=plt.get_cmap("gray"))plt.show()
迭代法阈值分割
  1. 求出图像的最大灰度和最小灰度值,分别记为Zmax和Zmin,令初始阈值T0 = 1/2(Zmax + Zmin)。
  2. 根据阈值Tk,将图像分为前景和背景,分别求出两者的平均灰度值ZO和ZB。
  3. 求出新阈值Tk+1 = 1/2(ZO + ZB)。
  4. 若TK = TK + 1,则得到最终阈值,否则继续迭代2。
  5. 使用最后的阈值。
大津阈值分割法

# 大津法阈值分割
if control == 3:img = cv2.imread("../dark_girl.jpg", flags=0)print(type(img))# 阈值法_, th1 = cv2.threshold(img, 100, maxval=255, type=cv2.THRESH_BINARY)# 大津法_, th2 = cv2.threshold(img, 0, maxval=255, type=cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 高斯滤波 + 大津法(常用套路)blur = cv2.GaussianBlur(img, ksize=(7, 7), sigmaX=0)_, th3 = cv2.threshold(blur, 0, maxval=255, type=cv2.THRESH_BINARY + cv2.THRESH_OTSU)plt.figure(figsize=(12, 6))plt.subplot(221)plt.title("origin")plt.imshow(img, cmap=plt.get_cmap("gray"))plt.subplot(222)plt.title("thresh")plt.imshow(th1, cmap=plt.get_cmap("gray"))plt.subplot(223)plt.title("otsu")plt.imshow(th2, cmap=plt.get_cmap("gray"))plt.subplot(224)plt.title("gussian + otsu")plt.imshow(th3, cmap=plt.get_cmap("gray"))plt.show()
边缘检测
  1. 梯度:梯度是一个向量,梯度方向指向函数变化最快的方向,梯度的大小是最大的变化率。
  2. 边缘:边缘就是梯度变化很快的点的集合。
  3. 梯度算子:梯度算子是一阶导数的算子,是水平梯度模板和竖直梯度模板的组合,也有对角线的方向。
  4. 常见的梯度算子:
  • Roberts交叉算子

优点:边缘定位较为准确,适用于边缘明显且噪声少的图像。

缺点:没有描述水平和竖直方向的灰度变化,只关注了对角线方向,容易造成边缘的遗漏;鲁棒性差,因为点本身参与梯度的计算,不能有效抑制噪声的干扰。

  • Prewitt算子

Prewitt算子引入了类似局部平均的运算,对噪声更有平滑作用,可以抑制噪声。

  • Sobel算子

  • canny边缘检测算法

if control == 2:img = cv2.imread("../road.png", 0)img_mask = cv2.imread("../road_mask.png", 0)img_mask = 1 - img_mask#print(img_mask)v1 = cv2.Canny(img, threshold1=60, threshold2=150, edges=(5, 5))v1_ = v1 * img_maskv2 = cv2.Canny(img, threshold1=50, threshold2=100, edges=(5, 5))v2_ = v2 * img_maskv_mask = cv2.Canny(img_mask, threshold1=0, threshold2=1, edges=(3, 3))plt.figure(figsize=(9, 18))plt.subplot(321)plt.title("origin")plt.imshow(img, cmap=plt.get_cmap("gray"))plt.subplot(322)plt.title("mask")plt.imshow(img_mask, cmap=plt.get_cmap("gray"))plt.subplot(323)plt.title("v1")plt.imshow(v1, cmap=plt.get_cmap("gray"))plt.subplot(324)plt.title("v2")plt.imshow(v2, cmap=plt.get_cmap("gray"))plt.subplot(325)plt.title("v1_")plt.imshow(v1_, cmap=plt.get_cmap("gray"))plt.subplot(326)plt.title("v_mask")plt.imshow(v_mask, cmap=plt.get_cmap("gray"))plt.show()
连通区域

连通区域:一般指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域。连通区域分析是将图像中各自联通区域找到并且标记。

Two-pass算法:

区域生长

区域生长:是一种串行区域分割的方法。从某个像素出发,按照一定的准则,逐步加入邻近像素。当满足一定的条件的时候,区域停止生长。

分水岭算法 原理:任意的灰度图像。高亮度的是山峰,低亮度的是山谷。

计算机视觉知识点整理(上) 基础篇(持续更新)相关推荐

  1. 计算机视觉-计算机视觉知识点整理1基础篇

    一.基础知识 1.1 BatchNorm/LayerNorm/InstanceNorm/GroupNorm 基础知识点 记忆点 备注 Batch Norm 达到的效果 BatchNorm就是在深度神经 ...

  2. linux(Ubuntu)常用命令整理 -- 基础篇 -- 持续更新

    2019独角兽企业重金招聘Python工程师标准>>> 有些命令很常用,但是一段时间不用就会忘,把自己每天用到的整理下来,具体参数用到的时候再写. 查看一个命令的使用帮助:man 查 ...

  3. 2020今日头条面试真题及答案整理最新最全持续更新中~~~~

    大家好,我是好好学习天天编程的天天 一个整天在互联网上爬虫的程序员,每天给大家分享学习干货的攻城狮 2020今日头条面试真题及答案整理&最新最全&持续更新中~~~~ 2020今日头条面 ...

  4. 2010 .NET面试题整理之基础篇

    2010 .NET面试题整理之基础篇 zhuan 开篇语:对于已有工作经验的朋友,也许面试题已显得不怎么重要,但是如果你应聘的还仅仅是个普通的程序员,相信在很多的公司都还是会先拿出一套面试题,可能对整 ...

  5. 详细前端面试题javascript篇--持续更新

    最新前端面试题汇总大全(超详细含vue,react,css,js,webpack,性能优化等)–持续更新点击查看 前端HTML篇 前端CSS篇 前端面试题js篇--持续更新 1. JS 数据类型 ?存 ...

  6. 2020美团(开水团)面试题真题整理最新最全~持续更新中~~~

    大家好我是好好学习天天编程的天天 一个整天在互联网上种菜和砍柴的程序员~ 如果我们每天关注互联网行业,也有心做程序员的话,我们可能进场会听到一些关键词:一东(时间单位),一度(市值单位,一个拼多多是几 ...

  7. 前端知识点总结——JS高级(持续更新中)

    前端知识点总结--JS高级(持续更新中) 1.字符串 什么是: 连续存储多个字符的字符数组 相同: 1. 下标 2. .length 3. 遍历 4. 选取: slice(starti[, endi] ...

  8. Nginx面试题(史上最全 + 持续更新)

    尼恩面试宝典专题39:Nginx面试题(史上最全.持续更新) 本文版本说明:V27 <尼恩面试宝典>升级规划为: 后续基本上,每一个月,都会发布一次,最新版本,可以联系构师尼恩获取, 发送 ...

  9. Puppet基础篇6-Puppet更新方式的选型

    Puppet基础篇6-Puppet更新方式的选型 零基础学习Puppet自动化配置管理系列文档 基于C/S架构的Puppet更新方式一般有两种,一种是Agent端设置同步时间主动去PuppetMast ...

最新文章

  1. 【javascript】javascript函数整理之日期型(Date)篇
  2. Spring Boot Serverless 实战 | Serverless 应用的监控与调试
  3. DDoS deflate–简单解决VPS被DDOS/CC攻击
  4. 《概率论与数理统计习题全解指南》中的“计算机得”
  5. 2021年春季学期期末统一考试 成本管理 试题
  6. 全网最详细的docker配置nginx http2 优化高速访问
  7. 还在用Postman?来,花2分钟体验下ApiPost的魅力!
  8. java生成二维码打印到浏览器
  9. three轨迹线在mapbox地图上显示
  10. springboot和vue data数据为空_常见数据结构的 Python 实现(建议收藏)
  11. 【python】Tkinter可视化窗口(一)
  12. git刷新分支列表_如何使用Git小技巧让你开发协作过程更加顺利?
  13. ThinkPHP3.2.3完全开发手册离线手册
  14. 马士兵Python基础版2020教程P98-P134 PPT笔记+课堂代码
  15. 聚类算法之DBSCAN
  16. Mac 使用终端彻底格式化U盘
  17. 晨光文具去年赚5亿,连2000元都拿来理财
  18. #后疫情时代的新思考#AI助力,“无接触”服务加速金融数字化转型丨数据猿公益策划...
  19. imageJ把两张图片在时间轴上进行合并
  20. 编译指示_#pragma在DSP中的编程技巧

热门文章

  1. tabindex属性_tabindex(HTML属性)
  2. 上午还在写Bug,下午突然“被离职”,咋整?
  3. 牛客竞赛 生涯回忆录
  4. 睡前玩手机很伤害眼睛,这几个方法可以有效缓解痛苦
  5. 测试生命周期、测试过程分为几个阶段,以及各阶段的含义?
  6. GoAccess安装
  7. 析构函数的作用和用法
  8. 智慧景区票务系统需要服务器吗,景区票务系统要不要选择SaaS系统的
  9. 谷歌浏览器备份书签及插件
  10. 完整的模型训练套路(pytorch)