本文主要参考自 OpenCV官方文档

一、色彩空间

  1. HSV
    ① 色调(H),取值范围:[0, 179]
    ② 饱和度(S),取值范围:[0, 255]
    ③ 明亮度(V),取值范围:[0, 255]
  2. 色彩空间转换
    import cv2
    import numpy as npimg = cv2.imread("../../Resources/cctv2.jpg")
    # 转换为HSV色彩空间
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)# 利用cv2.inRange()设置阈值,去除背景
    lower = np.array([0, 0, 0])
    upper = np.array([40, 255, 255])
    mask = cv2.inRange(hsv, lower, upper)
    res = cv2.bitwise_and(img, img, mask=mask)cv2.imshow('frame', img)
    cv2.imshow('mask', mask)
    cv2.imshow('res', res)
    cv2.waitKey(0)
    

    效果图如下

二、图像阈值

  1. 简单阈值

    简单阈值类型:

    cv2.THRESH_BINARY(阈值二值化):小于等于阈值的像素点置 0,大于阈值的像素点置 255

    cv2.THRESH_BINARY_INV(阈值反二值化):小于等于阈值的像素点置 255,大于阈值的像素点置 0

    cv2.THRESH_TRUNC(截断):小于等于阈值的像素点保持原色,大于阈值的像素点置灰(与阈值threshold一致)

    cv2.THRESH_TOZERO(阈值取零):小于等于阈值的像素点置 0,大于阈值的像素点保持原色

    cv2.THRESH_TOZERO_INV(阈值反取零):小于等于阈值的像素点保持原色,大于阈值的像素点置 0

    import cv2
    import numpy as np
    from matplotlib import pyplot as pltimg = np.uint8(np.arange(400 * 400).reshape([400, 400]) / (400 * 400) * 255)
    # 阈值二值化(threshold binary)
    # 小于等于阈值的像素点置0,大于阈值的像素点置255.
    ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    # cv2.imshow("",thresh1)# 阈值反二值化(threshold binary Inverted)
    # 小于等于阈值的像素点置255,大于阈值的像素点置0.
    ret2, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    # cv2.imshow("",thresh2)# 截断(truncate)
    # 小于等于阈值的像素点保持原色,大于阈值的像素点置灰(与阈值threshold一致).
    ret3, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
    # cv2.imshow("",thresh3)# 阈值取零(threshold to zero)
    # 小于等于阈值的像素点置0,大于阈值的像素点保持原色。
    ret4, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
    # cv2.imshow("",thresh4)# 阈值反取零(threshold to zero inverted)
    # 小于等于阈值的像素点保持原色,大于阈值的像素点置0。
    ret5, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
    # cv2.imshow("",thresh5)titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
    images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]for i in range(len(images)):# 划分2行*3列的区域,在第(i+1)个区域上画图plt.subplot(2, 3, i + 1)# 将图片显示在画板上# cmap颜色映射: 当img形状是三维矩阵(M,N,3)或(M,N,4)时,值被解释为RGB或RGBA,此时cmap将被忽略。# 当img形状是二维矩阵(M,N)时,此时cmap用于值到颜色的一个映射。plt.imshow(images[i], "gray")# 添加标题plt.title(titles[i])# 清空x轴、y轴刻度plt.xticks([]), plt.yticks([])plt.show()
    

    效果图如下

  2. 自适应阈值

    cv2.adaptiveThreshold 包含三个输入参数:

    其中 adaptiveMethod 决定阈值是如何计算:

    cv2.ADAPTIVE_THRESH_MEAN_C:阈值是邻近区域的平均值减去常数 C

    cv2.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域值的高斯加权总和减去常数 C

    import cv2
    from matplotlib import pyplot as pltimg = cv2.imread('../../Resources/paper.jpg', 0)
    # cv2.imshow("", img)ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_OTSU)# blockSize = 9 表示图片中分块大小,C = 3 阈值方法中的常数项
    th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 3)
    th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 9, 3)titles = ['Original Image', 'Global Thresholding (v = 127)','Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
    images = [img, th1, th2, th3]for i in range(4):plt.subplot(2, 2, i + 1),plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]), plt.yticks([])plt.imshow(th3, "gray")
    plt.show()
    cv2.waitKey(0)
    

    效果图如下

  3. OTSU(最大类间方差法)二值化

    在全局阈值化中,我们使用任意选择的值作为阈值。相反,OTSU的方法避免了必须选择一个值并自动确定它的情况。

    import cv2
    import matplotlib.pyplot as plt"# OTSU二值化"
    # 将彩色图转化为灰度图
    img = cv2.imread("../../Resources/beautiful_girl.jpg")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 将灰度图转化为二值化图(0,255),otsu是自动求取阈值
    ret1, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    ret2, binary_inv = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
    ret3, truncate = cv2.threshold(gray, 0, 255, cv2.THRESH_TRUNC | cv2.THRESH_OTSU)
    ret4, to_zero = cv2.threshold(gray, 0, 255, cv2.THRESH_TOZERO | cv2.THRESH_OTSU)
    ret5, to_zero_inv = cv2.threshold(gray, 0, 255, cv2.THRESH_TOZERO_INV | cv2.THRESH_OTSU)# print(ret1, ret2, ret3, ret4, ret5)# 结合matplotlib,展示多张二值化图
    titles = ['Gray Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
    images = [gray, binary, binary_inv, truncate, to_zero, to_zero_inv]for i in range(6):plt.subplot(2, 3, i + 1)plt.imshow(images[i], cmap="gray")plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    

    效果图如下
    想要具体了解 Otsu的二值化如何实现 的朋友可以参阅官方文档

三、图像几何变换

  1. 图像缩放

    图像的大小可以手动指定,也可以指定缩放比例,也可使用不同的插值方法

    几种插值方式
    ① 双线性插值(默认):cv2.INTER_LINEAR

    ② 最邻近插值:cv2.INTER_NEAREST

    ③ 基于4x4像素邻域内的三次样条插值:cv2.INTER_CUBIC

    ④ 基于8x8像素邻域内的Lanczos插值:cv2.INTER_LANCZOS4

    ⑤ 基于局部像素的重采样:cv2.INTER_AREA

    首选的插值方法是 cv.INTER_AREA 用于缩小,cv.INTER_CUBIC(慢)和 cv.INTER_LINEAR 用于缩放

    几种常用方法的效率是:最邻近插值 > 双线性插值 > 双立方插值 > Lanczos插值
    但是效率和效果成反比,所以根据自己的情况酌情使用。

    import cv2
    # import timeimg = cv2.imread("../../Resources/messi15.jpg")
    rows, cols, channels = img.shape
    # time_start = time.time()  # 开始时间# 图片缩放: resize()
    resize_1 = cv2.resize(img, dsize=(cols * 2, rows * 2))  # 按尺寸
    resize_2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2)  # 按因子# 几种插值方式:
    # 1.双线性插值(默认)
    linear = cv2.resize(img, dsize=(cols * 2, rows * 2), interpolation=cv2.INTER_LINEAR)# 2.最邻近插值
    nearest = cv2.resize(img, dsize=(cols * 2, rows * 2), interpolation=cv2.INTER_NEAREST)# 3.基于4x4像素邻域内的三次样条插值
    cubic = cv2.resize(img, dsize=(cols * 2, rows * 2), interpolation=cv2.INTER_CUBIC)# 4.基于8x8像素邻域内的Lanczos插值
    lanczos = cv2.resize(img, dsize=(cols * 2, rows * 2), interpolation=cv2.INTER_LANCZOS4)# 5.- 基于局部像素的重采样
    area = cv2.resize(img, dsize=(cols * 2, rows * 2), interpolation=cv2.INTER_AREA)cv2.imshow("image", img)
    cv2.imshow("resize_1", resize_1)
    cv2.imshow("resize_2", resize_2)
    cv2.imshow("linear", linear)
    cv2.imshow("nearest", nearest)
    cv2.imshow("cubic", cubic)
    cv2.imshow("lanczos", lanczos)
    cv2.imshow("area", area)# time_end = time.time()
    # print(time_end - time_start)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
  2. 图像翻转
    通过 cv2.flip() 来实现翻转效果,其中参数 flipCode 用来控制翻转样式。

    flipCode = 0:绕x轴翻转,即上下颠倒
    flipcode = 1:绕y轴翻转,左右翻转
    flipcode = -1:绕x,y轴同时翻转,即上下+左右翻转

    import cv2
    from OpenCv_Review.Part_1.Chapter6_Trackbar_Operation.section1_stack import stack_imagesimg = cv2.imread('../../Resources/Maserati.jpg')
    dst1 = cv2.flip(img, flipCode=0)
    dst2 = cv2.flip(img, flipCode=1)
    dst3 = cv2.flip(img, flipCode=-1)flip_stack = stack_images(0.6, ([img, dst1], [dst2, dst3]))cv2.imshow("Flip_Stack", flip_stack)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    实现的效果图如下

  3. 图像旋转

    图像旋转角度为 θ θ θ 是通过以下形式的变换矩阵实现的:

    [ c o s θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] \begin{bmatrix} \ cos \theta & - \sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} [ cosθsinθ​−sinθcosθ​]

    但是OpenCV提供了可缩放的旋转以及可调整的旋转中心,因此您可以在自己喜欢的任何位置旋转。修改后的变换矩阵为

    [ α β ( 1 − α ) ⋅ center.x − β ⋅ center.y − β α β ⋅ center.x + ( 1 − α ) ⋅ center.y ] \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} - \beta \cdot \texttt{center.y} \\ - \beta & \alpha & \beta \cdot \texttt{center.x} + (1- \alpha ) \cdot \texttt{center.y} \end{bmatrix} [α−β​βα​(1−α)⋅center.x−β⋅center.yβ⋅center.x+(1−α)⋅center.y​]

    其中:
    α = scale ⋅ cos ⁡ angle , β = scale ⋅ sin ⁡ angle \begin{array}{l} \alpha = \texttt{scale} \cdot \cos \texttt{angle} , \\ \beta = \texttt{scale} \cdot \sin \texttt{angle} \end{array} α=scale⋅cosangle,β=scale⋅sinangle​

    为了找到此转换矩阵,OpenCV提供了一个函数 cv.getRotationMatrix2D

    下列代码采用提供的函数和根据公式的自定义函数实现

    import cv2
    import numpy
    import matplotlib.pyplot as plt
    from math import *def rotate_pic(scale, angle):angle = (angle / 180) * pialpha = scale * cos(angle)beta = scale * sin(angle)rotate_arr = numpy.float32([[alpha, beta, (1 - alpha) * center_x - beta * center_y],[-beta, alpha, beta * center_x + (1 - alpha) * center_y]])return rotate_arrimg = cv2.imread("../../Resources/Maserati.jpg")width, height, channels = img.shape
    center_x = width // 2
    center_y = height // 2M = cv2.getRotationMatrix2D((center_x, center_y), 45, scale=0.8)  # 采用函数实现
    m = rotate_pic(0.8, 45)  # 按照公式自定义实现dst = cv2.warpAffine(img, M, (width, height))
    res = cv2.warpAffine(img, m, (width, height))titles = ['Image', 'getRotationMatrix2D', 'rotate_pic']
    images = [img, dst, res]for i in range(3):plt.subplot(1, 3, i + 1)plt.imshow(images[i])plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    
  4. 图像仿射变换

    仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换,是一个线性变换,该过程只发生旋转和平移过程。因此,一个平行四边形经过仿射变换后还是一个平行四边形。
    所以,仿射= 旋转 + 平移。(该段原理解释来自博客园博主 Baby-Lily)

    import cv2
    import numpy
    import matplotlib.pyplot as pltimg = cv2.imread("../../Resources/opencv-logo.jpg")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    rows, cols, channels = img.shape# 1.创建仿射变换矩阵# 0)原图,不进行变换
    M0 = numpy.float32([[1, 0, 0], [0, 1, 0]])# 1)平移
    M1 = numpy.float32([[1, 0, 20], [0, 1, 80]])  # 沿x轴平移+20,沿y轴平移+80# 2)缩放
    M2 = numpy.float32([[0.8, 0, 0], [0, 0.5, 0]])  # x轴变为0.8倍,y轴变为0.5倍# 3)倾斜
    M3 = numpy.float32([[1, 0.5, 0], [0, 1, 0]])  # 沿x轴倾斜0.5倍
    M4 = numpy.float32([[1, 0, 0], [0.5, 1, 0]])  # 沿y轴倾斜0.5倍# 4)翻转/镜像
    M5 = numpy.float32([[-1, 0, cols], [0, 1, 0]])  # 绕y转翻转,沿x轴平移cols个像素单位
    M6 = numpy.float32([[1, 0, 0], [0, -1, rows]])  # 绕x转翻转,沿y轴平移rows个像素单位
    M7 = numpy.float32([[-1, 0, cols], [0, -1, rows]])  # 绕y转翻转、绕x转翻转,最后沿x轴平移cols个像素单位、沿y轴平移rows个像素单位# 2.进行仿射变换# M: 仿射变换矩阵
    dst0 = cv2.warpAffine(img, M0, dsize=(cols, rows))  # 原图,无平移
    dst1 = cv2.warpAffine(img, M1, dsize=(cols, rows))  # 平移
    dst2 = cv2.warpAffine(img, M2, dsize=(cols, rows))  # 缩放
    dst3 = cv2.warpAffine(img, M3, dsize=(cols, rows))  # 倾斜
    dst4 = cv2.warpAffine(img, M4, dsize=(cols, rows))  # 倾斜
    dst5 = cv2.warpAffine(img, M5, dsize=(cols, rows))  # 翻转/镜像
    dst6 = cv2.warpAffine(img, M6, dsize=(cols, rows))  # 翻转/镜像
    dst7 = cv2.warpAffine(img, M7, dsize=(cols, rows))  # 翻转/镜像titles = ['Image', 'Translation', 'Scaling', 'Tilt_1', 'Tilt_2', 'Flip_1', 'Flip_2', 'Flip_3']
    images = [img, dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7]for i in range(8):plt.subplot(2, 4, i + 1)plt.imshow(images[i])plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    

    实现的效果图如下所示

  5. 图像的透视变换

    透视变换是把一个图像投影到一个新的视平面的过程,该过程包括:把一个二维坐标系转换为三维坐标系,然后把三维坐标系投影到新的二维坐标系。该过程是一个非线性变换过程,因此,一个平行四边形经过透视变换后只得到四边形,但不平行。(该段原理解释来自博客园博主 Baby-Lily)

    import numpy as np
    import matplotlib.pyplot as pltimg = cv2.imread("../../Resources/cards.jpg")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    width, height = 250, 350# 1.获取透视变换矩阵M: getPerspectiveTransform(src, dst)
    pts1 = np.float32([[111, 219], [287, 188], [154, 482], [352, 440]])
    pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])# 2.进行透视变换
    matrix = cv2.getPerspectiveTransform(pts1, pts2)
    imgOutput = cv2.warpPerspective(img, matrix, (width, height))titles = ['Image', 'Image_Output']
    images = [img, imgOutput]
    for i in range(2):plt.subplot(1, 2, i + 1)plt.imshow(images[i])plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    

    实现的效果图如下

四、图像过滤、平滑(模糊)处理

图像的时域(分析每个时间点、空间位置的一个点)和频域(分析两个点、线之间的变化:梯度)
滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。
图像滤波是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制。图像滤波的目的:
1.消除图像中混入的噪声;
2.为图像识别抽取出图像特征。
滤波可分为 低通滤波、高通滤波、中通滤波、阻带滤波。都是从频域上区别的。
低通滤波/平滑滤波:减弱或阻隔高频信号,保留低频信号,只留下变化较小的信号。可使图像变模糊,主要用于去噪。
高通滤波:减弱或阻隔低频信号,保留高频信号,只留下变化较大的信号。一般用于获取图像边缘、轮廓或梯度。
中通滤波:获取已知频率范围内的信号,去掉变化较大和较小的信号,留下变化适中的信号。
阻带滤波:去掉已知频率范围内的信号,去掉变化适中的信号,留下变化较大和较小的信号。

  1. 图像过滤

    操作如下:保持这个内核在一个像素上,将所有低于这个内核的 5*5 个像素相加,取其平均值,然后用新的平均值替换中心像素。它将对图像中的所有像素继续此操作。

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt'卷积滤波'
    img = cv2.imread("../../Resources/opencv-logo.jpg")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # 1.定义一个卷积核
    kernel = np.ones((5, 5), np.float32) / 25
    # 2.卷积操作
    dst = cv2.filter2D(img, -1, kernel)titles = ['Image', 'Filter_Image']
    images = [img, dst]for i in range(2):plt.subplot(1, 2, i + 1)plt.title(titles[i])plt.imshow(images[i])plt.xticks([])plt.yticks([])plt.show()
    

    实现效果如下

  2. 图像模糊

    通过将图像与低通滤波器内核进行卷积来实现图像模糊,这对于消除噪音很有用。
    它实际上从图像中消除了高频部分(例如噪声,边缘)。因此,在此操作中边缘有些模糊。

    OpenCV主要提供四种类型的模糊技术(具体介绍还可查看博主 TechArtisan6 的博文 ps:点击名字即可进入相应博文):

    cv2.blur (均值滤波):是指任意一点的像素值,都是周围 N × M N × M N×M 个像素值的均值。

    cv2.medianBlur (中值滤波):中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。选一个含有奇数点的窗口 W W W,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。

    cv2.GaussianBlur(高斯滤波):图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值。高斯滤波让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值

    cv2.bilateralFilter(双边滤波):双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空间与信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部处理的特点。之所以能够达到保边去噪的滤波效果是因为滤波器由两个函数构成:一个函数是由几何空间距离决定滤波器系数,另一个是由像素差值决定滤波器系数。(ps:可用于P图)

    import cv2
    import matplotlib.pyplot as pltimg = cv2.imread('../../Resources/blur_girl.jpg')
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 1.均值滤波,ksize表示内核大小为 3x3
    mean_img = cv2.blur(img, ksize=(3, 3))# 2.中值滤波,ksize 表示核大小。核必须是大于1的奇数,如3、5、7等
    median_img = cv2.medianBlur(img, ksize=7)# 3.高斯滤波,核大小(N, N)必须是奇数,sigmaX 为 X方向方差,主要控制权重。若不指定sigmaY,则sigmaY=sigmaX。
    gaussian_img = cv2.GaussianBlur(img, ksize=(7, 7), sigmaX=3, sigmaY=3)# 双边滤波,d:像素的邻域直径,sigmaColor:颜色空间的标准方差,sigmaSpace:坐标空间的标准方差(像素单位)
    bilateral_img = cv2.bilateralFilter(img, d=34, sigmaColor=68, sigmaSpace=68)titles = ['Image', 'Mean_Image', 'Median_Image', 'Gaussian_Image', 'Bilateral_Image']
    images = [img, mean_img, median_img, gaussian_img, bilateral_img]for i in range(len(images)):plt.subplot(2, 3, i + 1)plt.imshow(images[i])plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    

    实现的效果图如下

五、图像梯度

查找图像梯度,边缘等。OpenCV提供三种类型的梯度滤波器或高通滤波器,即 SobelScharrLaplacian

  1. 锐化操作

    # 1.自定义锐化核
    kernel = numpy.float32([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
    dst1 = cv2.filter2D(src, -1, kernel)# 2.USM锐化(UnsharpMask)
    gaussian = cv2.GaussianBlur(src, ksize=(17, 17), sigmaX=3, sigmaY=3)
    dst2 = cv2.addWeighted(src, 2, gaussian, -1, 0)# cv2.imshow("src", src)
    cv2.imshow("dst1", dst1)
    cv2.imshow("dst2", dst2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    效果图如下

  2. 梯度操作(高通滤波):找轮廓
    Sobel算子 是高斯平滑加微分运算的联合运算,因此它更抗噪声。

    你可以指定要采用的导数方向,垂直或水平(分别通过参数 yorderxorder)。

    你还可以通过参数 ksize 指定内核的大小。如果 ksize = -1,则使用 3x3 Scharr滤波器,比 3x3 Sobel滤波器 具有更好的结果。请参阅文档以了解所使用的内核。

    ② Laplacian 算子

    它计算了由关系 dst = Δ src = ∂ 2 src ∂ x 2 + ∂ 2 src ∂ y 2 \texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2} dst=Δsrc=∂x2∂2src​+∂y2∂2src​ 给出的图像的拉普拉斯图,它是每一阶导数通过 Sobel算子 计算。如果 ksize = 1,然后使用以下内核用于过滤:

    k e r n e l = [ 0 1 0 1 − 4 1 0 1 0 ] kernel= \begin{bmatrix} \ 0 & 1 & 0 \\ \ 1 & -4 & 1 \\ \ 0 & 1 & 0 \end{bmatrix} kernel=⎣⎡​ 0 1 0​1−41​010​⎦⎤​

    import cv2
    import matplotlib.pyplot as plt# 梯度操作/高通滤波:找轮廓
    gray = cv2.imread("../../Resources/paper2.jpg", cv2.IMREAD_GRAYSCALE)# 1.Sobel算子: dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
    sobel_x = cv2.Sobel(gray, -1, dx=1, dy=0, ksize=3)  # x轴方向上的一阶导数
    sobel_y = cv2.Sobel(gray, -1, dx=0, dy=1, ksize=3)  # y轴方向上的一阶导数
    sobel_x_abs = cv2.convertScaleAbs(sobel_x, alpha=2, beta=1)
    sobel_y_abs = cv2.convertScaleAbs(sobel_y, alpha=2, beta=1)sobel = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0)  # 近似有|G|=|Gx|+|Gy|# 2.Scharr算子: dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
    scharr_x = cv2.Scharr(gray, -1, dx=1, dy=0)  # x轴方向上的一阶导数
    scharr_y = cv2.Scharr(gray, -1, dx=0, dy=1)  # y轴方向上的一阶导数
    scharr_x_abs = cv2.convertScaleAbs(scharr_x)
    scharr_y_abs = cv2.convertScaleAbs(scharr_y)
    scharr = cv2.addWeighted(scharr_x_abs, 0.5, scharr_y_abs, 0.5, 0)  # 近似有|G|=|Gx|+|Gy|# 近似有|G|=|Gx|+|Gy|
    # 3.Laplacian算子
    laplacian = cv2.Laplacian(gray, -1)# 结合matplotlib显示多张图片
    titles = ['Original Gray', 'Sobel x', 'Sobel y', 'Sobel', 'Scharr x', 'Scharr y', 'Scharr', 'Laplacian']
    images = [gray, sobel_x_abs, sobel_y_abs, sobel, scharr_x, scharr_y, scharr, laplacian]
    for i in range(8):plt.subplot(2, 4, i + 1)plt.imshow(images[i], cmap="gray")plt.title(titles[i])plt.xticks([]), plt.yticks([])
    plt.show()
    

    效果图如下

六、图像形态学操作

  1. 构造一个特定形状和大小的结构元素(核),用于形态学操作。
    kernel = cv2.getStructuringElement(shape, ksize, anchor=None)
    参数:
    shape: 核的形状。
    MORPH_RECT = 0:矩形
    MORPH_CROSS = 1:交叉形
    MORPH_ELLIPSE = 2:椭圆形
    ksize: 核的结构大小

  2. 几种基本形态学操作
    ① 膨胀: 原图部分区域(A)与核(B)进行卷积,求局部最大值,并将局部最大值赋值给指定像素,从而增长高亮区域。
    dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    ② 腐蚀: 与膨胀相反,用局部极小值替换当前像素,从而缩短高亮区域。
    erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    ③ 更多形态学操作
    morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)

    参数:
    op:形态学操作类型。
    cv2.MORPH_DILATE膨胀。–> 增长高亮部分
    cv2.MORPH_ERODE腐蚀。–> 缩短高亮部分
    cv2.MORPH_GRADIENT梯度,(膨胀 - 腐蚀)。–> 提取轮廓
    cv2.MORPH_OPEN开,先腐蚀在膨胀。–> 去除噪点
    cv2.MORPH_CLOSE闭,先膨胀再腐蚀。–> 填补漏洞
    cv2.MORPH_TOPHAT顶帽/礼帽,(原图 - 开)。–> 获取噪点
    cv2.MORPH_BLACKHAT黑帽,(闭 - 原图)。–> 获取漏洞

    import cv2
    import numpy as np
    import matplotlib.pyplot as pltimg = cv2.imread('../../Resources/number8.jpg')
    rows, cols, channel = img.shape# 加噪声
    for i in range(50):x = np.random.randint(0, rows)y = np.random.randint(0, cols)if x % 2 == 0 and y % 2 == 0:img[x, y, :] = 255else:img[x, y, :] = 0# 1.获取指定形状和大小的结构元素(核)
    kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(3, 3))# 2.形态学操作:必须是二值化图,膨胀和腐蚀的部分是白颜色
    dilate_img = cv2.dilate(img, kernel)  # 膨胀
    erode_img = cv2.erode(img, kernel)  # 腐蚀
    morph_dilate_img = cv2.morphologyEx(img, cv2.MORPH_DILATE, kernel)  # 膨胀,增长高亮部分
    morph_erode_img = cv2.morphologyEx(img, cv2.MORPH_ERODE, kernel)  # 腐蚀,缩短高亮部分
    morph_gradient_img = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)  # 梯度,提取轮廓
    morph_open_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  # 开: 先腐蚀再膨胀,用于去噪
    morph_close_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)  # 闭: 先膨胀后腐蚀,用于填补漏洞
    morph_top_hat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)  # 顶帽/礼帽: 原图-开,用于获取噪点
    morph_black_hat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)  # 黑帽: 闭-原图,用于获取漏洞titles = ['Image', 'Dilate', 'Erode', 'Morph_Dilate', 'Morph_Erode', 'Morph_Gradient','Morph_Open', 'Morph_Close', 'Morph_Top_Hat', 'Morph_Black_Hat']
    images = [img, dilate_img, erode_img, morph_dilate_img, morph_erode_img, morph_gradient_img,morph_open_img, morph_close_img, morph_top_hat, morph_black_hat]for i in range(len(images)):plt.subplot(4, 3, i + 1)plt.imshow(images[i], cmap='gray')plt.title(titles[i])plt.xticks([])plt.yticks([])plt.show()
    

    实现的效果图如下

【OpenCV】Mango的OpenCV学习笔记【三】相关推荐

  1. J2EE学习笔记三:EJB基础概念和知识 收藏

    J2EE学习笔记三:EJB基础概念和知识 收藏 EJB正是J2EE的旗舰技术,因此俺直接跳到这一章来了,前面的几章都是讲Servlet和JSP以及JDBC的,俺都懂一些.那么EJB和通常我们所说的Ja ...

  2. tensorflow学习笔记(三十二):conv2d_transpose (解卷积)

    tensorflow学习笔记(三十二):conv2d_transpose ("解卷积") deconv解卷积,实际是叫做conv_transpose, conv_transpose ...

  3. Ethernet/IP 学习笔记三

    Ethernet/IP 学习笔记三 原文为硕士论文: 工业以太网Ethernet/IP扫描器的研发 知网网址: http://kns.cnki.net/KCMS/detail/detail.aspx? ...

  4. iView学习笔记(三):表格搜索,过滤及隐藏列操作

    iView学习笔记(三):表格搜索,过滤及隐藏某列操作 1.后端准备工作 环境说明 python版本:3.6.6 Django版本:1.11.8 数据库:MariaDB 5.5.60 新建Django ...

  5. 吴恩达《机器学习》学习笔记三——多变量线性回归

    吴恩达<机器学习>学习笔记三--多变量线性回归 一. 多元线性回归问题介绍 1.一些定义 2.假设函数 二. 多元梯度下降法 1. 梯度下降法实用技巧:特征缩放 2. 梯度下降法的学习率 ...

  6. Python基础学习笔记三

    Python基础学习笔记三 print和import print可以用,分割变量来输出 import copy import copy as co from copy import deepcopy ...

  7. Mr.J-- jQuery学习笔记(三十二)--jQuery属性操作源码封装

    扫码看专栏 jQuery的优点 jquery是JavaScript库,能够极大地简化JavaScript编程,能够更方便的处理DOM操作和进行Ajax交互 1.轻量级 JQuery非常轻巧 2.强大的 ...

  8. MYSQL学习笔记三:日期和时间函数

    MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...

  9. ROS学习笔记三:创建ROS软件包

    ,# ROS学习笔记三:创建ROS软件包 catkin软件包的组成 一个软件包必须满足如下条件才能被称之为catkin软件包: 这个软件包必须包含一个catkin编译文件package.xml(man ...

  10. Python学习笔记三之编程练习:循环、迭代器与函数

    Python学习笔记三之编程练习 1. 编程第一步 # 求解斐波纳契数列 #/user/bin/python3#Fibonacci series:斐波那契数列 #两个元素的总和确定了下一个数 a,b= ...

最新文章

  1. uboot流程——命令行模式以及命令处理介绍
  2. PolarMask:单阶段实例分割框架,FCOS进阶!
  3. 编译原理:全片知识难点总结
  4. docker ps 和docker ps -a
  5. 【渝粤教育】国家开放大学2018年秋季 0161-22T教师职业道德 参考试题
  6. 计算机的安全设置在哪儿,电脑防火墙在哪里设置
  7. 什么是数字孪生,它的应用价值在哪里?
  8. 一款好用的并发测试工具、接口测试工具、项目管理工具
  9. 中兴ZXDSL831驱动
  10. showdown让你的网站支持Markdown和代码块highlight
  11. CentOS7和CentOS8 Asterisk 20.0.0 简单图形化界面7--对接讯时FXO网关落地
  12. 【fpdlink】FPDlink接口---TI954解串器功能分析
  13. redis为什么选择了跳跃表而不是红黑树
  14. 第二章 ObjectARX类库简介
  15. 计算机会考作业,计算机会考Excel操作题作业文档.doc
  16. 《有一种失败叫瞎忙》读书笔记
  17. jQuery属性遍历、HTML操作
  18. C# Development 13 Things Every C# Developer Should Know--C#开发人员应该知道的13件事情
  19. 安卓 chrome html文件,打开Chrome浏览器在本地文件的Android
  20. 关闭工单时报错 订单 XXXX 的未处理将来更改记录阻止删除标记/完成

热门文章

  1. 真实经历!运维安全工程师经典面试汇总
  2. C#,入门教程(04)——Visual Studio 2022 数据编程实例:随机数与组合
  3. 智能合约升级原理01---起源
  4. 【python数据分析(24)】Matplotlib库基本图形绘制(1)(线形图、柱状图、堆叠图、面积图、填图、饼图)
  5. 抖音投放怎么收费?抖音投放展现方式有哪些
  6. 用python3爬取天猫商品评论并分析(1)
  7. 2019天津市计算机等级考试报名时间,天津2020上半年计算机等级考试报名时间已公布...
  8. 让IE6,IE7,IE8共存
  9. Python3使用Xpath解析网易云音乐歌手页面
  10. 原腾讯QQ技术总监、T13专家,黄希彤被裁,原因竟是不愿意被 PUA ?