python中图像处理_python图像处理库pil中图像格式转换 - CSDN
  • 其中,OpenCV是图像处理中最强大的一个库,它的源代码是由C\C++写成的,所以原版的OpenCV可以与C、C++无缝结合。Python版的OpenCV主要依赖于cv2这个包来实现。Python里面自带一个PIL(python images library),但这...

    在Python中进行图像处理可以使用的库有很多,本文主要介绍下面三个:

    • OpenCV(Open Source Computer Vision Library)
    • PIL(Python Imaging Library)
    • skimage(scikit-image)

    *如下代码的实验环境为Jupyter Notebook.

    欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。


    1. OpenCV

    OpenCV是图像处理中最强大的一个库,它的源代码是由C\C++写成的,所以原版的OpenCV可以与C、C++无缝结合。Python版的OpenCV主要依赖于cv2这个包来实现。

    1.1  imread()

    import cv2
    import numpy as np
    
    #读入图片:默认彩色图,cv2.IMREAD_GRAYSCALE灰度图,cv2.IMREAD_UNCHANGED包含alpha通道
    img = cv2.imread('Lena.png')
    print(img.shape)
    print(type(img))

    上述代码的执行结果如下:

    (512, 512, 3)
    <class 'numpy.ndarray'>
    

    此时,被读入的图像以ndarray格式存在,取值范围是 [0, 255]。

    1.2  imshow()

    cv2.imshow('Lena',img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    函数imshow()用于显示图像,但只使用它并不会得到任何结果,必须结合后面的waitKey(delay),参数delay表示延迟多少毫秒。默认情况为0。当delay≤0,可以理解为延迟无穷大毫秒。调用destroyAllWindows()函数可以释放由 OpenCV创建的所有窗口。注意上面三条语句必须写在Jupyter notebook中的同一Cell里,然后按任意键,系统会关闭图像显示窗口。

    1.3  imwrite()

    cv2.imwrite('lena.jpg',img)

    函数imwrite()用于存储图像,第一个参数是file name,第二个参数是要存储的图像对象。

     

    参考链接【点击链接】

    欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。


    2. PIL

    Python里面自带一个PIL(python images library), 但这个库现在已经停止更新了,所以使用Pillow, 它是由PIL发展而来的。

    1.1  open()

    from PIL import Image
    import numpy as np
    
    img = Image.open('Lena.png')
    print(img.size)
    print(img.mode)
    print(type(img))

    上述代码的执行结果如下:

    (512, 512)
    RGB
    <class 'PIL.PngImagePlugin.PngImageFile'>
    

    1.2 show()

    下面的代码可以用来显示图像,程序会弹出一个单独的图像窗口。

    img.show()

    除此之外,还可以使用matplotlib来绘制图像,它是一个专业绘图的库,相当于matlab中的plot,可以设置多个figure,设置figure的标题,甚至可以使用subplot在一个figure中显示多张图片。

    import matplotlib.pyplot as plt
    %matplotlib inline
    
    plt.imshow(img)

    inline一句的作用是在Jupyter Notebook的网页中直接绘图,即不会单独弹出绘图窗口,上述代码的执行结果如下:

    如果不希望显示坐标轴,则可以使用下面的代码:

    plt.axis('off')
    plt.imshow(img)

    下面的代码演示了显示多行、多列图像的方法,注意其中显示灰度图像的语法。

    fig=plt.figure(figsize=(28, 28))
    columns = 5
    rows = 5
    for i in range(1, columns*rows +1):
        img = test_only_success_adv[650+i].reshape(28,28)+0.5
        fig.add_subplot(rows, columns, i)
        plt.imshow(img, cmap='gray')
        plt.axis('off')

    代码执行结果如下:

    1.3  save()

    图像保存可以使用:

    img.save('lena2.jpg')

    如果要把以ndarray格式存储的矩阵保存成图像,则需要使用:

    im = Image.fromarray(np.uint8(data_jsma_0*255))
    im.save("000.png")

     

    参考链接【点击链接】

    欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。


    3. skimage

     

    1.1  imread()

    参考示例代码:

    from skimage import io
    import numpy as np
    
    img = io.imread('Lena.png')
    print(img.shape) # numpy矩阵,(h,w,c)
    
    print(type(img))

    上述代码执行结果如下:

    (512, 512, 3)
    <class 'numpy.ndarray'>
    

    被读入的图像以ndarray格式存在。

    与之前类似,io.imshow() 和 io.imsave() 分别用于显示和存储图像。

    1.2  img_as_ubyte()

    该函数的作用是convert an image to 8-bit unsigned integer format,也就是把图像像素灰度的取值范围转化到0~255之间的整数。

    例如,

    print(np.max(adv_test_cw0[0]))
    print(np.min(adv_test_cw0[0]))
    
    byte_adv_test_cw0 = img_as_ubyte(adv_test_cw0)
    
    print(np.max(byte_adv_test_cw0[0]))
    print(np.min(byte_adv_test_cw0[0]))

    上述代码的执行结果如下:

    0.9997719
    0.00054621696

    255
    0

     

    参考链接【点击链接】

     

    欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。

    【全文完】

    展开全文
  • 图像的基本处理 读取图片 颜色空间转换 获取图片属性 缩放图片 平移图片 旋转图片 仿射变换 图像颜色变换 通道的拆分/合并处理 图片添加边距 import numpy as np import cv2 as cv # OpenCv库...

    图像的基本处理



    1. 读取图片
    2. 保存图片
    3. 颜色空间转换
    4. 获取图片属性
    5. 缩放图片
    6. 平移图片
    7. 旋转图片
    8. 仿射变换
    9. 通道的拆分/合并处理
    10. 图片添加边距


    import numpy as np
    import cv2 as cv        # OpenCv库
    
    # 为了一直显示图片  在显示图片后加上
    cv.waitKey(0)                 # 等待输入  一直显示当前图片
    
    # 销毁所有窗口
    cv.destroyAllWindows()

    1、读取图片

    img = cv.imread(r".\1.png")     # 相对路径
    # 这里用的相对路径  当然也可以用绝对路径

    函数解析:

    可以go to declaration查看使用说明


    函数原型:
    def imread(filename, flags=None): # real signature unknown; restored from doc
    参数含义:
    @param filename Name of file to be loaded.
    @param flags Flag that can take values of cv::ImreadModes


    参数说明:

    1. filename没什么可说的,绝对地址或者相对地址
    2. 重点说明一下flags参数

    Enumerator

    1. IMREAD_UNCHANGED:不进行转化,比如保存为了16位的图片,读取出来仍然为16位。
      If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
    2. IMREAD_GRAYSCALE :进行转化为灰度图,比如保存为了16位的图片,读取出来为8位,类型为CV_8UC1
      If set, always convert image to the single channel grayscale image.
    3. IMREAD_COLOR :进行转化为三通道图像。
      If set, always convert image to the 3 channel BGR color image.
    4. IMREAD_ANYDEPTH :如果图像深度为16位则读出为16位,32位则读出为32位,其余的转化为8位。
      If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
    5. IMREAD_ANYCOLOR
      If set, the image is read in any possible color format.
    6. IMREAD_LOAD_GDAL 使用GDAL驱动读取文件,GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。
      If set, use the gdal driver for loading the image.


    1、If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function returns an empty matrix ( Mat::data==NULL ).
    翻译过来,当由于某种原因读取不到文件时,返回空矩阵!
    2、该函数支持的文件类型:
    . - Windows bitmaps - *.bmp, *.dib (always supported)
    . - JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
    . - JPEG 2000 files - *.jp2 (see the Notes section)
    . - Portable Network Graphics - *.png (see the Notes section)
    . - WebP - *.webp (see the Notes section)
    . - Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
    . - Sun rasters - *.sr, *.ras (always supported)
    . - TIFF files - *.tiff, *.tif (see the Notes section)
    . - OpenEXR Image files - *.exr (see the Notes section)
    . - Radiance HDR - *.hdr, *.pic (always supported)
    . - Raster and Vector geospatial data supported by Gdal (see the Notes section)
    3、注意点:
    (1)、 The function determines the type of an image by the content, not by the file extension.
    读取的图片的形式是由图片本身的内容决定,而不是由图片的后缀名决定
    (2)、In the case of color images, the decoded images will have the channels stored in B G R order.
    (3)、其他

    2、保存图片

    3、颜色转换

    使用cvtColor函数


    函数作用:
      The function converts an input image from one color space to another. In case of a transformation to-from RGB color space, the order of the channels should be specified explicitly (RGB or BGR)(指定输入图像颜色空间类型).
      Note that the default color format in OpenCV is often referred to as RGB but it is actually BGR (the bytes are reversed).
      So the first byte in a standard (24-bit) color image will be an 8-bit Blue component, the second byte will be Green, and the third byte will be Red. The fourth, fifth, and sixth bytes would then be the second pixel (Blue, then Green, then Red), and so on.
    OpenCv默认的颜色制式是BGR而非RGB。
    . The conventional ranges for R, G, and B channel values are:
    . - 0 to 255 for CV_8U images
    . - 0 to 65535 for CV_16U images
    . - 0 to 1 for CV_32F images

    对于线性变换来说,这些取值范围是无关紧要的。
    但是对于非线性转换,输入的RGB图像必须归一化到其对应的取值范围来或得最终正确的转换结果,
      例如从RGB->L*u*v转换。如果从一个8-bit类型图像不经过任何缩放(scaling)直接转换为32-bit浮点型图像,函数将会以0-255的取值范围来取代0-1的取值范围,所以在使用cvtColor函数之前需要对图像进行缩放

    img *= 1./255;
    cvtColor(img, img, CV_BGR2Luv);

    如果对8-bit图像使用cvtColor()函数进行转换将会由一些信息丢失。函数可以做下面类型的转换,需要说明的是在opencv2.x时颜色空间转换code用的宏定义是CV_前缀开头,而在opencv3.x版本其颜色空间转换code宏定义更改为COLOR_开头,而经验证,2.4.13版本中opencv同事支持这两种形式的写法。故下面表格会将两种code类型同时列出,以供参考:
    这里写图片描述

    这里列出的类型并不齐全,但是对于一般的图像处理已经够用。需要特别说明的是RGB–>GRAY的转换是我们常用的转换格式,其转换公式如下:

    这里写图片描述

    上图中出现的RGBA格式图片,RGBA是代表Red(红色)、Green(绿色)、Blue(蓝色)和Alpha的色彩空间。虽然它有时候被描述为一个颜色空间,但是它其实是RGB模型附加了额外的信息,可以属于任何一种RGB颜色空间。Alpha参数一般用作不透明度参数,如果一个像素的alpha通道数值为0%,那它就是完全透明的也就是肉眼不可见,而数值为100%则意味着一个完全不透明的像素,传统的数字图像就是alpha值为100%。
    需要注意的是cvtColor()函数不能直接将RGB图像转换为二值图像(Binary Image),需要借助threshold()函数,其具体用法请查阅threshold().

    代码如下:

    # 使用opencv读取图像,直接返回numpy.ndarray 对象,通道顺序为BGR ,注意是BGR,通道值默认范围0-255。
    img = cv.imread(r".\1.png")     # 相对路径
    cv.imshow("IMAGE_BGR",img)       # 在Image窗口中显示图片img
    
    img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)   # 将彩色图像转换为灰度图像
    img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)     # 将彩色图像转换为HSV图像
    cv.imshow("IMAGE_GRAY",img_gray)
    cv.imshow("IMAGE_HSV", img_hsv)


    函数原型:

    def cvtColor(src, code, dst=None, dstCn=None): # real signature unknown; restored from doc

    参数意义:

    . @param src input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC… ), or single-precision
    . floating-point.
    . @param dst output image of the same size and depth as src.
    . @param code color space conversion code (see #ColorConversionCodes).
    . @param dstCn number of channels in the destination image; if the parameter is 0, the number of the
    . channels is derived automatically from src and code.


    4、获得图片属性:

    sp = img.shape    # 图片的大小  像素 高  宽    通道数  
    # sp[0] 高
    # sp[1] 宽
    # sp[2] 通道数
    img.size     # 像素点个数
    

    5、缩放图片:

    size = img_gray.shape
    temping = cv.resize(img_gray,((int)(size[1]*0.1),(int)(size[0]*0.5)),interpolation=cv.INTER_LINEAR)
    # 等同上述一行代码
    temping = cv.resize(img_gray,None, fx=0.5, fy=0.5, interpolation=cv.INTER_LINEAR)
    cv.imshow('img_gray2',temping)

    6、平移图片

    rows,cols = img_gray.shape
    
    M = np.float32([[1,0,100],[0,1,50]])
    dst = cv.warpAffine(img,M,(cols,rows))
    
    cv.imshow('img_gray3',dst)
    cv.waitKey(0)
    cv.destroyAllWindows()

    7、旋转图片

    rows,cols = img_gray.shape
    
    M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
    dst = cv.warpAffine(img,M,(cols,rows))
    
    cv.imshow('img_gray4',dst)

    8、仿射变换

    rows,cols,ch = img.shape
    
    pts1 = np.float32([[50,50],[200,50],[50,200]])
    pts2 = np.float32([[10,100],[200,50],[100,250]])
    
    M = cv.getAffineTransform(pts1,pts2)
    
    dst = cv.warpAffine(img,M,(cols,rows))
    
    cv.imshow('image',dst)

    9、通道的拆分/合并处理

    b,g,r = cv.split(img)
    img = cv.merge((b,g,r))

    10、图片添加边距

    未完待续!!!

    展开全文
  • 提到图像处理第一个想到的库就是PIL,全称Python Imaging Library Python图像处理类库,它提供了大量的图像操作,比如图像缩放,裁剪,贴图,模糊等等,很多时候它需要配合numpy库一起使用 1.open() 你可以使用...

    质量、速度、廉价,选择其中两个

    提到图像处理第一个想到的库就是PIL,全称Python Imaging Library Python,图像处理类库,它提供了大量的图像操作,比如图像缩放,裁剪,贴图,模糊等等,很多时候它需要配合numpy库一起使用

    1.open()

    你可以使用Image.open打开一个图像文件,它会返回PIL图像对象

    image = Image.open(image_address)

    2.covert()

    你可以 covert() 方法转换图像格式,covert() 有三种传参方式

    im.convert(mode) ⇒ image

    im.convert(“P”, **options) ⇒ image

    im.convert(mode, matrix) ⇒ image

    最常用的还是第一种,通过该方法你可以将PIL图像转换成九种不同的格式,分别1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。

    1.模式“1”

    模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。

    2.模式“L”

    模式”L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:

    L = R * 299/1000 + G * 587/1000+ B * 114/1000

    3.模式“p”

    模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。

    4.模式“RGBA”

    模式“RGBA”为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。

    5.模式“CMYK”

    模式“CMYK”为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。

    四种标准颜色是:C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:Key Plate(blacK) = 定位套版色(黑色)。

    6.模式“YCbCr”

    模式“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

    模式“RGB”转换为“YCbCr”的公式如下:

    Y= 0.257*R+0.504*G+0.098*B+16
    Cb = -0.148*R-0.291*G+0.439*B+128
    Cr = 0.439*R-0.368*G-0.071*B+128

    7.模式“I”

    模式“I”为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的:

    I = R * 299/1000 + G * 587/1000 + B * 114/1000

    8.模式“F”

    模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:

    F = R * 299/1000+ G * 587/1000 + B * 114/1000

    3.调整尺寸、创建缩略图、裁剪、贴图、旋转

    PIL库给我们提供了丰富基本图像操作,如果你想调整一张图片的尺寸,你可以使用resize()方法,该方法需要传入你指定新图像宽高的元组

    img = img.resize((128,128))

    如果你想创建一张图片的缩略图,你可以使用thumbnail()方法,该方法需要传入缩略图的宽高元组

    img=img.thumbnail((128,128))

    如果你想对一张图片的一部分进行裁剪,你可以使用crop()方法,该方法需要你传入一个元组,该元组指定裁剪区域的左上角坐标和右下角坐标

    box = (100,100,400,400)
    img = img.crop(box)

    如果你想把一张图片覆盖在另一个图片的上面,你可以使用paste()方法,该方法需要传入要贴的图片和位置(左上角坐标和右下角坐标)

    img2=img2.paste(img1,(100,100,200,200))

    如果你想要旋转一张图片,你可以使用transpose()方法,该方法传入旋转角度

    img = img.transpose(Image.ROTATE_180)

    不过这些角度很受限制,只可以传下面之中的一个

    • PIL.Image.FLIP_LEFT_RIGHT 
    • PIL.Image.FLIP_TOP_BOTTOM
    • PIL.Image.ROTATE_90
    • PIL.Image.ROTATE_180
    • PIL.Image.ROTATE_270
    • PIL.Image.TRANSPOSE
    • PIL.Image.TRANSVERSE

    你也可以使用rotate()方法,该方法更为简单方便,只需要传入一个旋转角度即可

    image = image.rotate(45)

    4.Numpy

    对图像进行变换其实就是对矩阵进行变换,我们需要把一张图片转换成矩阵再进行操作,使用array()方法

    image = Image.open(image_address)
    imageArray = array(image)

    1.反向处理与二值化

    图像一般都是三通道的,也就是红绿蓝,他们的值从0-255,所谓反相处理呢,就是把颜色反过来

    imageArray = 255 - imageArray

     图像的二值化也很简单,0-255以128为分界,小于128置为0否则置为1

    imageArray = 1 * (imageArray < 128)

    2.像素值限制范围

    如果你想把一个图像的像素值都限制到一个范围内,比如说你想把像素值限制到100-200这个区间上,你可以这么干

    imageArray = (100.0 / 255) * imageArray + 100

    3.像素值求平方

    imageArray = 255.0 * (imageArray / 255.0) ** 2

    4.直方图均衡化

    图像灰度变换中一个非常有用的例子就是直方图均衡化。直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。在对图像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。

    在这种情况下,直方图均衡化的变换函数是图像中像素值的累积分布函数(cumulative distribution function,简写为 cdf,将像素值的范围映射到目标范围的归一化操作)

    def histeq(im,nbr_bins=256):
        """ 对一幅灰度图像进行直方图均衡化"""
        # 计算图像的直方图
        imhist,bins = histogram(im.flatten(),nbr_bins,normed=True)
        cdf = imhist.cumsum()
        # cumulative distribution function
        cdf = 255 * cdf / cdf[-1]
        #  归一化
        #  使用累积分布函数的线性插值,计算新的像素值
        im2 = interp(im.flatten(),bins[:-1],cdf)
        return im2.reshape(im.shape), cdf

    该函数有两个输入参数,一个是灰度图像,一个是直方图中使用小区间的数目。函数返回直方图均衡化后的图像,以及用来做像素值映射的累积分布函数。注意,函数中使用到累积分布函数的最后一个元素(下标为 -1),目的是将其归一化到 0...1 范围。

    直方图均衡化后图像可以使对比度增强,使原先图像灰色区域的细节变得更清晰

    5.多种滤波

    gaussian滤波是多维的滤波器,是一种平滑滤波,可以消除高斯噪声

    通过调节sigma的值来调整滤波效果

    imageArray = filters.gaussian_filter(imageArray, 5)

    sobel算子可用来检测边缘

    edges = filters.sobel(img)

    roberts算子、scharr算子、prewitt算子和sobel算子一样,用于检测边缘

    edges = filters.roberts(img)
    edges = filters.scharr(img)
    edges = filters.prewitt(img)

    canny算子也是用于提取边缘特征,但它不是放在filters模块,而是放在feature模块

    edges1 = feature.canny(img)   #sigma=1
    edges2 = feature.canny(img,sigma=3)   #sigma=3

    gabor滤波可用来进行边缘检测和纹理特征提取。

    通过修改frequency值来调整滤波效果,返回一对边缘结果,一个是用真实滤波核的滤波结果,一个是想象的滤波核的滤波结果。

    filt_real, filt_imag = filters.gabor_filter(img,frequency=0.6)   

    6.PCA

    PCA(Principal Component Analysis,主成分分析)是一个非常有用的降维技巧。它可以在使用尽可能少维数的前提下,尽量多地保持训练数据的信息,在此意义上是一个最佳技巧。即使是一幅 100×100 像素的小灰度图像,也有 10 000 维,可以看成 10 000 维空间中的一个点。一兆像素的图像具有百万维。由于图像具有很高的维数,在许多计算机视觉应用中,我们经常使用降维操作。PCA 产生的投影矩阵可以被视为将原始坐标变换到现有的坐标系,坐标系中的各个坐标按照重要性递减排列。

    为了对图像数据进行 PCA 变换,图像需要转换成一维向量表示。我们可以使用 NumPy 类库中的 flatten() 方法进行变换。

    将变平的图像堆积起来,我们可以得到一个矩阵,矩阵的一行表示一幅图像。在计算主方向之前,所有的行图像按照平均图像进行了中心化。我们通常使用 SVD(Singular Value Decomposition,奇异值分解)方法来计算主成分;但当矩阵的维数很大时,SVD 的计算非常慢,所以此时通常不使用 SVD 分解。下面就是 PCA 操作的代码:

    def pca(X):
        """ 主成分分析:    输入:矩阵X ,其中该矩阵中存储训练数据,每一行为一条训练数据
           返回:投影矩阵(按照维度的重要性排序)、方差和均值"""
        # 获取维数
        num_data,dim = X.shape
        # 数据中心化
        mean_X = X.mean(axis=0)
        X = X - mean_X
        if dim<num_data:
            # PCA- 使用紧致技巧
            M = dot(X,X.T)
            # 协方差矩阵
            e,EV = linalg.eigh(M)
            # 特征值和特征向量
            tmp = dot(X.T,EV).T
            # 这就是紧致技巧
            V = tmp[::-1]
            # 由于最后的特征向量是我们所需要的,所以需要将其逆转
            S = sqrt(e)[::-1]
            # 由于特征值是按照递增顺序排列的,所以需要将其逆转
            for i in range(V.shape[1]):
                V[:,i] /= S
        else:
            # PCA- 使用SVD 方法
            U,S,V = linalg.svd(X)
            V = V[:num_data]
            # 仅仅返回前nun_data 维的数据才合理
            #  返回投影矩阵、方差和均值
        return V,S,mean_X

    7.图像添加噪声和降噪

    添加噪声比降噪简单得多,只需要把图像矩阵上面随机加一些值就好了

    imageArray = imageArray + 30 * random.standard_normal(imageArray.shape)

    图像降噪是在去除图像噪声的同时,尽可能地保留图像细节和结构的处理技术,我们这里使用 ROF去燥模型

    一幅(灰度)图像 I 的全变差(Total Variation,TV)定义为梯度范数之和。在连续表示的情况下,全变差表示为:

    J(\boldsymbol{I})=\int\left|\nabla\boldsymbol{I}\right|\text{dx} 

    在离散表示的情况下,全变差表示为:

    J(\boldsymbol{I})=\sum_{\text{x}}\left|\nabla\boldsymbol{I}\right|

    其中,上面的式子是在所有图像坐标 x=[x, y] 上取和。

    在 Chambolle 提出的 ROF 模型里,目标函数为寻找降噪后的图像 U,使下式最小:

    \min_U\left|\left|\boldsymbol{I}-\boldsymbol{U}\right|\right|^2+2\lambda J(\boldsymbol{U}),

    其中范数 ||I-U|| 是去噪后图像 U 和原始图像 I 差异的度量。也就是说,本质上该模型使去噪后的图像像素值“平坦”变化,但是在图像区域的边缘上,允许去噪后的图像像素值“跳跃”变化。

    def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
        """ 使用A. Chambolle(2005)在公式(11)中的计算步骤实现Rudin-Osher-Fatemi(ROF)去噪模型
           输入:含有噪声的输入图像(灰度图像)、U 的初始值、TV 正则项权值、步长、停业条件
            输出:去噪和去除纹理后的图像、纹理残留"""
        m,n = im.shape # 噪声图像的大小
    
        #  初始化
        U = U_init
        Px = im # 对偶域的x 分量
        Py = im # 对偶域的y 分量
        error = 1
        while (error > tolerance):
            Uold = U
    
            # 原始变量的梯度
            GradUx = roll(U,-1,axis=1)-U # 变量U 梯度的x 分量
            GradUy = roll(U,-1,axis=0)-U # 变量U 梯度的y 分量
    
            #  更新对偶变量
            PxNew = Px + (tau/tv_weight)*GradUx
            PyNew = Py + (tau/tv_weight)*GradUy
            NormNew = maximum(1,sqrt(PxNew**2+PyNew**2))
            Px = PxNew/NormNew # 更新x 分量(对偶)
            Py = PyNew/NormNew # 更新y 分量(对偶)
            #  更新原始变量
            RxPx = roll(Px,1,axis=1) # 对x 分量进行向右x 轴平移
            RyPy = roll(Py,1,axis=0) # 对y 分量进行向右y 轴平移
    
            DivP = (Px-RxPx)+(Py-RyPy) # 对偶域的散度
            U = im + tv_weight*DivP # 更新原始变量
    
            #  更新误差
            error = linalg.norm(U-Uold)/sqrt(n*m);
        return U,im-U  # 去噪后的图像和纹理残余
    

    5.Matplotlib

    我们队图像进行处理之后往往需要知道处理后变化如何,该库便可以方便地绘制出条形图,饼状图等等呢个图像,还可在上面添加标记等等

    尽管 Matplotlib 可以绘制出较好的条形图、饼状图、散点图等,但是对于大多数计算机视觉应用来说,仅仅需要用到几个绘图命令。最重要的是,我们想用点和线来表示一些事物,比如兴趣点、对应点以及检测出的物体。下面是用几个点和一条线绘制图像的例子:

    from PIL import Image
    from pylab import *
    
    # 读取图像到数组中
    im = array(Image.open('empire.jpg'))
    
    # 绘制图像
    imshow(im)
    
    # 一些点
    x = [100,100,400,400]
    y = [200,500,200,500]
    
    # 使用红色星状标记绘制点
    plot(x,y,'r*')
    
    # 绘制连接前两个点的线
    plot(x[:2],y[:2])
    
    # 添加标题,显示绘制的图像
    title('Plotting: "empire.jpg"')
    show()

    上面的代码首先绘制出原始图像,然后在 x 和 y 列表中给定点的 x 坐标和 y 坐标上绘制出红色星状标记点,最后在两个列表表示的前两个点之间绘制一条线段(默认为蓝色)。该例子的绘制结果如图 1-2 所示。show() 命令首先打开图形用户界面(GUI),然后新建一个图像窗口。该图形用户界面会循环阻断脚本,然后暂停,直到最后一个图像窗口关闭。在每个脚本里,你只能调用一次 show() 命令,而且通常是在脚本的结尾调用。注意,在 PyLab 库中,我们约定图像的左上角为坐标原点。

    图像的坐标轴是一个很有用的调试工具;但是,如果你想绘制出较美观的图像,加上下列命令可以使坐标轴不显示:

    axis('off')

     下面是我写的一个图像处理的脚本

    import PIL.Image as Image
    import os
    from pylab import *
    from numpy import *
    from scipy.ndimage import filters
    from scipy.ndimage import measurements,morphology
    
    
    def get_imlist(path):
        # 一级文件夹下有用
        # return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')]
        g = os.walk(path)
        image_list=[]
        for path, d, filelist in g:
            for filename in filelist:
                if filename.endswith('jpg'):
                    image_list.append(os.path.join(path, filename))
        return image_list
    
    def histeq(im,nbr_bins=256):
        """ 对一幅灰度图像进行直方图均衡化"""
        # 计算图像的直方图
        imhist,bins = histogram(im.flatten(),nbr_bins,normed=True)
        cdf = imhist.cumsum()
        # cumulative distribution function
        cdf = 255 * cdf / cdf[-1]
        #  归一化
        #  使用累积分布函数的线性插值,计算新的像素值
        im2 = interp(im.flatten(),bins[:-1],cdf)
        return im2.reshape(im.shape), cdf
    
    def pca(X):
        """ 主成分分析:    输入:矩阵X ,其中该矩阵中存储训练数据,每一行为一条训练数据
           返回:投影矩阵(按照维度的重要性排序)、方差和均值"""
        # 获取维数
        num_data,dim = X.shape
        # 数据中心化
        mean_X = X.mean(axis=0)
        X = X - mean_X
        if dim<num_data:
            # PCA- 使用紧致技巧
            M = dot(X,X.T)
            # 协方差矩阵
            e,EV = linalg.eigh(M)
            # 特征值和特征向量
            tmp = dot(X.T,EV).T
            # 这就是紧致技巧
            V = tmp[::-1]
            # 由于最后的特征向量是我们所需要的,所以需要将其逆转
            S = sqrt(e)[::-1]
            # 由于特征值是按照递增顺序排列的,所以需要将其逆转
            for i in range(V.shape[1]):
                V[:,i] /= S
        else:
            # PCA- 使用SVD 方法
            U,S,V = linalg.svd(X)
            V = V[:num_data]
            # 仅仅返回前nun_data 维的数据才合理
            #  返回投影矩阵、方差和均值
        return V,S,mean_X
    
    def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
        """ 使用A. Chambolle(2005)在公式(11)中的计算步骤实现Rudin-Osher-Fatemi(ROF)去噪模型
           输入:含有噪声的输入图像(灰度图像)、U 的初始值、TV 正则项权值、步长、停业条件
            输出:去噪和去除纹理后的图像、纹理残留"""
        m,n = im.shape # 噪声图像的大小
    
        #  初始化
        U = U_init
        Px = im # 对偶域的x 分量
        Py = im # 对偶域的y 分量
        error = 1
        while (error > tolerance):
            Uold = U
    
            # 原始变量的梯度
            GradUx = roll(U,-1,axis=1)-U # 变量U 梯度的x 分量
            GradUy = roll(U,-1,axis=0)-U # 变量U 梯度的y 分量
    
            #  更新对偶变量
            PxNew = Px + (tau/tv_weight)*GradUx
            PyNew = Py + (tau/tv_weight)*GradUy
            NormNew = maximum(1,sqrt(PxNew**2+PyNew**2))
            Px = PxNew/NormNew # 更新x 分量(对偶)
            Py = PyNew/NormNew # 更新y 分量(对偶)
            #  更新原始变量
            RxPx = roll(Px,1,axis=1) # 对x 分量进行向右x 轴平移
            RyPy = roll(Py,1,axis=0) # 对y 分量进行向右y 轴平移
    
            DivP = (Px-RxPx)+(Py-RyPy) # 对偶域的散度
            U = im + tv_weight*DivP # 更新原始变量
    
            #  更新误差
            error = linalg.norm(U-Uold)/sqrt(n*m);
        return U,im-U  # 去噪后的图像和纹理残余
    
    
    
    
    image_list = get_imlist("G:\\最后两种\\")
    
    index=6858
    for image_address in image_list:
        index = index + 1
        dealIndex=0
        for x in range(1,17):
            image = Image.open(image_address)
            imageArray = array(image)
            dealIndex+=1
            if x==1:
                # 反相处理
                imageArray = 255 - imageArray
                print("第"+str(index)+"张 反向处理")
            elif x==2:
                # 将图像像素值变换到100...200 区间
                imageArray = (100.0 / 255) * imageArray + 100
                print("第" + str(index) + "张 像素值变换")
            elif x==3:
                # 对图像像素值求平方后得到的图像
                imageArray = 255.0 * (imageArray / 255.0) ** 2
                print("第" + str(index) + "张 像素值求平方")
            elif x==4:
                # 图像旋转
                image = image.rotate(random.randint(0,360))
                imageArray=array(image)
                print("第" + str(index) + "张 图像旋转")
            elif x==5:
                # 直方图均衡化
                imageArray,cdf=histeq(imageArray)
                print("第" + str(index) + "张 直方图均衡化")
            elif x==6:
                # gaussian滤波
                imageArray = filters.gaussian_filter(imageArray, 5)
                print("第" + str(index) + "张 gaussian滤波")
            elif x==7:
                # Sobel 导数滤波器
                imx = zeros(imageArray.shape)
                filters.sobel(imageArray, 1, imx)
                imy = zeros(imageArray.shape)
                filters.sobel(imageArray, 0, imy)
                magnitude = sqrt(imx ** 2 + imy ** 2)
                imageArray=magnitude
                print("第" + str(index) + "张  Sobel导数滤波器")
            elif x==8:
                # 噪声
                imageArray = imageArray + 30 * random.standard_normal(imageArray.shape)
                print("第" + str(index) + "张  噪声")
            elif x==9:
                # 反相处理+像素值变换
                imageArray = 255 - imageArray
                imageArray = (100.0 / 255) * imageArray + 100
                print("第" + str(index) + "张  反相处理+像素值变换")
            elif x==10:
                # 反相处理+像素值求平方
                imageArray = 255 - imageArray
                imageArray = 255.0 * (imageArray / 255.0) ** 2
                print("第" + str(index) + "张  反相处理+像素值求平方")
            elif x==11:
                # 像素值求平方+反相处理
                imageArray = 255.0 * (imageArray / 255.0) ** 2
                imageArray = 255 - imageArray
                print("第" + str(index) + "张  像素值求平方+反相处理")
            elif x==12:
                # 像素值变换+像素值求平方
                imageArray = (100.0 / 255) * imageArray + 100
                imageArray = 255.0 * (imageArray / 255.0) ** 2
                print("第" + str(index) + "张  像素值变换+像素值求平方")
            elif x==13:
                # 图像旋转+反相
                image = image.rotate(random.randint(0, 360))
                imageArray = array(image)
                imageArray = 255 - imageArray
                print("第" + str(index) + "张  图像旋转+反相")
            elif x==14:
                # 图像旋转+噪声
                image = image.rotate(random.randint(0, 360))
                imageArray = array(image)
                imageArray = imageArray + 30 * random.standard_normal(imageArray.shape)
                print("第" + str(index) + "张  图像旋转+噪声")
            elif x==15:
                # 噪声+直方图均衡化
                imageArray = imageArray + 30 * random.standard_normal(imageArray.shape)
                imageArray, cdf = histeq(imageArray)
                print("第" + str(index) + "张  噪声+直方图均衡化")
    
    
            imageArray = uint8(imageArray)
            image=Image.fromarray(imageArray)
            image = image.convert('RGB')
            if image_address.rfind("不规则")!= -1:
                image.save("G:\\兔屎图片_二次处理\\不规则\\" + str(index)+"_"+str(dealIndex) + ".jpg")
            elif image_address.rfind("大小不一") != -1:
                image.save("G:\\兔屎图片_二次处理\\大小不一\\" + str(index) +"_"+str(dealIndex)+ ".jpg")
            elif image_address.rfind("拉稀") != -1:
                image.save("G:\\兔屎图片_二次处理\\拉稀\\" + str(index) +"_"+str(dealIndex)+ ".jpg")
            elif image_address.rfind("正常") != -1:
                image.save("G:\\兔屎图片_二次处理\\正常\\" + str(index) +"_"+str(dealIndex)+ ".jpg")
    
            print("完事一个")

    参考文章:https://www.cnblogs.com/xk-bench/p/7825290.html

    展开全文
  • 本文主要讲解图像傅里叶变换的相关内容,在数字图像处理中,有两个经典的变换被广泛应用——傅里叶变换和霍夫变换。其中,傅里叶变换主要是将时间域上的信号转变为频率域上的信号,用来进行图像除噪、图像增强等处理...

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~

    该系列在github所有源代码:https://github.com/eastmountyxz/ImageProcessing-Python
    PS:请求帮忙点个Star,哈哈,第一次使用Github,以后会分享更多代码,一起加油。

    同时推荐作者的C++图像系列知识:
    [数字图像处理] 一.MFC详解显示BMP格式图片
    [数字图像处理] 二.MFC单文档分割窗口显示图片
    [数字图像处理] 三.MFC实现图像灰度、采样和量化功能详解
    [数字图像处理] 四.MFC对话框绘制灰度直方图
    [数字图像处理] 五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理详解
    [数字图像处理] 六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解
    [数字图像处理] 七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

    前文参考:
    [Python图像处理] 一.图像处理基础知识及OpenCV入门函数
    [Python图像处理] 二.OpenCV+Numpy库读取与修改像素
    [Python图像处理] 三.获取图像属性、兴趣ROI区域及通道处理
    [Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
    [Python图像处理] 五.图像融合、加法运算及图像类型转换
    [Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移
    [Python图像处理] 七.图像阈值化处理及算法对比
    [Python图像处理] 八.图像腐蚀与图像膨胀
    [Python图像处理] 九.形态学之图像开运算、闭运算、梯度运算
    [Python图像处理] 十.形态学之图像顶帽运算和黑帽运算
    [Python图像处理] 十一.灰度直方图概念及OpenCV绘制直方图
    [Python图像处理] 十二.图像几何变换之图像仿射变换、图像透视变换和图像校正
    [Python图像处理] 十三.基于灰度三维图的图像顶帽运算和黑帽运算
    [Python图像处理] 十四.基于OpenCV和像素处理的图像灰度化处理
    [Python图像处理] 十五.图像的灰度线性变换
    [Python图像处理] 十六.图像的灰度非线性变换之对数变换、伽马变换
    [Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
    [Python图像处理] 十八.图像锐化与边缘检测之Scharr算子、Canny算子和LOG算子
    [Python图像处理] 十九.图像分割之基于K-Means聚类的区域分割
    [Python图像处理] 二十.图像量化处理和采样处理及局部马赛克特效
    [Python图像处理] 二十一.图像金字塔之图像向下取样和向上取样

    前面一篇文章我讲解了Python图像量化、采样处理及图像金字塔。本文主要讲解图像傅里叶变换的相关内容,在数字图像处理中,有两个经典的变换被广泛应用——傅里叶变换和霍夫变换。其中,傅里叶变换主要是将时间域上的信号转变为频率域上的信号,用来进行图像除噪、图像增强等处理。基础性文章,希望对你有所帮助。同时,该部分知识均为杨秀璋查阅资料撰写,转载请署名CSDN+杨秀璋及原地址出处,谢谢!!

    1.图像傅里叶变换
    2.Numpy实现傅里叶变换
    3.Numpy实现傅里叶逆变换
    4.OpenCV实现傅里叶变换
    5.OpenCV实现傅里叶逆变换


    PS:文章参考自己以前系列图像处理文章及OpenCV库函数,同时参考如下文献:
    《数字图像处理》(第3版),冈萨雷斯著,阮秋琦译,电子工业出版社,2013年.
    《数字图像处理学》(第3版),阮秋琦,电子工业出版社,2008年,北京.
    《OpenCV3编程入门》,毛星云,冷雪飞,电子工业出版社,2015,北京.
    百度百科-傅里叶变换
    网易云课堂-高登教育 Python+OpenCV图像处理
    安安zoe-图像的傅里叶变换
    daduzimama-图像的傅里叶变换的迷思----频谱居中
    tenderwx-数字图像处理-傅里叶变换在图像处理中的应用
    小小猫钓小小鱼-深入浅出的讲解傅里叶变换(真正的通俗易懂)


    一.图像傅里叶变换原理

    傅里叶变换(Fourier Transform,简称FT)常用于数字信号处理,它的目的是将时间域上的信号转变为频率域上的信号。随着域的不同,对同一个事物的了解角度也随之改变,因此在时域中某些不好处理的地方,在频域就可以较为简单的处理。同时,可以从频域里发现一些原先不易察觉的特征。傅里叶定理指出“任何连续周期信号都可以表示成(或者无限逼近)一系列正弦信号的叠加。”

    下面引用李老师 “Python+OpenCV图像处理” 中的一个案例,非常推荐同学们去购买学习。如下图所示,他将某饮料的制作过程的时域角度转换为频域角度。

    绘制对应的时间图和频率图如下所示:

    傅里叶公式如下,其中w表示频率,t表示时间,为复变函数。它将时间域的函数表示为频率域的函数f(t)的积分。

    傅里叶变换认为一个周期函数(信号)包含多个频率分量,任意函数(信号)f(t)可通过多个周期函数(或基函数)相加合成。从物理角度理解,傅里叶变换是以一组特殊的函数(三角函数)为正交基,对原函数进行线性变换,物理意义便是原函数在各组基函数的投影。如下图所示,它是由三条正弦曲线组合成。

    傅里叶变换可以应用于图像处理中,经过对图像进行变换得到其频谱图。从谱频图里频率高低来表征图像中灰度变化剧烈程度。图像中的边缘信号和噪声信号往往是高频信号,而图像变化频繁的图像轮廓及背景等信号往往是低频信号。这时可以有针对性的对图像进行相关操作,例如图像除噪、图像增强和锐化等。

    二维图像的傅里叶变换可以用以下数学公式(15-3)表达,其中f是空间域(Spatial Domain))值,F是频域(Frequency Domain)值

    对上面的傅里叶变换有了大致的了解之后,下面通过Numpy和OpenCV分别讲解图像傅里叶变换的算法及操作代码。


    二.Numpy实现傅里叶变换

    Numpy中的 FFT包提供了函数 np.fft.fft2()可以对信号进行快速傅里叶变换,其函数原型如下所示,该输出结果是一个复数数组(Complex Ndarry)。

    fft2(a, s=None, axes=(-2, -1), norm=None)

    • a表示输入图像,阵列状的复杂数组
    • s表示整数序列,可以决定输出数组的大小。输出可选形状(每个转换轴的长度),其中s[0]表示轴0,s[1]表示轴1。对应fit(x,n)函数中的n,沿着每个轴,如果给定的形状小于输入形状,则将剪切输入。如果大于则输入将用零填充。如果未给定’s’,则使用沿’axles’指定的轴的输入形状
    • axes表示整数序列,用于计算FFT的可选轴。如果未给出,则使用最后两个轴。“axes”中的重复索引表示对该轴执行多次转换,一个元素序列意味着执行一维FFT
    • norm包括None和ortho两个选项,规范化模式(请参见numpy.fft)。默认值为无

    Numpy中的fft模块有很多函数,相关函数如下:

    #计算一维傅里叶变换
    numpy.fft.fft(a, n=None, axis=-1, norm=None)
    #计算二维的傅里叶变换
    numpy.fft.fft2(a, n=None, axis=-1, norm=None)
    #计算n维的傅里叶变换
    numpy.fft.fftn()
    #计算n维实数的傅里叶变换
    numpy.fft.rfftn()
    #返回傅里叶变换的采样频率
    numpy.fft.fftfreq()
    #将FFT输出中的直流分量移动到频谱中央
    numpy.fft.shift()

    下面的代码是通过Numpy库实现傅里叶变换,调用np.fft.fft2()快速傅里叶变换得到频率分布,接着调用np.fft.fftshift()函数将中心位置转移至中间,最终通过Matplotlib显示效果图。

    # -*- coding: utf-8 -*-
    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    
    #读取图像
    img = cv.imread('test.png', 0)
    
    #快速傅里叶变换算法得到频率分布
    f = np.fft.fft2(img)
    
    #默认结果中心点位置是在左上角,
    #调用fftshift()函数转移到中间位置
    fshift = np.fft.fftshift(f)       
    
    #fft结果是复数, 其绝对值结果是振幅
    fimg = np.log(np.abs(fshift))
    
    #展示结果
    plt.subplot(121), plt.imshow(img, 'gray'), plt.title('Original Fourier')
    plt.axis('off')
    plt.subplot(122), plt.imshow(fimg, 'gray'), plt.title('Fourier Fourier')
    plt.axis('off')
    plt.show()
    

    输出结果如图15-2所示,左边为原始图像,右边为频率分布图谱,其中越靠近中心位置频率越低,越亮(灰度值越高)的位置代表该频率的信号振幅越大。


    三.Numpy实现傅里叶逆变换

    下面介绍Numpy实现傅里叶逆变换,它是傅里叶变换的逆操作,将频谱图像转换为原始图像的过程。通过傅里叶变换将转换为频谱图,并对高频(边界)和低频(细节)部分进行处理,接着需要通过傅里叶逆变换恢复为原始效果图。频域上对图像的处理会反映在逆变换图像上,从而更好地进行图像处理。

    图像傅里叶变化主要使用的函数如下所示:

    #实现图像逆傅里叶变换,返回一个复数数组
    numpy.fft.ifft2(a, n=None, axis=-1, norm=None)
    #fftshit()函数的逆函数,它将频谱图像的中心低频部分移动至左上角
    numpy.fft.fftshift()
    #将复数转换为0至255范围
    iimg = numpy.abs(逆傅里叶变换结果)

    下面的代码分别实现了傅里叶变换和傅里叶逆变换。

    # -*- coding: utf-8 -*-
    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    
    #读取图像
    img = cv.imread('Lena.png', 0)
    
    #傅里叶变换
    f = np.fft.fft2(img)
    fshift = np.fft.fftshift(f)
    res = np.log(np.abs(fshift))
    
    #傅里叶逆变换
    ishift = np.fft.ifftshift(fshift)
    iimg = np.fft.ifft2(ishift)
    iimg = np.abs(iimg)
    
    #展示结果
    plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Image')
    plt.axis('off')
    plt.subplot(132), plt.imshow(res, 'gray'), plt.title('Fourier Image')
    plt.axis('off')
    plt.subplot(133), plt.imshow(iimg, 'gray'), plt.title('Inverse Fourier Image')
    plt.axis('off')
    plt.show()
    

    输出结果如图15-4所示,从左至右分别为原始图像、频谱图像、逆傅里叶变换转换图像。


    四.OpenCV实现傅里叶变换

    OpenCV 中相应的函数是cv2.dft()和用Numpy输出的结果一样,但是是双通道的。第一个通道是结果的实数部分,第二个通道是结果的虚数部分,并且输入图像要首先转换成 np.float32 格式。其函数原型如下所示:

    dst = cv2.dft(src, dst=None, flags=None, nonzeroRows=None)

    • src表示输入图像,需要通过np.float32转换格式
    • dst表示输出图像,包括输出大小和尺寸
    • flags表示转换标记,其中DFT _INVERSE执行反向一维或二维转换,而不是默认的正向转换;DFT _SCALE表示缩放结果,由阵列元素的数量除以它;DFT _ROWS执行正向或反向变换输入矩阵的每个单独的行,该标志可以同时转换多个矢量,并可用于减少开销以执行3D和更高维度的转换等;DFT _COMPLEX_OUTPUT执行1D或2D实数组的正向转换,这是最快的选择,默认功能;DFT _REAL_OUTPUT执行一维或二维复数阵列的逆变换,结果通常是相同大小的复数数组,但如果输入数组具有共轭复数对称性,则输出为真实数组
    • nonzeroRows表示当参数不为零时,函数假定只有nonzeroRows输入数组的第一行(未设置)或者只有输出数组的第一个(设置)包含非零,因此函数可以处理其余的行更有效率,并节省一些时间;这种技术对计算阵列互相关或使用DFT卷积非常有用

    注意,由于输出的频谱结果是一个复数,需要调用cv2.magnitude()函数将傅里叶变换的双通道结果转换为0到255的范围。其函数原型如下:

    cv2.magnitude(x, y)

    • x表示浮点型X坐标值,即实部
    • y表示浮点型Y坐标值,即虚部
      最终输出结果为幅值,即:

    完整代码如下所示:

    # -*- coding: utf-8 -*-
    import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    
    #读取图像
    img = cv2.imread('Lena.png', 0)
    
    #傅里叶变换
    dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
    
    #将频谱低频从左上角移动至中心位置
    dft_shift = np.fft.fftshift(dft)
    
    #频谱图像双通道复数转换为0-255区间
    result = 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(result, cmap = 'gray')
    plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
    plt.show()
    

    输出结果如图15-5所示,左边为原始“Lena”图,右边为转换后的频谱图像,并且保证低频位于中心位置。


    五.OpenCV实现傅里叶逆变换

    在OpenCV 中,通过函数cv2.idft()实现傅里叶逆变换,其返回结果取决于原始图像的类型和大小,原始图像可以为实数或复数。其函数原型如下所示:

    dst = cv2.idft(src[, dst[, flags[, nonzeroRows]]])

    • src表示输入图像,包括实数或复数
    • dst表示输出图像
    • flags表示转换标记
    • nonzeroRows表示要处理的dst行数,其余行的内容未定义(请参阅dft描述中的卷积示例)

    完整代码如下所示:

    # -*- coding: utf-8 -*-
    import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    
    #读取图像
    img = cv2.imread('Lena.png', 0)
    
    #傅里叶变换
    dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
    dftshift = np.fft.fftshift(dft)
    res1= 20*np.log(cv2.magnitude(dftshift[:,:,0], dftshift[:,:,1]))
    
    #傅里叶逆变换
    ishift = np.fft.ifftshift(dftshift)
    iimg = cv2.idft(ishift)
    res2 = cv2.magnitude(iimg[:,:,0], iimg[:,:,1])
    
    #显示图像
    plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Image')
    plt.axis('off')
    plt.subplot(132), plt.imshow(res1, 'gray'), plt.title('Fourier Image')
    plt.axis('off')
    plt.subplot(133), plt.imshow(res2, 'gray'), plt.title('Inverse Fourier Image')
    plt.axis('off')
    plt.show()
    

    输出结果如图15-6所示,第一幅图为原始“Lena”图,第二幅图为傅里叶变换后的频谱图像,第三幅图为傅里叶逆变换,频谱图像转换为原始图像的过程。


    六.总结

    傅里叶变换的目的并不是为了观察图像的频率分布(至少不是最终目的),更多情况下是为了对频率进行过滤,通过修改频率以达到图像增强、图像去噪、边缘检测、特征提取、压缩加密等目的。下一篇文章,作者将结合傅里叶变换和傅里叶逆变换讲解它的应用。

    时也,命也。
    英语低分数线一分,些许遗憾,但不气馁,更加努力。雄关漫道真如铁,而今迈过从头越,从头越。苍山如海,残阳如血。感谢一路陪伴的人和自己。

    无论成败,那段拼搏的日子都很美。结果只会让我更加努力,学好英语。下半年沉下心来好好做科研写文章,西藏之行,课程分享。同时,明天的博士考试加油,虽然裸泳,但也加油!还有春季招考开始准备。

    最后补充马刺小石匠精神,当一切都看起来无济于事的时候,我去看一个石匠敲石头.他一连敲了100次,石头仍然纹丝不动。但他敲第101次的时候,石头裂为两半。可我知道,让石头裂开的不是那最后一击,而是前面的一百次敲击的结果。人生路漫漫,不可能一路一帆风顺,暂时的不顺只是磨练自己的必经之路,夜最深的时候也是距黎明最近的时刻,经历过漫漫长夜的打磨,你自身会更加强大。

    最后希望这篇基础性文章对您有所帮助,如果有错误或不足之处,请海涵!

    (By:Eastmount 2019-04-23 周二下午6点写于花溪 https://blog.csdn.net/Eastmount )

    展开全文
  • 当今世界充满了各种数据,而图像是其中高的重要组成部分。然而,若想其有所应用,我们...图像处理中的常见任务包括显示图像,基本操作(如裁剪、翻转、旋转等),图像分割,分类和特征提取,图像恢复和图像识别等。...
  • Python图像处理

    2008-01-18 12:11:00
    Python图像处理 最近在做一件比较 evil 的事情——验证码识别,以此来学习一些新的技能。...在 Python ,比较常用的图像处理库是 PIL(Python Image Library),当前版本是 1.1.6 ,用起来非常方便。大家可以在
  • 请问StaticBitmap和bitmap有什么区别 StaticBitmap和bitmap有什么区别,在python中图像处理
  • Python数字图像处理

    2017-06-22 20:18:26
    转:宁静家园python数字图像处理(1):环境安装和配置python数字图像处理(2):图像的读取、显示与保存python数字图像处理(3):图像像素的访问与裁剪python数字图像处理(4):图像数据类型及颜色空间转换python...
  • Python中图像处理

    2018-03-03 22:27:15
    第 1 章 基本的图像操作和处理本章讲解操作和处理图像的基础知识,将通过大量...1.1 PIL:Python图像处理类库PIL(Python Imaging Library Python,图像处理类库)提供了通用的图像处理功能,以及大量有用的基本图...
  • 该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。...
  • 目录 ...初学OpenCV图像处理的小伙伴肯定对什么高斯函数、滤波处理、阈值二值化等特性非常头疼,这里给各位分享一个小项目,可通过摄像头实时动态查看各类图像处理的特点,也可对各位调参、测试...
  • 第 1 章 基本的图像操作和处理本章讲解操作和处理图像的基础知识,将通过大量...1.1 PIL:Python图像处理类库PIL(Python Imaging Library Python,图像处理类库)提供了通用的图像处理功能,以及大量有用的基本图...
  • 欢迎大家关注微信公众号:baihuaML,白话机器学习。 码字不易,如转载请私信我!! 在这里,我们一起分享AI的故事。...在使用python进行编程时,涉及到多个不同的图像处理库的选择,今天我们简单聊一聊...
  • python图像处理之skimage

    2017-12-11 21:04:14
    转自:python数字图像处理(2):图像的读取、显示与保存 skimage提供了io模块,顾名思义,这个模块是用来图片输入输出操作的。为了方便练习,也提供一个data模块,里面嵌套了一些示例图片,我们可以直接使用。 ...
  • 该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。...
  • python数字图像处理

    2018-09-12 20:03:41
    这里博客是自己做的个系统整理,主要说的是python在数字图像处理方面的应用,主要用到的库有PIL和skimage PIL库 1、用python简单处理图片:打开、显示、保存图像 2、用python简单处理图片:图像通道、几何变换...
  • python数字图像处理-图像噪声与去噪算法图像噪声椒盐噪声概述: 椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,所谓椒盐,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。...
  • python 图像处理

    2018-06-19 14:51:01
    转自:点击打开链接第 1 章 基本的图像操作和处理本章讲解操作和处理图像的基础知识,将通过大量...1.1 PIL:Python图像处理类库PIL(Python Imaging Library Python,图像处理类库)提供了通用的图像处理功能,以...
1 2 3 4 5 ... 20
收藏数 119,342
精华内容 47,736
关键字:

python中图像处理