• 【python版CV】-图像处理(1)


    开头一下: 上一篇学习完了图像的基础操作,这一篇博客是记录图像处理的一部分。回顾python版的OpenCV第二篇,对于相关的图像处理也有一定的了解。视频参考B站唐宇迪博士,也是来自一位计算机视觉的大佬推荐。


    1、图像阈值

    ret,dst=cv2.threshold(src,thresh,maxval,type)
    
    • 1
    • src:输入图,只能输入单通道图像,一般为灰度图

    • dst:输出图

    • thresh:阈值

    • maxval:当像素值超过阈值(或者小于阈值),所赋予的值

    • type:二值化(大于取一个值,小于取另一个值)操作的类型,包含五种类型

      THRESH_BINARY:超过阈值部分取maxval,否则为0

      THRESH_BINARY_INV: THRESH_BINARY的反转

      THRESH_TRUNC:大于阈值部分设为阈值,否则不变

      THRESH_TOZERO:大于阈值部分不改变,否则设为0

      THRESH_TOZERO_INV: THRESH_TOZERO的反转

    #图像阈值
    #显示原图
    #img=cv.cvtColor(img,cv.COLOR_BGR2GRAY) #图像取灰
    cv_show("yuantu",img)
    ret,thresh1=cv.threshold(img,127,255,cv.THRESH_BINARY)
    ret,thresh2=cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
    ret,thresh3=cv.threshold(img,127,255,cv.THRESH_TRUNC)
    ret,thresh4=cv.threshold(img,127,255,cv.THRESH_TOZERO)
    ret,thresh5=cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
    title=['Original','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
    images=[img,thresh1,thresh2,thresh3,thresh4,thresh5]
    for i in range(6):
        plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
        plt.title(title[i])
        plt.xticks([]),plt.yticks([])
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    2、图像平滑

    2.1 均值滤波

    说明:通过构造一个卷积矩阵,做内积。

    image=cv.imread('E:\\Pec\\zao.jpg')
    cv.imshow('image',image)
    cv.waitKey(0)
    cv.destroyAllWindows() #如果之前没有释放掉内存的操作的话destroyallWIndows会释放掉被那个变量占用的内存
    #简单的平均卷积操作
    blur=cv.blur(image,(3,3))
    #cv_show('blur',blur)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2 方框滤波

    说明:基本和均值滤波一样,可以选择归一化

    box=cv.boxFilter(image,-1,(3,3),normalize=False)#-1表示输入的元素一致。
    # normalize=True表示做归一化,与均值滤波一直。若为false,不做归一化,不除以矩阵长和宽,但是容易越界。
    #大于255,则取255
    #cv_show('box',box)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    2.3 高斯滤波

    说明:高斯模糊的卷积核里面的数值满足高斯分布(就是凸曲线,更重视中间的)

    aussian=cv.GaussianBlur(image,(5,5),1)
    #cv_show('aussian',aussian)
    
    • 1
    • 2

    2.4 中值滤波

    说明:取一个卷积之后,然后取中间值代替

    median=cv.medianBlur(image,5)
    #cv_show("median",median)
    
    • 1
    • 2

    2.5 集中展示

    #集中展示
    res=np.hstack((blur,aussian,median))
    #np.hatack:按水平方向堆叠数组,构成一个新数组
    #np.vstack:按垂直方向堆叠数组,构成一个新数组
    print(res)
    cv_show("average",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [[[226 134  53]
      [226 134  53]
      [226 134  53]
      ...
      [226 134  53]
      [226 134  53]
      [226 134  53]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    3、形态学—腐蚀操作

    #形态学-腐蚀操作
    image=cv.imread('E:\\Pec\\fushi.jpg')
    cv_show("fushi-Ori",image)
    kernel=np.ones((2,2),np.uint8)#(2,2)表示腐蚀的核大小,就是腐蚀的半径
    erosion=cv.erode(image,kernel,iterations=1)#iterations=1表示腐蚀的次数
    cv_show("fushi-eff",erosion)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    原图:

    在这里插入图片描述

    腐蚀之后:

    在这里插入图片描述

    接着连续图片介绍腐蚀过程:

    pie=cv.imread('E:\\Pec\\fushiyuan.jpg')
    cv_show("pie",pie)
    kernel=np.ones((20,20),np.uint8)
    erosion1=cv.erode(pie,kernel,iterations=1)
    erosion2=cv.erode(pie,kernel,iterations=2)
    erosion3=cv.erode(pie,kernel,iterations=3)
    res=np.hstack((erosion1,erosion2,erosion3))
    cv_show('fushilianhuantu',res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8MLHEick-1658901677758)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220725230820236.png)]

    4 形态学—膨胀操作

    #形态学-膨胀操作
    image=cv.imread('E:\\Pec\\fushi.jpg')
    cv_show("fushi-Ori",image)
    kernel=np.ones((3,3),np.uint8)#(2,2)表示腐蚀的核大小,就是腐蚀的半径
    erosion=cv.erode(image,kernel,iterations=1)#iterations=1表示腐蚀的次数
    cv_show("fushi-eff",erosion)
    dige_dilate=cv.dilate(erosion,kernel,iterations=1)
    cv_show('dilate',dige_dilate)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    5、开运算与闭运算

    #开:先腐蚀,再膨胀
    image=cv.imread('E:\\Pec\\fushi.jpg')
    kernel=np.ones((3,3),np.uint8)#(2,2)表示腐蚀的核大小,就是腐蚀的半径
    opening=cv.morphologyEx(image,cv.MORPH_OPEN,kernel)
    #cv_show("opening",opening)
    #闭:先膨胀,再腐蚀
    image=cv.imread('E:\\Pec\\fushi.jpg')
    kernel=np.ones((3,3),np.uint8)#(2,2)表示腐蚀的核大小,就是腐蚀的半径
    closeing=cv.morphologyEx(image,cv.MORPH_CLOSE,kernel)
    #cv_show("close",closeing)
    res=np.hstack((image,opening,closeing))
    cv_show('fushilianhuantu',res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    6、梯度运算

    说明:#梯度=膨胀-腐蚀

    pie=cv.imread('E:\\Pec\\fushiyuan.jpg')
    kernel=np.ones((20,20),np.uint8)
    erode=cv.erode(pie,kernel,iterations=2)
    dilate=cv.dilate(pie,kernel,iterations=2)
    res=np.hstack((pie,erode,dilate))
    cv_show("zhanshi",res)
    gradient=cv.morphologyEx(pie,cv.MORPH_GRADIENT,kernel)
    cv_show("gradient",gradient)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    在这里插入图片描述

    7、礼帽和黑帽

    • 礼帽=原始输入-开运算结果(开运算:先腐蚀再膨胀)
    • 黑帽=闭运算-原始输入(闭运算:先膨胀,再腐蚀)
    #礼帽和黑帽
    image=cv.imread('E:\\Pec\\fushi.jpg')
    kernel=np.ones((3,3),np.uint8)#(2,2)表示腐蚀的核大小,就是腐蚀的半径
    topat=cv.morphologyEx(image,cv.MORPH_TOPHAT,kernel)
    res=np.hstack((image,topat))
    cv_show("limao",res)
    blackhat=cv.morphologyEx(image,cv.MORPH_BLACKHAT,kernel)
    res=np.hstack((image,blackhat))
    cv_show("heimao",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    在这里插入图片描述

    8、图像梯度

    8.1 Sobel算子

    说明:
    Sobel算子是像素图像边缘检测中最重要的算子之一。在技术上,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。该方法能通过增强图像的边缘效果来突出图像的轮廓特征。

    为什么要检测边缘?
    比如自动驾驶里面,我们至少要做的一个工作就是道路的边缘检测,只有正确的检测到道路的边缘我们的车才会行驶在道路上而不是开到马路牙子外。
    或者从另一个角度解释,我们做边缘检测不是让人眼去欣赏一张道路图片里面的道路边缘的,我们正确检测出一张图像的边缘是为了让模型更好的去认识这张图片中的道路。所以精确的边缘检测可以帮助电脑模型很好的识别这是道路还是道路外面,从而做出正确的反馈——指导汽车正确行使。

    在这里插入图片描述

    d s t = c v . S o b e l ( s r c , d d e p t h , d x , d y , k s i z e ) dst=cv.Sobel(src,ddepth,dx,dy,ksize) dst=cv.Sobel(src,ddepth,dx,dy,ksize)

    • ddepth:图像的深度,通常指定-1
    • dx和dy分别表示水平和竖直方向
    • ksize是Sobel算子的大小,必须是1,3,5,7.默认是3
    #cv.CV_64F,opencv默认把负值重新定义为0.加上这个就允许有负值
    pie=cv.imread('E:\\Pec\\fushiyuan.jpg')
    cv_show("yuan",pie)
    sobelx=cv.Sobel(pie,cv.CV_64F,1,0,ksize=3)#1,0只算水平方向
    #右边-左边:白到黑是正数,黑到白是负数,所有的负数都会截断成0,所以要取绝对值
    sobelx=cv.convertScaleAbs(sobelx)
    #cv_show("sobelx",sobelx)
    #竖直方向
    sobely=cv.Sobel(pie,cv.CV_64F,0,1,ksize=3)#1,0只算水平方向
    #右边-左边:白到黑是正数,黑到白是负数,所有的负数都会截断成0,所以要取绝对值
    sobely=cv.convertScaleAbs(sobely)
    res=np.hstack((sobelx,sobely))
    cv_show("sobel",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    在这里插入图片描述

    #若要求Gx和Gy不建议直接相加,把上述(1,0)或者(0,1)写成(1,1)
    sobelxy=cv.addWeighted(sobelx,0.5,sobely,0.5,0)#是一种饱和操作,通过各自占的权重相加
    cv_show("sobelxy",sobelxy)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    具体例子:

    #一个例子
    pie=cv.imread('E:\\Pec\\cat.jpg')
    ima=cv.cvtColor(pie,cv.COLOR_BGR2GRAY)
    #cv_show("pie",ima)
    sobelx=cv.Sobel(ima,cv.CV_64F,1,0,ksize=3)
    sobelx=cv.convertScaleAbs(sobelx)
    sobely=cv.Sobel(ima,cv.CV_64F,0,1,ksize=3)#1,0只算水平方向
    sobely=cv.convertScaleAbs(sobely)
    sobelxy=cv.addWeighted(sobelx,0.5,sobely,0.5,0)
    #cv_show("sobelxy",sobelxy)
    sobelxy1=cv.Sobel(ima,cv.CV_64F,1,1,ksize=3)#1,0只算水平方向
    sobelxy1=cv.convertScaleAbs(sobelxy1)
    #cv_show("sobelxy1",sobelxy1)
    res=np.hstack((ima,sobelxy,sobelxy1))
    cv_show("zong",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    8.2 Scharr算子

    把卷积的数值变得更大、更敏感;描绘的更细致

    在这里插入图片描述

    8.3 laplacian算子

    二阶导,一阶导的变化率;更敏感;对噪音点比较敏感;与其他算子一块使用

    在这里插入图片描述

    9 Canny边缘检测

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

    9.1 高斯滤波器

    在这里插入图片描述

    9.2 梯度和方向(Sobel算子)

    在这里插入图片描述

    9.3 非极大值抑制

    线性插值法:设g1的梯度幅值M(g1),g2的梯度幅值M(g2),则dtmp1可以得到:

    M ( d t m p 1 ) = w ∗ M ( g 2 ) + ( 1 − w ) ∗ M ( g 1 ) M(dtmp1)=w*M(g2)+(1-w)*M(g1) M(dtmp1)=wM(g2)+(1w)M(g1)

    w = d i s t a n c e ( d t m p 1 , g 2 ) / d i s t a n c e ( g 1 , g 2 ) / / d i s t a n c e ( g 1 , g 2 ) 表示两点距离 w=distance(dtmp1,g2)/distance(g1,g2) //distance(g1,g2)表示两点距离 w=distance(dtmp1,g2)/distance(g1,g2)//distance(g1,g2)表示两点距离

    最后,通过计算,比较C点梯度幅值是否大于Q、Z,然后抑制非极大值点

    9.4 双阈值检测

    在这里插入图片描述

    9.5 边缘检测

    说明:minVal:80; MaxVal:150;自己指定。若minVal设置过小的时候,筛选范围变小,要求非常低了。maxVal同理

    #边缘检测
    cat=cv.imread('E:\\Pec\\loufang.jpg',cv.IMREAD_GRAYSCALE)
    v1=cv.Canny(cat,120,250)
    #minVal:80; MaxVal:150;自己指定。
    #若minVal设置过小的时候,筛选范围变小,要求非常低了。maxVal同理
    v2=cv.Canny(cat,50,100)
    res=np.hstack((v1,v2))
    cv_show("res",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果可以分析出来:阈值设置的范围越广,图像的细节描述的越清晰
    在这里插入图片描述

  • 相关阅读:
    马赛克后挡板是什么?
    C++ Primer学习笔记-----附录:标准库
    面试--spring基础
    【Java】涉及到GUI、JAVASE、网络编程、多线程、数据库的聊天系统,非常适合大学Java课程的练手
    Spring的事务详解
    Python批处理(一)提取txt中数据存入excel
    马斯克 VS 乔布斯,谁是21世纪最伟大的创业家
    机器学习基础-Pandas学习笔记
    基于 FPGA 实现 IIC(I2C) 协议控制 EEPROM 读写操作
    【Spring Cloud】Nacos 配置管理详解
  • 原文地址:https://blog.csdn.net/qq_44859533/article/details/126013349