学习笔记,防止自己忘记。
skimage & opencv
基础
- 频域的图像处理主要包括低通滤波和高通滤波
- 低通滤波可以使低频信号正常通过,高于设定的临界值的高频信号则被阻隔或者减弱,可用于去噪,相当于平滑处理
- 高通滤波可以使高频信号正常通过,低于所设定的临界值的低频信号被阻隔或者减弱,可增强图像边缘轮廓等高频信号,相当于锐化处理。
平滑处理
- 用于模糊处理和降低噪声,处理图像中一些不重要的细节,并减小噪声。
- 使用给定领域内像素的平均灰度值或逻辑运算值代替原始图像中像素的灰度值,降低了图像灰度的尖锐变化。
- 但有边缘模糊的负面效应。
平滑线性空间滤波器
盒状态滤波
import numpy as np
from scipy import signal
from skimage import data, io
from matplotlib import pyplot as plt
# 定义二维灰度图像的空间滤波函数
def correl2d(img, window):
s = signal.correlate2d(img, window, mode='same', boundary='fill')
return s.astype(np.uint8)
img = data.grass()
#img = io.imread('tomato.jpg')
# 3*3 盒状滤波模板
window1 = np.ones((3, 3)) / (3 ** 2)
# 5*5 盒状滤波模板
window2 = np.ones((5, 5)) / (5 ** 2)
# 9*9 盒状滤波模板
window3 = np.ones((9, 9)) / (9 ** 2)
# 生成滤波结果
img1 = correl2d(img, window1)
img2 = correl2d(img, window2)
img3 = correl2d(img, window3)
plt.figure()
plt.imshow(img)
plt.figure()
plt.imshow(img1)
plt.figure()
plt.imshow(img2)
plt.figure()
plt.imshow(img3)
plt.show()
高斯平滑滤波
使用data自带图像
import numpy as np
from scipy import signal
from skimage import data, io
from matplotlib import pyplot as plt
import math
# 定义二维灰度图像的空间滤波函数
def correl2d(img, window):
#mode='same' 表示输出尺寸等于输入尺寸
#boundary=‘fill’ 表示滤波前,用常量值填充原始图像的边缘,默认常量值为0
s = signal.correlate2d(img, window, mode='same', boundary='fill')
return s.astype(np.uint8)
# 定义二维高斯函数
def gauss(i, j, sigma):
return 1 / (2 * math.pi * sigma ** 2) * math.exp(-(i ** 2 + j ** 2) / (2 * sigma ** 2))
# 定义radius*radius的高斯平滑模板
def gauss_window(radius, sigma):
window = np.zeros((radius * 2 + 1, radius * 2 + 1))
for i in range(-radius, radius + 1):
for j in range(-radius, radius + 1):
window[i + radius][j + radius] = gauss(i, j, sigma)
return window / np.sum(window)
img = data.grass()
# 3*3 高斯平滑滤波模板
window1 = gauss_window(3, 1.0)
# 5*5 高斯平滑滤波模板
window2 = gauss_window(5, 1.0)
# 9*9 高斯平滑滤波模板
window3 = gauss_window(9, 1.0)
# 生成滤波结果
img1 = correl2d(img, window1)
img2 = correl2d(img, window2)
img3 = correl2d(img, window3)
plt.figure()
plt.imshow(img, cmap='gray')
plt.figure()
plt.imshow(img1, cmap='gray')
plt.figure()
plt.imshow(img2, cmap='gray')
plt.figure()
plt.imshow(img3, cmap='gray')
plt.show()
导入外部图像:
import cv2
import numpy as np
from scipy import ndimage
img1 = cv2.imread('tomato.jpg')
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) # 灰色
cv2.imwrite('gray.jpg', gray)
kernel_3x3 = np.array([
[1, 2, 1],
[2, 4, 2],
[1, 2, 1]
])
kernel_5x5 = np.array([
[1, 4, 7, 4, 1],
[4, 16, 26, 16, 4],
[7, 26, 41, 26, 7],
[4, 16, 26, 16, 4],
[1, 4, 7, 4, 1]
])
kernel_3x3 = kernel_3x3 / kernel_3x3.sum() # 加权平均
kernel_5x5 = kernel_5x5 / kernel_5x5.sum() # 加权平均
img = cv2.imread("tomato.jpg", 0)
k3 = ndimage.convolve(img, kernel_3x3)
k5 = ndimage.convolve(img, kernel_5x5)
cv2.imshow("3x3", k3)
cv2.imshow("5x5", k5)
cv2.imwrite('k3.jpg', k3)
cv2.imwrite('k5.jpg', k5)
cv2.waitKey()
统计排序滤波器
- 典型的统计排序滤波器包括最大值滤波器、中值滤波器、最小值滤波器。
- 最大值滤波器用像素邻域内的最大值代替该像素的灰度值,主要用于寻找亮点。
- 中值滤波器用像素邻域内的中值代替该像素的灰度值,主要用于降噪。
- 最小值滤波器用像素邻域内的最小值代替该像素的灰度值,主要用于寻找最暗点。
灰度图像:
from scipy import ndimage
from skimage import util, data, io
from matplotlib import pyplot as plt
img = io.imread('tomato.jpg')[:, :, 0]
# 对图像加入脉冲噪声
noise_img = util.random_noise(img, mode='s&p', seed=None, clip=True)
# 中值滤波
n = 3
new_img = ndimage.median_filter(noise_img, (n, n))
plt.figure()
plt.axis('off')
plt.imshow(img, cmap='gray') # 显示原始图像
plt.figure()
plt.axis('off')
plt.imshow(noise_img, cmap='gray') # 显示加噪图像
plt.figure()
plt.axis('off')
plt.imshow(new_img, cmap='gray') # 显示去噪图像
plt.show()
RGB空间图像:
from scipy import ndimage
from skimage import util, io
from matplotlib import pyplot as plt
import numpy as np
#img = data.astronaut()
img = io.imread('tomato.jpg')
noise_img = np.zeros(img.shape)
new_img = np.zeros(img.shape)
for i in range(3):
gray_img = img[:, :, i]
# 对图像加入脉冲噪声
noise_img[:, :, i] = util.random_noise(gray_img, mode='s&p', seed=None, clip=True)
# 中值滤波
n = 3
new_img[:, :, i] = ndimage.median_filter(noise_img[:, :, i], (n, n))
plt.figure()
plt.axis('off')
plt.imshow(img, cmap='gray') # 显示原始图像
plt.figure()
plt.axis('off')
plt.imshow(noise_img, cmap='gray') # 显示加噪图像
plt.figure()
plt.axis('off')
plt.imshow(new_img, cmap='gray') # 显示去噪图像
plt.show()
from scipy import ndimage
from skimage import util, data, io
from matplotlib import pyplot as plt
import numpy as np
img = io.imread('tomato.jpg')[:, :, 0]
# 对图像加入胡椒噪声
pepper_img = util.random_noise(img, mode='pepper', seed=None, clip=True)
# 对图像加入盐粒噪声
salt_img = util.random_noise(img, mode='salt', seed=None, clip=True)
n = 3
# 最大值滤波
max_img = ndimage.maximum_filter(pepper_img, (n, n))
# 最小值滤波
min_img = ndimage.minimum_filter(salt_img, (n, n))
plt.figure()
plt.axis('off')
plt.imshow(img, cmap='gray') # 显示原始图像
plt.figure()
plt.axis('off')
plt.imshow(pepper_img, cmap='gray') # 显示加胡椒噪声图像
plt.figure()
plt.axis('off')
plt.imshow(salt_img, cmap='gray') # 显示加盐粒噪声图像
plt.figure()
plt.axis('off')
plt.imshow(max_img, cmap='gray') # 显示最大值滤波图像
plt.figure()
plt.axis('off')
plt.imshow(min_img, cmap='gray') # 显示最小值滤波图像
plt.show()
锐化处理
- 锐化处理的目的就是增强图像中目标的细节、边缘、轮廓和其他灰度突变,削弱了灰度变化缓慢的区域。
一阶微分算子
- 需满足:在灰度不变的区域,微分值为0;在灰度变化的区域,微分值非0。
罗伯特
- 边缘检测的特点: 产生的边缘应清晰;背景尽可能减少噪声;边缘强度尽可能接近人类的感知。
from skimage import data, filters
from matplotlib import pyplot as plt
img = data.camera()
# 罗伯特交叉梯度算子
img_robert_pos = filters.roberts_pos_diag(img)
img_robert_neg = filters.roberts_neg_diag(img)
img_robert = filters.roberts(img)
# 显示原始图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
# 显示罗伯特正对角线边缘图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
# 显示罗伯特负对角线边缘图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
# 显示罗伯特梯度图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
索贝尔
使用skimage,内部图片:
(使用外部图片,会出现error,需要图像是二维数组)
from skimage import data, filters, io
from matplotlib import pyplot as plt
img = data.camera()
#img = io.imread('tomato.jpg')
# Sobel算子
img_sobel_h = filters.sobel_h(img)
img_sobel_v = filters.sobel_v(img)
img_sobel = filters.sobel(img)
# 显示原始图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
# 显示水平Sobel边缘图像
plt.figure()
plt.imshow(img_sobel_h, cmap='gray')
plt.show()
# 显示竖直Sobel边缘图像
plt.figure()
plt.imshow(img_sobel_v, cmap='gray')
plt.show()
# 显示Sobel梯度图像
plt.figure()
plt.imshow(img_sobel, cmap='gray')
plt.show()
使用opencv,外部图片:
import cv2
import numpy as np
img = cv2.imread("tomato.jpg", 0)
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
absX = cv2.convertScaleAbs(x) # 转回unit8
absY = cv2.convertScaleAbs(y)
dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
cv2.imshow("absX", absX)
cv2.imshow("absY", absY)
cv2.imshow("Result", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
二阶微分算子
- 二阶微分算子需满足:在灰度不变的区域微分值为0;在灰度台阶或者斜坡的起点处微分值非0。
拉普拉斯算子
skimage库:
from skimage import data, filters
from matplotlib import pyplot as plt
img = data.camera()
# laplace
img_laplace = filters.laplace(img, ksize=3, mask=None)
img_enhance = img + img_laplace
# 显示原始图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.show()
# 显示拉普拉斯图像
plt.figure()
plt.imshow(img_laplace, cmap='gray')
plt.show()
# 显示锐化增强图像
plt.figure()
plt.imshow(img_enhance, cmap='gray')
plt.show()
opencv库:
#coding=utf-8
import cv2
import numpy as np
img = cv2.imread("tomato.jpg", 0)
gray_lap = cv2.Laplacian(img,cv2.CV_16S,ksize = 3)
dst = cv2.convertScaleAbs(gray_lap)
cv2.imshow('laplacian',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
混合空间增强
- 利用平滑滤波器、锐化滤波器、灰度拉伸等对图像进行处理,得到更理想的效果。
- 过程:
from skimage import data, filters, io
from matplotlib import pyplot as plt
import numpy as np
# 图像空间滤波函数
def correlate2d(img, window):
m = window.shape[0]
n = window.shape[1]
# 边界通过0灰度值填充扩展
img1 = np.zeros((img.shape[0] + m - 1, img.shape[1] + n - 1))
img1[(m - 1) // 2:(img.shape[0] + (m - 1) // 2), (n - 1) // 2:(img.shape[1] + (n - 1) // 2)] = img
img2 = np.zeros(img.shape)
for i in range(img2.shape[0]):
for j in range(img2.shape[1]):
temp = img1[i:i + m, j:j + n]
img2[i, j] = np.sum(np.multiply(temp, window))
return img2
img = io.imread('tomato.jpg', as_gray=True)
# img_laplace为原始图像经过拉普拉斯变换后的结果
window = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
img_laplace = correlate2d(img, window)
img_laplace = 255 * (img_laplace - img_laplace.min()) / (img_laplace.max() - img_laplace.min())
# 将img与img_laplace相加得到锐化增强图像
img_laplace_enhance = img + img_laplace
# img_sobel为原始图像img经sobel处理的结果
img_sobel = filters.sobel(img)
# 使用5*5均值滤波器平滑后的Sobel图像
window_mean = np.ones((5, 5)) / (5 ** 2)
img_sobel_mean = correlate2d(img_sobel, window_mean)
# 将img_laplace_enhance 与 img_sobel_mean相乘得到锐化结果
img_mask = img_laplace_enhance * img_sobel_mean
# 将原图像img与锐化图像img_mask相加得到锐化增强图像
img_sharp_enhance = img + img_mask
# 对img_sharp_enhance进行灰度幂律变换得到最终结果
img_enhance = img_sharp_enhance ** 0.5
# 显示图像
imgList = [img, img_laplace, img_laplace_enhance, img_sobel, img_sobel_mean, img_mask, img_sharp_enhance, img_enhance]
for grayImg in imgList:
plt.figure()
plt.axis('off')
plt.imshow(grayImg, cmap='gray')
plt.show()