• 【python版CV】-直方图 & 傅里叶变换


    1、直方图

    说明:统计像素值,用柱形图来统计

    cv.calcHist(images,channels,mask,histSize,ranges)
    
    • 1
    • images:原图像的格式为uint8或者float32.当传入函数时,应用括号[]括起来,如:[image]
    • channels:同样用括号括起来,告诉函数我们统幅图像的直方图。如果入图像是灰度图它的值就是[0],如果是彩色图,它的值可以是[0]、[1]、[2],对应B、G、R
    • mask:掩膜图像。统整幅图像的直方图就把它设为None,但如果想统整幅图像某一部分的直方图就制作一个掩膜图像并使用它。
    • histSize: BIN的数目,括号括起来(一般固定256)
    • ranges:像素范围[0,256](一般固定)
    #直方图
    img=cv.imread("E:\\Pec\\cat.jpg",0)
    hist=cv.calcHist([img],[0],None,[256],[0,256])
    print(hist.shape)
    plt.hist(img.ravel(),256)
    plt.show()
    #彩色图
    img=cv.imread("E:\\Pec\\cat.jpg")
    color=('b','g','r')
    for i,col in enumerate(color):
        histr=cv.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
    • 13
    • 14

    mask操作:

    掩码(mask):只有两部分,一部分为黑,另一部分为白。

    img=cv.imread("E:\\Pec\\cat.jpg",0)
    mask_1=np.zeros(img.shape[:2],np.uint8)
    print(mask_1.shape)
    #选择一些区域
    mask_1[100:300,180:480]=255
    #[100:300]表示上下去100位置到300,同理左右去180位置到480
    cv_show('mask',mask_1)
    masked_img=cv.bitwise_and(img,img,mask=mask_1)#与操作,mask表示要提取的区域
    cv_show('masked_img',masked_img)
    plt.subplot(221),plt.imshow(img,'gray')
    plt.subplot(222),plt.imshow(masked_img,'gray')
    plt.show()
    #plt.subplot(221) 表示将整个图像窗口分为2行2列, 当前位置为1.
    #plt.subplot(221) 表示第一行的左图
    #plt.subplot(222) 表示将整个图像窗口分为2行2列, 当前位置为2.
    #plt.subplot(222) 第一行的右图
    #plt.plot(图线名)
    #plt.xlim() 显示的是x轴的作图范围
    #plt.ylim() 显示的是y轴的作图范围
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    shape学习

    1. shape[:2] 取彩色图片的长和宽
      shape[:3]取彩色图片的长和宽和通道
      
      • 1
      • 2
    2. img.shape[0]:图像的垂直高度
      img.shape[1]:图像的水平宽度
      img.shape[2]:图像的通道数
      
      • 1
      • 2
      • 3
    3. 矩阵中,[0]代表水平,[1]代表高度。
      
      • 1
      print(type(img))  #显示类型
      print(img.shape)  #显示尺寸
      print(img.shape[0])  #图片宽度
      print(img.shape[1])  #图片高度
      print(img.shape[2])  #图片通道数
      print(img.size)   #显示总像素个数
      print(img.max())  #最大像素值
      print(img.min())  #最小像素值
      print(img.mean()) #像素平均值
      print(img.shape[:0])
      print(img.shape[:1])#图片宽度
      print(img.shape[:2])#图片宽度,高度
      print(img.shape[:3])#图片宽度,高度,通道数
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    图像基本运算:

    说明:图像的基本运算有很多种,比如两幅图像可以相加、相减、相乘、相除、位运算、平方根、对数、绝对值等;图像也可以放大、缩小、旋转,还可以截取其中的一部分作为ROI(感兴趣区域)进行操作,各个颜色通道还可以分别提取及对各个颜色通道进行各种运算操作。

    #bitwise_and、bitwise_or、bitwise_xor、bitwise_not这四个按位操作函数。
    void bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()); //dst = src1 & src2
    void bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()); //dst = src1 | src2
    void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray()); //dst = src1 ^ src2
    void bitwise_not(InputArray src, OutputArray dst,InputArray mask=noArray()); //dst = ~src
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • bitwise_and是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0
    • bitwise_or是对二进制数据进行“或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“或”操作,1|1=1,1|0=0,0|1=0,0|0=0
    • bitwise_xor是对二进制数据进行“异或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“异或”操作,11=0,10=1,01=1,00=0
    • bitwise_not是对二进制数据进行“非”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作,1=0,0=1

    直方图均衡化

    在这里插入图片描述
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oX2zIK7-1659425527337)(/image-20220802103530818.png)]

    img=cv.imread("E:\\Pec\\cat.jpg",0)
    hist=cv.calcHist([img],[0],None,[256],[0,256])
    #均衡化
    equ=cv.equalizeHist(img)
    plt.subplot(221),plt.hist(img.ravel(),256)
    plt.subplot(222),plt.hist(equ.ravel(),256)
    plt.show()
    res=np.hstack((img,equ))
    cv_show("red",res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    在这里插入图片描述

    2、傅里叶变换

    说明:生活在时间的世界中,早上7:00吃早饭,8:00上班路上,9:00上班,以时间为参照的时域分析。频域中看来一切都是静止的,以上帝的视角。不需要了解你什么时间按照顺序干了什么事,只需要了解你这一天干了什么就行了

    傅里叶变换的作用

    • 高频:变换剧烈得到灰度分量,例如边界
    • 低频:变化缓慢的灰度分量,例如一望无际的大海

    滤波:

    • 低通滤波器:只保留低频,会使图像变得模糊
    • 高通滤波器:只保留高频,会使图像细节增强

    注意:

    (1)输入图像需要先转换成np.float32格式

    (2)得到的结果中频域为0的部分会在左上角,通常要转到中心位置,可以通过shift变换来实现

    (3)cv.dft()返回的结果是双通道的(实部,虚部),通常需要转换成图像格式才能展示(0,255)

    补充:

    (1)numpy.zeros(shape, dtype=float)

    • 各个参数意义:
      shape:创建的新数组的形状(维度)。
      dtype:创建新数组的数据类型。
    • 返回值:给定维度的全零数组。

    (2)numpy.ones(shape, dtype=None, order=‘C’)

    • 可以创建任意维度和元素个数的数组,其元素值均为1
    • shape :int或int的序列,为新数组的形状;
    • dtype(可选 ):数组的所需数据类型;默认是 numpy.float64。
    • order : {‘C’,‘F’},可选,默认值:C 是否在内存中以行主(C-风格)或列主(Fortran-风格)顺序存储多维数据。
    img=cv.imread("E:\\Pec\\lida.jpg",0)
    img_float32=np.float32(img)#输入图像需要先转换成np.float32格式
    #傅里叶转换为复数
    dft=cv.dft(img_float32,flags=cv.DFT_COMPLEX_OUTPUT)
    #将低频从左上角转换到中心
    dft_shift=np.fft.fftshift(dft)
    #得到灰度图能表示的形式
    #cv.dft()返回的结果是双通道的(实部,虚部),通常需要转换成图像格式才能展示(0,255)
    magnitude_spectrum=20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
    plt.subplot(121),plt.imshow(img,'gray')
    plt.title('Input Image'),plt.xticks([]),plt.yticks([])
    plt.subplot(122),plt.imshow(magnitude_spectrum,'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

    在这里插入图片描述

    低通滤波器

    #低通滤波器
    img=cv.imread("E:\\Pec\\lida.jpg",0)
    img_float32=np.float32(img)#输入图像需要先转换成np.float32格式
    #傅里叶转换为复数
    dft=cv.dft(img_float32,flags=cv.DFT_COMPLEX_OUTPUT)
    #将低频从左上角转换到中心
    dft_shift=np.fft.fftshift(dft)
    #找到图像中心位置
    rows,cols=img.shape
    crow,col=int(rows/2),int(cols/2)
    #低通滤波
    #生成rows行cols列的2纬矩阵,数据格式为uint8,uint8的范围[0,255]
    mask=np.zeros((rows,cols,2),np.uint8)
    mask[crow-30:crow+30,col-30:col+30]=1
    #IDFT
    fshift=dft_shift*mask
    f_ishift=np.fft.ifftshift(fshift)
    img_back=cv.idft(f_ishift)
    img_back=cv.magnitude(img_back[:,:,0],img_back[:,:,1])
    plt.subplot(121),plt.imshow(img,'gray')
    plt.title('Input Image'),plt.xticks([]),plt.yticks([])
    plt.subplot(122),plt.imshow(img_back,'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

    从结果可以看出,图像的边缘模糊,但是图像除边缘部分的其他地方不模糊

    在这里插入图片描述

    高通滤波器

    #高通滤波
    #生成rows行cols列的2纬矩阵,数据格式为uint8,uint8的范围[0,255]
    mask=np.ones((rows,cols,2),np.uint8)
    mask[crow-30:crow+30,col-30:col+30]=0
    
    • 1
    • 2
    • 3
    • 4

    从结果可以看出,图像只有边缘信息保存下来,内容模糊不见了
    在这里插入图片描述

  • 相关阅读:
    Leetcode刷题详解——长度最小的子数组
    【有营养的算法笔记】快速排序
    第十七章:IO流
    Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别&常见的几种异常
    new动态创建一维数组、qsort函数、折半查找
    QT收藏夹
    yum命令中的gcc是什么含义?答:是一种包,并不是参数。
    基于SqlSugar的开发框架循序渐进介绍(15)-- 整合代码生成工具进行前端界面的生成
    数据结构——克鲁斯卡尔(Kruskal)算法
    (6)点云数据处理学习——RGBD图
  • 原文地址:https://blog.csdn.net/qq_44859533/article/details/126123494