• opencv-python图像处理:Canny边缘检测算法,模板匹配,直方图均衡化,傅里叶变换


    1 Canny边缘检测流程

    1)使用高斯滤波器,以平滑图像,滤除噪声
    2)计算图像中每个像素点的梯度强度和方向
    3)应用非极大值抑制,以消除边缘检测带来的杂散响应
    4)应用双阈值检测来确定真实的和潜在的边缘
    5)通过抑制孤立的弱边缘最终完成边缘检测

    1.高斯滤波器
    在这里插入图片描述
    2.梯度和方向
    在这里插入图片描述
    3.非极大值抑制
    在这里插入图片描述
    4.双阈值检测
    在这里插入图片描述

    import cv2
    import numpy as np
    
    
    def cv_show(im, name):
        cv2.imshow(name, im)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    
    img = cv2.imread('data/test2.jpg', cv2.IMREAD_GRAYSCALE)
    img = cv2.resize(img, (400, 400))
    
    v1 = cv2.Canny(img, 80, 150)
    v2 = cv2.Canny(img, 50, 100)
    
    res = np.hstack((img, v1, v2))
    cv_show(res, 'res')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    结论:区间值越大,检测的边界越少;区间值越少,检测的边界越多。
    在这里插入图片描述
    在这里插入图片描述

    2 图像金字塔

    高斯金字塔
    拉普拉斯金字塔
    在这里插入图片描述
    高斯金字塔:向下采样方法(缩小)
    在这里插入图片描述
    高斯金字塔:向上采样方法(放大)
    在这里插入图片描述

    import cv2
    import numpy as np
    
    
    def cv_show(im, name):
        cv2.imshow(name, im)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    
    img = cv2.imread('data/dog.jpg')
    img = cv2.resize(img, (400, 400))
    
    up = cv2.pyrUp(img)
    cv_show(up, 'up')
    
    down = cv2.pyrDown(img)
    cv_show(down, 'down')
    
    reset = cv2.pyrUp(down)
    res = np.hstack([img, reset])
    cv_show(res, 'res')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    上采样的结果
    在这里插入图片描述
    下采样的结果
    在这里插入图片描述
    原图和先上采样再下采样的图
    在这里插入图片描述
    拉普拉斯金字塔
    在这里插入图片描述

    import cv2
    import numpy as np
    
    
    def cv_show(im, name):
        cv2.imshow(name, im)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    
    img = cv2.imread('data/dog.jpg')
    img = cv2.resize(img, (400, 400))
    
    up = cv2.pyrUp(img)
    down = cv2.pyrDown(img)
    
    reset = cv2.pyrUp(down)
    res = np.hstack([img, reset, img - reset])
    cv_show(res, 'res')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    3 轮廓检测方法

    cv2.findContours(img, mode, method)
    mode:轮廓检索模式

    • RETR_EXTERNAL:只检索最外面的轮廓
    • RETR_LIST:检索所有的轮廓,并将其保存在列表中
    • RETER_CCOMP:检索所有的轮廓,并将它们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界
    • RETER_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次

    method:轮廓逼近方法

    • CHAIN_APPROX_NONE:以Freema链码的方式输出轮廓,所有其他地方输出多边形(顶点序列)。
    • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜外的部分,也就是,函数只是保留它们的终点部分。

    4 模板匹配

    模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv中有六种,将每次计算的结果放入一个矩阵里,作为结果输出。假如原图像是AxB大小,而模板是axb大小,则输出的结果矩阵是(A-a+1)x(B-b+1)
    在这里插入图片描述

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png', cv2.IMREAD_GRAYSCALE)
    template = cv2.imread('data/face.png', cv2.IMREAD_GRAYSCALE)
    w, h = template.shape[0], template.shape[1]
    methods = ['cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_SQDIFF',
               'cv2.TM_SQDIFF_NORMED']
    for meth in methods:
        img2 = img.copy()
        method = eval(meth)
        print(method)
        res = cv2.matchTemplate(img, template, method)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
        # 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED取最小值
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
        bottom_right = (top_left[0] + w, top_left[1] + h)
        # 画矩形
        cv2.rectangle(img2, top_left, bottom_right, 255, 2)
    
        plt.subplot(121), plt.imshow(res, cmap='gray')
        plt.xticks([]), plt.yticks([])
        plt.subplot(122), plt.imshow(img2, cmap='gray')
        plt.xticks([]), plt.yticks([])
        plt.suptitle(meth)
        plt.show()
    
    
    • 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

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5 图像直方图

    在这里插入图片描述

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png', cv2.IMREAD_GRAYSCALE)
    res = cv2.calcHist(images=[img], channels=[0], mask=None, histSize=[256], ranges=[0, 256])
    print(res.shape)  # (256, 1)
    plt.hist(img.ravel(), 256)
    plt.show()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png')
    color = ('b', 'g', 'r')
    for i, col in enumerate(color):
        histr = cv2.calcHist([img], [i], None, [256], [0, 256])
        plt.plot(histr, color=col)
        plt.xlim([0, 256])
    plt.show()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    6 傅里叶变换

    傅里叶变换的作用

    • 高频:变化剧烈的灰度分量,例如边界
    • 低频:变化缓慢的灰度分量,例如一片大海

    滤波

    • 低通滤波器:只保留低频,使得图像模糊
    • 高通滤波器:只保留高频,使得图像细节增强
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png', cv2.IMREAD_GRAYSCALE)
    img_float32 = np.float32(img)
    dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
    dft_shift = np.fft.fftshift(dft)
    # 得到灰度图能表示的形式
    magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
    
    plt.subplot(121), plt.imshow(img, cmap='gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
    plt.title('magnitude spectrum'), plt.xticks([]), plt.yticks([])
    plt.show()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    低通滤波器

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png', cv2.IMREAD_GRAYSCALE)
    img_float32 = np.float32(img)
    dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
    dft_shift = np.fft.fftshift(dft)
    
    rows, cols = img.shape
    c_row, c_col = int(rows / 2), int(cols / 2)  # 中心位置
    
    # 低通滤波器
    mask = np.zeros((rows, cols, 2), np.uint8)
    mask[c_row - 30:c_row + 30, c_col - 30:c_col + 30] = 1
    
    # IDFT
    f_shift = dft_shift * mask
    f_ishift = np.fft.ifftshift(f_shift)
    img_back = cv2.idft(f_ishift)
    img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
    
    plt.subplot(121), plt.imshow(img, cmap='gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(img_back, cmap='gray')
    plt.title('Result'), plt.xticks([]), plt.yticks([])
    
    plt.show()
    
    
    • 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

    在这里插入图片描述

    高通滤波器

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    img = cv2.imread('data/lena.png', cv2.IMREAD_GRAYSCALE)
    img_float32 = np.float32(img)
    dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
    dft_shift = np.fft.fftshift(dft)
    
    rows, cols = img.shape
    c_row, c_col = int(rows / 2), int(cols / 2)  # 中心位置
    
    # 高通滤波器
    mask = np.ones((rows, cols, 2), np.uint8)
    mask[c_row - 30:c_row + 30, c_col - 30:c_col + 30] = 0
    
    # IDFT
    f_shift = dft_shift * mask
    f_ishift = np.fft.ifftshift(f_shift)
    img_back = cv2.idft(f_ishift)
    img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
    
    plt.subplot(121), plt.imshow(img, cmap='gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(img_back, cmap='gray')
    plt.title('Result'), plt.xticks([]), plt.yticks([])
    
    plt.show()
    
    
    • 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

    在这里插入图片描述

  • 相关阅读:
    Vue中如何进行自定义动画与动画效果设计(如CSS动画、Web动画)
    【Mac】破解死循环,成功安装 Homebrew、curl、wget,快速配置 zsh
    二、面经整理(二)
    MacBook安装gym
    【C++ Exceptions】异常处理的成本
    uniapp H5项目 获取接口的二进制流转化成图片url(base64)
    前馈神经网络与支持向量机实战 --- 手写数字识别
    Yii2使用composer安装MongoDB扩展
    Go语言错误处理最佳实践
    当遇到 502 错误(Bad Gateway)怎么办
  • 原文地址:https://blog.csdn.net/qq_40507857/article/details/126683892