阿刚带你学Opencv--图像的基本处理

图像的基本处理

  • 前言
    • 几何变换
    • 形态学操作
    • 图像平滑
    • 直方图
    • 边缘检测
    • 模板匹配:
    • 霍夫变换:
    • 傅里叶变换
    • 轮廓检测
    • 图像分割
  • 参考

前言

  • OpenCV工具完成对图像数据的处理(类比机器学习里面的数据的预处理和特征工程,只不过这里处理的数据都是图像。)

几何变换

  • 图像的缩放
  • 图像的平移:
  • 先确定平移矩阵(在x轴方向平移的距离和y轴方向平移的距离);
  • 使用cv.warpAffine()实现对应的仿射操作,传入对应的仿射矩阵M即可。
  • 仿射操作:平移、翻转、旋转、裁切等操作。
  • 图像的旋转:
  • 先确定仿射矩阵,包含2个平移操作和一个旋转操作:
    • M = cv.getRotationMatrix2D((cols/2,rows/2),45,1)
  • 使用cv.warpAffine()实现对应的仿射操作,传入对应的仿射矩阵M即可。
  • 图像的仿射变换:
  • 通过确定在仿射前和仿射后平面上对应的不共线的3个点(形成三角形的3个点)来确定仿射矩阵:

    • M = cv.getAffineTransform(pts1,pts2)
      
  • 使用cv.warpAffine()实现对应的仿射操作,传入对应的仿射矩阵M即可。

  • 图像的透视变换:
  • 通过确定在投影前和投影后平面上任意4个点(其中任意3个点之间不共线,也就是形成一个四边形),来确定透射矩阵。

  • T = cv.getPerspectiveTransform(pts1,pts2)
    
  • 使用cv.warpPerspective(img,T,(cols,rows))实现对应的透视操作。

  • 仿射变换是特殊的透视变换。

  • 图像金字塔
  • 它是用来帮助我们对图像进行多个尺度的采样的操作,方便提取更多的特征,特别是一些细节特征和全局特征。
  • 实现方式:
    • 上采样:cv.pyrUp,对图像进行2倍的放大;
    • 下采样:cv.pyrDown,对图像进行2倍的缩小。

形态学操作

  • 操作的对象一般是二值图。
  • 连通性:
    • 邻域:4邻域、D邻域、8邻域。
    • 确定连通性的意义:用于确定图像中像素点之间的连通性,来确定图片中对应事物的边界和区域。
  • 膨胀与腐蚀:
    • 腐蚀:使用对应的核结构依次对原图像进行与操作得到对应的像素值表示,操作后的结果是对高亮区域进行蚕食。
      • cv.erode()
    • 膨胀:使用对应的核结构依次对原图像进行与操作得到对应的像素值表示,操作后的结果是对高亮区域进行扩张。
      • cv.dilate()
    • 创建核结构:
      • 十字形核结构:cv.getStructuringElement(cv.MORPH_CROSS, (5, 5))
  • 开运算与闭运算:
    • 开运算:先对图像进行腐蚀再膨胀,能够在不影响原图中物体的情况下消除噪声。
      • cv.morphologyEx(close, cv.MORPH_OPEN, kenel)
    • 闭运算:先对原图进行膨胀再腐蚀,能够在不影响原图中物体的情况下消除孔洞。
      • cv.morphologyEx(close, cv.MORPH_CLOSE, kenel)
  • 礼帽和黑帽:
    • 礼帽(顶帽):使用原图像和原图像的开运算的结果之差,表示分离背景中的一些亮的噪声点。

        cvOpen = cv.morphologyEx(img1,cv.MORPH_TOPHAT,kernel)
      
    • 黑帽:使用原图像的闭运算和原图像结果的差,表示分离离物体近的一些暗的斑块。

      cvOpen = cv.morphologyEx(img1,cv.MORPH_BLACKHAT,kernel)
      

图像平滑

  • 常见噪声的表示:
    • 椒盐噪声:包含随机的黑白噪声点。
    • 高斯噪声:包含符合正态分布(高斯分布)的各种颜色的噪声点。
  • 均值滤波:
    • 计算简单,但是效果不好,对图像进行了模糊操作。
      • cv.blur()
  • 高斯滤波:
    • 通过高斯分布计算要高斯模糊处理的像素点对应的像素值的权重大小,离它越远的像素点的权重越小,反之越大。
      • cv.GaussianBlur()
  • 中值滤波:
    • 通过计算像素点和其邻域内所有像素点的像素值的中值,来替换该像素点的像素值,受异常值的影响较小,对于椒盐噪声的处理效果较好。
      • cv.medianBlur()

直方图

  • 目的:用来统计图像中对应的像素值在连续区间上的分布状况,观察图像的对比度情况。

  • cv.calcHist()

  • 掩膜mask:

    • 作用:提取感兴趣的区域、或者屏蔽不需要的区域,或者提取对应区域的指定特征。
    • 制作掩膜一般用只包含0或者1的数组来表示。
  • 直方图均衡化:

    • 目的:提高图片的对比度,让一些细节特征更加突出,更容易辨别。
      • cv.equalizeHist()
  • 自适应直方图均衡化:

    • 目的:解决普通的直方图均衡化全局操作后的一些缺陷,导致原图部分的局部特征更加模糊。

    • 操作过程:

      • 1、将整张图片进行分块(8*8);
      • 2、将每一张分块的图片计算直方图,然后根据指定的对比度阈值来做均衡化;
      • 3、通过插值方法对处在块边缘的像素点的像素值进行求解;
      • 4、将每一块均衡化后的块进行拼接。
    • cv.createCLAHE(clipLimit, tileGridSize)
      

边缘检测

  • 基于对原图像进行求导,然后根据导数的极大值判断最大的梯度和方向,让后根据这样的特性确定边界。

  • 常用方法:

    • 基于搜索(一阶导):sobel算子、Scharr算子
    • 基于零穿越(二阶导):Laplacian算子
  • sobel算子:

    • 利用在x方向的一阶导和y方向的一阶导进行合成,最终通过显示对应的梯度值的一个分布状况,显示原图中的对应的边界和边缘信息。
    • 当卷积核大小为3时,可以将sobel算子演化成Scharr算子,Scharr算子在精度上比一般的sobel算子更精确。
  • canny算子:

    • 1、对图像进行高斯滤波处理,去除噪声;

    • 2、将去除噪声后的图像进行梯度计算,使用sobel算子分别计算x方向和y方向的梯度,然后合成,最后计算梯度的方向;

    • 3、利用非极大值抑制,获取边界中的极大值,形成最初的细边界;

    • 4、利用指定的滞后阈值,设置最大梯度值和最小梯度值,如果对应像素点求出的梯度值大于最大值,则被判断成边界点,如果小于最小值,则被舍弃,如果介于最大值和最小值之间,那就判断此像素点是否和边界点相连,如果是,则被判断成边界点,否则不是,进行舍弃。

    • cv.Canny(image, threshold1, threshold2)
      
    • canny算子相比于sobel算子来说精度更高,但是效率相比之下更低,sobel算子计算量相对较小,但是精度相比之下不够。

模板匹配:

  • 原理:使用需要匹配的模板图片当做滑动窗口依次从原图片的左上角计算对应区域的相似度,然后通过比较相似度矩阵中的值的大小,获取最大值,然后对应的坐标也可获取,最终即可得到目标图像中和模板图像最相似的区域。

    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    # 1 图像和模板读取
    img = cv.imread('图像的位置')
    template = cv.imread('模板位置')
    h,w,l = template.shape
    # 2 模板匹配
    # 2.1 模板匹配
    res = cv.matchTemplate(img, template, cv.TM_CCORR)
    # 2.2 返回图像中最匹配的位置,确定左上角的坐标,并将匹配位置绘制在图像上
    min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
    # 使用平方差时最小值为最佳匹配位置
    # top_left = min_loc
    top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv.rectangle(img, top_left, bottom_right, (0,255,0), 2)
    # 3 图像显示
    plt.imshow(img[:,:,::-1])
    plt.title('匹配结果'), plt.xticks([]), plt.yticks([])
    plt.show()
    
  • 缺陷,对于尺度变换、视角变换的图片匹配效果不好。

霍夫变换:

  • 直线检测原理:
    通过在笛卡尔坐标系中的共线的点(直线)能确定霍夫空间中的唯一的坐标点,那么可以利用这一性质,确定了霍夫空间中的一个点,那么原图像空间(笛卡尔坐标系)中的对应的直线也就能唯一确定了。
  • 直线检测实现步骤:
    • 1、对原图像进行边缘检测,得到二值图;
    • 2、遍历二值图中有值的点,构建累加器,遍历 θ \theta θ 的值(0-180),可以求解对应的 r 值,通过计算相同的 θ \theta θ 和r的取值对累加器中对应位置的点进行累加,每计算出一个相同的值,则对应位置累加1;
    • 3、根据构建的累加器,获取取得最大值时的 θ \theta θ 和r 的值,那么最后即可确定图像空间的某一条直线。
  • 霍夫变换检测直线
    # coding=utf-8
    # 本文件代码目的:opencv 霍夫变换实现图片旋转角度计算
    # 作者:syg(史永刚)
    # 公司-职位:我爱我家图像识别算法工程师
    # 微信公众号:AI初学者
    # csdn:AI-初学者
    # 知乎:AI-初学者
    import random
    import cv2 as cv
    import matplotlib.pyplot as plt
    # 1.加载图片,转为二值图
    img = cv.imread('图片位置')
    
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    edges = cv.Canny(gray, 50, 150)
    
    # 2.霍夫直线变换
    lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150)
    # 3.将检测的线绘制在图像上(注意是极坐标噢)
    for line in lines:
        rho, theta = line[0]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a * rho
        y0 = b * rho
        x1 = int(x0 + 1000 * (-b))
        y1 = int(y0 + 1000 * (a))
        x2 = int(x0 - 1000 * (-b))
        y2 = int(y0 - 1000 * (a))
        cv.line(img, (x1, y1), (x2, y2), (0, 255, 0))
    # 4. 图像显示
    plt.figure(figsize=(10,8),dpi=100)
    plt.imshow(img[:,:,::-1]),plt.title('霍夫变换线检测')
    plt.xticks([]), plt.yticks([])
    plt.show()
    
  • 霍夫变换检测圆
    import cv2 as cv
    import numpy as np
    import matplotlib.pyplot as plt
    # 1 读取图像,并转换为灰度图
    planets = cv.imread("./image/star.jpeg")
    gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)
    # 2 进行中值模糊,去噪点
    img = cv.medianBlur(gay_img, 7)  
    # 3 霍夫圆检测
    circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 200, param1=100, param2=30, minRadius=0, maxRadius=100)
    # 4 将检测结果绘制在图像上
    for i in circles[0, :]:  # 遍历矩阵每一行的数据
        # 绘制圆形
        cv.circle(planets, (i[0], i[1]), i[2], (0, 255, 0), 2)
        # 绘制圆心
        cv.circle(planets, (i[0], i[1]), 2, (0, 0, 255), 3)
    # 5 图像显示
    plt.figure(figsize=(10,8),dpi=100)
    plt.imshow(planets[:,:,::-1]),plt.title('霍夫变换圆检测')
    plt.xticks([]), plt.yticks([])
    plt.show()
    

傅里叶变换

轮廓检测

图像分割

参考

itcast Ai7期系列课程

阿刚带你学Opencv--图像的基本处理_第1张图片
阿刚带你学Opencv--图像的基本处理_第2张图片

你可能感兴趣的:(小学生的OpenCV之旅,opencv,计算机视觉,python)