OpenCV-2-图像算子

OpenCV-2-图像算子

二维卷积在图像处理中有着非常重要的作用,不同的卷积核可以得到不同的效果,比如高斯卷积核可以用来做图像的平滑,而一些边缘检测的卷积核可以得到图像的边缘等。二维的卷积也被称为算子,但是实际上算子可以有更广义的理解,针对逐个像素的操作可以认为算子,也就是一个或者多个输入图像到输出图像的函数。

2.1 点算子

上节课最后的部分,即OpenCV-1中的图像叠加,其实就是一个点算子的伏笔。当两个图像叠加满足z=a*x+(1-a)y,其中x和y是两张不同图像的时候,这就是一个覆盖算子,由Blinn在1994年提出。这类的算子可以用于图像的合成,以及抠图。除此之外还有两个最常见的点算子,分别是伽马校正,阈值和直方图均衡化。

2.1.1 伽马校正

import cv2
import numpy as np
from matplotlib import pyplot as plt

def gamma_correction(image, gamma=1.0):
    inv_gamma = 1.0 / gamma
    table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
    return cv2.LUT(image, table)

img = cv2.imread(r'F:\Blog\opencv\lena.png',cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_gamma = gamma_correction(img, gamma = 2.2)

plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(img_gamma)
plt.show()

在这里插入图片描述

这里我们就实现了一个伽马校正的例子。伽马校正就是对于每个像素进行的非线性运算,公式是y=x^(1/gamma),其中要求x和y都是0到1之间。伽马校正是常见的预处理的方法,用于校正照相机传感器器件带来的非线性映射,其中对于数码照相机常见的gamma值取2.2。gamma校正最快最好的实现方法就是如代码所示,构建一个映射函数来完成,其中cv2.LUT是look up tables的简称,就是对应查表,将1到255映射到另一组数值(有兴趣研究的可以在函数中print(table)探索一下)。

涉及到的指令有:cv2.LUT

2.1.2阈值法

正如上面说的,阈值可以理解为一个映射将一定范围内的图像值映射为0将另一部分映射为1或者256

img_gray = cv2.imread(r'F:\Blog\opencv\lena.png',cv2.IMREAD_GRAYSCALE)
ret,img_gray_127 = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)
img_gray_adapt  = cv2.adaptiveThreshold(img_gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
ret,img_gray_otsu = cv2.threshold(img_gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

这里我们简单举三个例子,分别是阈值法,自适应阈值法,和大津法做阈值分割(网上很多人用自己写的方法实现大津法,学习的精神值得肯定,但是建议把人家opencv自带的方法也写出来呀,不然在实际应用的时候用自己写的代码效率还是差了一点,还容易出错)。这里主要的重点在于解释各个函数。

cv2.threshold 传入的是灰度图像,阈值,图像最大值,和阈值的方法,binary是二值的意思,还有cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv.THRESH_TOZERO_INV 等。这里不深入讨论,用官网的一张图解释。

在这里插入图片描述

cv2.adaptiveThreshold传入图像,图像最大值,自适应的方法cv2.ADAPTIVE_THRESH_MEAN_C 和cv2.ADAPTIVE_THRESH_GAUSSIAN_C 阈值的确定方法是均值和高斯核的均值结果减去常数c,阈值的方法,均值或者高斯核的大小,常数c。具体的

另外大津法滤波也是通过threshold实现的,通过cv2.THRESH_BINARY的基础上追加一个大津法的阈值实现cv2.THRESH_OTSU。

涉及到的指令有:cv2.threshold, cv2.adaptiveThreshold

2.1.3直方图均衡化

img_gray = cv2.imread(r'F:\Blog\opencv\lena.png',cv2.IMREAD_GRAYSCALE)
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
plt.subplot(131),plt.plot(hist_full)

img_gray_hist = cv2.equalizeHist(img_gray)
hist_full = cv2.calcHist([img_gray_hist],[0],None,[256],[0,256])
plt.subplot(132),plt.plot(hist_full)

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
img_gray_clahe = clahe.apply(img_gray)
hist_full = cv2.calcHist([img_gray_clahe],[0],None,[256],[0,256])
plt.subplot(133),plt.plot(hist_full)
plt.show()

plt.figure('img')
plt.subplot(131),plt.imshow(img_gray, cmap='gray')
plt.subplot(132),plt.imshow(img_gray_hist, cmap='gray')
plt.subplot(133),plt.imshow(img_gray_clahe, cmap='gray')
plt.show()

在这里插入图片描述

在这里插入图片描述

这里我们展示了如何查看图像的直方图,如何做直方图均衡化和自适应直方图均衡化CLAHE。图像的直方图反映了图像像素灰度值的分布,我们会发现有些图像很多的像素值都很亮或者都很暗,为了进一步校正色彩我们使用直方图均衡化的方法。这个方法的主要目的就是为了将直方图均匀的分布,以达到更好的图像显示效果。直方图均衡化是在整张图像上进行的,自适应直方图均衡化是将图像分成一个个小的局部,在局部进行直方图均衡化并且合并在一起,有很多参数可以在课后根据不同的应用进行不同的设置。

cv2.calcHist(image,channel,mask,histsize,range),参数分别是图像,通道(在彩色图像中可以是[0],[1],[2]),蒙版(同样大小0-255图像),直方图大小通常是256,取值范围0到255。

cv2.equalizeHist是直方图均衡化的命令,cv2.createCLAHE是自适应直方图均衡化的命令。

如果要对彩图进行直方图均衡化处理,我们通常将图像映射到HSI空间,然后对I通道进行直方图均衡化之后,再将HSI映射回RGB或者BGR空间进行后续处理。对彩色图像进行处理的方法在第一讲和该讲全部包含了,大家可以自己尝试

涉及到的指令有:cv2.calcHist, cv2.equalizeHist, cv2.createCLAHE

2.2 邻域算子

2.2.1 图像模糊

img = cv2.imread(r'F:\Blog\opencv\lena.png',cv2.IMREAD_COLOR)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((5,5),np.float32)/25
img_manual = cv2.filter2D(img,-1,kernel)

# 均值
img_avergae = cv2.blur(img,(17,17))
# 高斯
img_gaussian = cv2.GaussianBlur(img,(17,17),1)
# 中值
img_median = cv2.medianBlur(img,17)
# 双边
img_bilateral = cv2.bilateralFilter(img,17,75,75)

plt.subplot(2,3,1),plt.imshow(img)
plt.subplot(2,3,2),plt.imshow(img_manual)
plt.subplot(2,3,3),plt.imshow(img_avergae)
plt.subplot(2,3,4),plt.imshow(img_gaussian)
plt.subplot(2,3,5),plt.imshow(img_median)
plt.subplot(2,3,6),plt.imshow(img_bilateral)
plt.show()

在这里插入图片描述

cv2.filter2D输入的参数是图像,图像的深度和卷积核,其中图像的深度为-1的时候和原图保持一致。这里kernel是一个5*5的核,是一个均值滤波。大家也可以根据功能设计自己想要的滤波器,进行滤波。随后按照顺序展示了均值滤波,高斯滤波,中值滤波,双边滤波。各有特点,网上资料超级多,因为该系列注重opencv的讲解和一些功能的最简单的和标准的实现方法(而非网上流传的各个大牛自己实现函数)所以对滤波器的性质特点不多赘述。

涉及到的指令有:cv2.filter2D, cv2.blur, cv2.GaussianBlur, cv2.medianBlur, cv2.bilateralFilter

2.2.2 梯度检测,边缘检测

img_gray = cv2.imread(r'F:\Blog\opencv\lena.png',cv2.IMREAD_GRAYSCALE)

img_gray_laplacian = cv2.Laplacian(img_gray,cv2.CV_64F)
img_gray_sobelx = cv2.Sobel(img_gray,cv2.CV_64F,1,0,ksize=3)
img_gray_sobely = cv2.Sobel(img_gray,cv2.CV_64F,0,1,ksize=3)
img_gray_canny = cv2.Canny(img,100,200)

print(np.max(img_gray_sobelx))
print(np.min(img_gray_sobelx))
plt.subplot(2,3,1),plt.imshow(img_gray,cmap = 'gray')
plt.subplot(2,3,2),plt.imshow(img_gray_laplacian,cmap = 'gray')
plt.subplot(2,3,3),plt.imshow(img_gray_sobelx,cmap = 'gray')
plt.subplot(2,3,4),plt.imshow(img_gray,cmap = 'gray')
plt.subplot(2,3,5),plt.imshow(img_gray_sobely,cmap = 'gray')
plt.subplot(2,3,6),plt.imshow(img_gray_canny,cmap = 'gray')
plt.show()

494.0
-583.0

在这里插入图片描述

这里我们展示了拉普拉斯算子,sobel算子,canny算子的结果。其中梯度的计算是通过拉普拉斯算子和sobel算子计算的,梯度有正负而且值的得到的结果并不是图像,用cv2.CV_64F规定数据类型为float类型。sobel算子是有方向的算子,其中方向通过1,0和0,1控制方向。而canny算子是用于边缘检测的。

涉及到的指令有:cv2.Laplacian,cv2.Sobel,cv2.Canny

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值