本文基于opencv官方文档,是本人的学习笔记。在linux下的opencv4.2,无bug可直接运行。

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

# 对于每个像素,应用相同的阈值。
# 如果像素值小于阈值,则将其设置为0,否则将其设置为最大值。
# 函数cv.threshold用于应用阈值。
# 第一个参数是源图像,它应该是灰度图像。
# 第二个参数是阈值,用于对像素值进行分类。
# 第三个参数是分配给超过阈值的像素值的最大值。
# OpenCV提供了不同类型的阈值,这由函数的第四个参数给出。
# 通过使用cv.THRESH_BINARY类型。所有简单的阈值类型为
#   cv.THRESH_BINARY           正常二值化
#   cv.THRESH_BINARY_INV       翻转二值化
#   cv.THRESH_TRUNC            小于阈值不变,大于为最大
#   cv.THRESH_TOZERO           大于阈值不变,小于为最小
#   cv.THRESH_TOZERO_INV       翻转上面的

img = cv.imread('girl.jpg', 0)
ret, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
ret, thresh2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
ret, thresh3 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
ret, thresh4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
ret, thresh5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

# 自适应阈值
# C++实现 https://www.cnblogs.com/Summerio/p/8280905.html
# 如果图像在不同区域具有不同的光照条件。在这种情况下,自适应阈值阈值化可以提供帮助。
# 在此,算法基于像素周围的小区域确定像素的阈值。因此,对于同一图像的不同区域,
# 我们获得了不同的阈值,这为光照度变化的图像提供了更好的结果。
# 除上述参数外,方法cv.adaptiveThreshold还包含三个输入参数:
# 该adaptiveMethod决定阈值是如何计算的:
# cv.ADAPTIVE_THRESH_MEAN_C::阈值是邻近区域的平均值减去常数C。
# cv.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域值的高斯加权总和减去常数C。
# 该BLOCKSIZE确定附近区域的大小,C是从邻域像素的平均或加权总和中减去的一个常数。
cap = cv.VideoCapture(0)
cv.namedWindow('image')
while 1:
    _, frame = cap.read()
    frame = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
    # 此函数只返回图像 因为它是局部阈值,所以直接进行二值化,然后返回图像
    th1 = cv.adaptiveThreshold(frame, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 5)
    th2 = cv.adaptiveThreshold(frame, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 5)

    # 大津法二值化
    # 高斯滤波后再采用Otsu阈值
    blur = cv.GaussianBlur(frame, (5, 5), 0)
    ret3, th3 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)

    cv.imshow('image', th2)
    if cv.waitKey(1)==27:
        cv.destroyAllWindows()
        break

# 2D卷积(图像过滤)
# 会使图像在一定程度变平滑
img = cv.imread('bird.png')
kernel = np.ones((5, 5), np.float32) / 25

dst = cv.filter2D(img, -1, kernel)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()

# 图像的梯度
# OpenCV提供三种类型的梯度滤波器或高通滤波器,即Sobel,Scharr和Laplacian。
# Sobel 和 Scharr 算子
# Sobel算子是高斯平滑加微分运算的联合运算,因此它更抗噪声。
# 可以指定要采用的导数方向,垂直或水平(分别通过参数yorder和xorder)。
# 还可以通过参数ksize指定内核的大小。如果ksize = -1,则使用3x3 Scharr滤波器,
# 比3x3 Sobel滤波器具有更好的结果。请参阅文档以了解所使用的内核。
# Laplacian算子
# 实现的方法是先用Sobel 算子计算二阶x和y导数,再求和

img = cv.imread('hui.jpg', 0)
laplacian = cv.Laplacian(img, cv.CV_64F)
sobelx = cv.Sobel(img, cv.CV_64F, 1, 0, ksize=5)
sobely = cv.Sobel(img, cv.CV_64F, 0, 1, ksize=5)
plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

# OpenCV下的四种模糊算法
img = cv.imread('girl.jpg')
# 平均 通过功能cv.blur()或cv.boxFilter()完成的
blur = cv.blur(img, (5, 5))
# 高斯模糊
gauss = cv.GaussianBlur(img, (5, 5), 0)
# 中值模糊
median = cv.medianBlur(img, 5)
# 双边过滤
bilateral = cv.bilateralFilter(img, 9, 75, 75)
cv.namedWindow('blur')
cv.namedWindow('gauss')
cv.namedWindow('median')
cv.namedWindow('bilateral')
cv.imshow('blur', blur)
cv.imshow('gauss', gauss)
cv.imshow('median', median)
cv.imshow('bilateral', bilateral)
cv.waitKey(0)
cv.destroyAllWindows()

# Canny 边缘检测
# OpenCV将canny边缘检测放在单个函数cv.Canny()中。
# 第一个参数是我们的输入图像。第二个和第三个参数分别是我们的minVal和maxVal。
# 它们用于检测边缘的真假,是两个梯度阈值
# 第三个参数是perture_size。它是用于查找图像渐变的Sobel内核的大小。
# 默认情况下为3。最后一个参数是L2gradient,它指定用于查找梯度幅度的方程式。
# 如果为True,则使用上面提到的更精确的公式,
# 否则使用以下函数:$Edge_Gradient \; (G) = |G_x| + |G_y|$。
# 默认情况下,它为False。

img = cv.imread('aodiali.jpg', 0)
edges = cv.Canny(img, 100, 200)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()