一、采样:
采样是对图像像素点的选择或拒绝,是一种空间操作
1.上采样
为了增加图像的大小,需要进行上采样——即增加一些在原来小图像中没有的像素
1.1最近邻上采样
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
im = Image.open('D:/test.jpg')
plt.imshow(im)
im1 = im.resize((im.width*5, im.height*5), Image.NEAREST)
plt.imshow(im1)
效果不是很理想,图像效果差
1.2双线性插值
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
im = Image.open('D:/test.jpg')
plt.imshow(im)
im1 = im.resize((im.width*5, im.height*5), Image.BILINEAR)
plt.imshow(im1)
1.3双三次插值(效果最好)
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
im = Image.open('D:/test.jpg')
plt.imshow(im)
im1 = im.resize((im.width*5, im.height*5), Image.BICUBIC)
plt.imshow(im1)
2.下采样
缩小图像,要么直接删除一些像素,要么通过计算生成像素
2.1直接删除像素
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
im = Image.open('D:/test.jpg')
im1 = im.resize((im.width//15, im.height//15))
plt.figure(figsize=(15,10))
plt.axis('off')
plt.imshow(im1)
可以看到,图像中有一些在原始图像中不存在的黑色斑点或伪影——这种效果称为混叠。之所以发生混叠效果,通常是因为采样率比奈奎斯特速率小(像素太少了的缘故),因此避免混叠的一种方法是增加采样率,使其大于奈奎斯特速率
2.2 抗混叠下采样
(1)求平均采样:
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
im = Image.open('D:/test.jpg')
im1 = im.resize((im.width//15, im.height//15),Image.ANTIALIAS)
plt.figure(figsize=(15,10))
plt.axis('off')
plt.imshow(im1)
抗混叠通常是通过在向下采样之前通过平滑图像(将图像与低通滤波器卷积)
二、量化与信噪比
量化是指图像中每个像素所使用的比特数。数字图像通常被量化到256灰度级
信噪比是指图像数组的均值除以图像数组的标准差
1.PIL量化
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
from spicy.stats import signaltonoise
import numpy as np
im = Image.open('D:/test.jpg')
plt.figure(figsize=(20,30))
num_colors_list = [1 << n for n in range(8, 0, -1)]
snr_list=[]
i = 1
for num_color in num_colors_list:
im1 = im.convert('P', palette=Image.ADAPTIVE, colors=num_color)
plt.subplot(4,2,i)
plt.imshow(im1)
plt.axis('off')
snr_list.append(signaltonoise(im1, axis=None))
plt.title('Image with =' + str(num_colors) + 'SNR='+str(np.round(snr_list[i-1], 3)), size=20)
i+1
plt.subplots_adjust(wspace=0.2, hspace=0)
plt.show()
不断降低构成一个色素的比特位,图像效果越来越差
随着比特位数的下降,图像数组均值也下降,而方差几乎不变,所以信噪比下降。
通常这是图像质量的一种度量方法,信噪比越高,图像质量越好
三、离散傅里叶变换
3.1DFT(二维傅里叶变换)
图像处理只用关注二维离散傅里叶变换,基本思想是将图像看作是一个二维函数,这个函数可以表示成在两个维度上的正弦余弦加权和。
在频域中,低频对应于图像中信息的平均总体水平,高频对应于边缘,噪声和更详细的信息。
通常,图像本质上是平滑的,这就是为什么大多数图像可以用少量的DFT系数表示,而其余所有较高的系数几乎可以被忽略或为0。
DFT对图像压缩是非常有用的,尤其是对于稀疏傅里叶图像,只有少数的傅里叶系数需要重建图像,因此,只有那些频率可以被存储,其他的则可以丢弃,这会导致高压缩,例如,在JPEG图像压缩算法中使用了类似于变换的离散余弦变换(Discrete Cosine Transform,DCT)。同样,正如将在本章后面看到的,在频域中使用DFT进行滤波比在空间域中进行滤波快得多。
3.2使用快速傅里叶(FFT)变换计算DFT
FFT采用分而治之的办法计算DFT
对于一幅n × n的图像,它递归计算DFT的速度快得多(时间复杂度为O (Nlog 2N)),而离散傅里叶变换计算的速度慢得多(时间复杂度为O (N2))
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
import numpy as np
import numpy.fft as fp
from skimage import color
im = color.rgb2gray(io.imread('D:/test.jpg'))
plt.figure(figsize=(12, 10))
freq1 = fp.fft2(im) #获得图像的2维离散傅里叶变换
im_ = fp.ifft2(freq1).real #获得图像的2维离散傅里叶逆变换
plt.subplot(2,2,1)
plt.imshow(im, cmap='gray') #画灰度值照片
plt.title('Original Image', size=20)
plt.subplot(2,2,2)
plt.imshow(20*np.log10(0.01+np.abs(fp.fftshift(freq1))), cmap='gray')
plt.title('FFT Spectrum Magnitude', size=20)
plt.subplot(2,2,3)
plt.imshow(np.angle(fp.fftshift(freq1)), cmap='gray')
plt.title('FFT Phase', size=20)
plt.subplot(2,2,4)
plt.imshow(np.clip(im_, 0, 255), cmap='gray')
plt.title('Reconstructd Image', size=20)
plt.show()
DFT的F值[0,0]称为直流系数(DC coefficient)。DC系数对于其他系数值而言太大,因此看不到,所以我们需要通过显示变换的对数来增大变换值。此外,为了显示方便,变换系数被移位(使用fftshift()),使直流分量在中间(即低频在中间)
np.clip的例子
import numpy as np x=np.array([1,2,3,5,6,7,8,9]) np.clip(x,3,8) Out[88]: array([3, 3, 3, 5, 6, 7, 8, 8])
四、理解卷积(这个理解很重要)
卷积是对两幅图像进行操作的运算:一幅是输入图像;另一幅图像是作为输入图像的滤波器而产生输出图像的掩模(也称为核)。
图像的卷积操作就是CNN里面的卷积。
卷积的作用:
卷积对输入图像使用了一种通用的滤波效果,这样做是为了在图像上使用合适的核实现各种效果(如平滑、锐化和浮雕),以及在边缘检测等操作中实现各种效果。
4.1对灰度图像进行卷积(拉普拉斯核边缘检测,方框(box)核模糊图像)
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
import numpy as np
import numpy.fft as fp
from skimage import color
from scipy import signal
im = color.rgb2gray(io.imread('D:/mimi.jpg'))
blur_box_kernel = np.ones((3,3)) / 9
edge_laplace_kernel = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
im_blurred = signal.convolve2d(im, blur_box_kernel)
im_edges = np.clip(signal.convolve2d(im, edge_laplace_kernel), 0, 1)
fig, axes = plt.subplots(ncols=3, sharex=True, sharey=True, figsize=(18, 6))
axes[0].imshow(im, cmap=plt.cm.gray)
axes[0].set_title('Original Image', size=20)
axes[1].imshow(im_blurred, cmap=plt.cm.gray)
axes[1].set_title('Box Blur', size=20)
axes[2].imshow(im_edges, cmap=plt.cm.gray)
axes[2].set_title('Laplace Edge Detection', size=20)
for ax in axes:
ax.axis('off')
plt.show()
记住这两个核, Box Kernel & Laplace Kernel
4.2 彩色图像的卷积(emboss kernel(浮雕核)& schar边缘检测核)
from PIL import Image
import skimage.io as io
import matplotlib.pyplot as plt
import numpy as np
import numpy.fft as fp
from skimage import color
from scipy import signal
im = io.imread('D:/tiantan.jpg')/255 #控制在0-1内
emboss_kernel = np.array([[-2, -1, 0], [-1, 1, 1], [0, 1, 2]])
edge_scharr_kernel = np.array([[-3-3j, 0-10j, +3-3j], [-10+0j, 0+0j, +10+0j], [-3+3j, 0+10j, +3+3j]])
im_embossed = np.ones(im.shape)
im_edges = np.ones(im.shape)
for i in range(3):#对三个通道都要进行卷积
im_embossed[...,i] = np.clip(signal.convolve2d(im[...,i], emboss_kernel,\
mode='same', boundary='symm'),0,1)
for i in range(3):
im_edges[...,i] = np.clip(np.real(signal.convolve2d(im[...,i], edge_scharr_kernel,mode='same',\
boundary='symm')),0,1)
fig, axes = plt.subplots(ncols=3, figsize=(20, 30))
axes[0].imshow(im)
axes[0].set_title('Original Image', size=20)
axes[1].imshow(im_embossed)
axes[1].set_title('Embossed Image', size=20)
axes[2].imshow(im_edges)
axes[2].set_title('Schar Edge Detection', size=20)
for ax in axes:
ax.axis('off')
plt.show()
记得有这两个卷积核,然后彩色图像要对三个通道都进行卷积。