1.线性滤波器
计算机视觉中的线性滤波器是一种数字图像处理技术,它可以对图像进行滤波处理,以达到去噪、边缘检测、图像增强等目的。线性滤波器的本质是将一幅图像与指定的核函数进行卷积,将每一个像素点的值替换为其周围像素点的值与核函数中各项系数的加权和。
常见的线性滤波器包括:均值滤波器、高斯滤波器、中值滤波器等。其中,均值滤波器可以对图像进行平滑处理和去噪。高斯滤波器可以对图像进行平滑处理,同时可以保留图像的高频信息,应用于边缘检测和提高图像质量。中值滤波器可以有效去除图像的椒盐噪声。
2.边缘检测
边缘检测的原理是检测图像中不连续的灰度级变化,并且确定这些变化的位置和方向。目前常用的边缘检测算法有:Sobel算子、Canny算子等。
Sobel算子是一种基于一阶导数的边缘检测算子,在图像x与y方向上分别进行卷积,得到水平和垂直方向上的灰度变化值,通过对这两个方向的值进行平方和再平方根运算,可以得到最终的边缘值。
Canny算法是比较经典且常用的边缘检测算法,其主要思路是:
1.去除图像中的噪声(可以使用高斯滤波器等方法去噪)。
2.计算图像中每个像素的梯度和方向(可以使用Sobel算子等方法计算),得到图像的梯度幅值和方向。
3.非最大值抑制(NMS):在梯度方向上进行极大值筛选,非最大值去掉,去除非边缘响应。
4.双门限阈值:按照高阈值和低阈值进行阈值判定,确定边缘强度值高于高阈值的点为强边缘,边缘强度值在两个阈值之间的点为弱边缘,并根据强边缘的邻域判断弱边缘是否为真边缘。
5.边缘跟踪(连接边缘):将相邻的弱边缘连接到强边缘上,形成完整的边缘。
具体实现步骤如下:
1.对输入图像进行高斯平滑滤波,以去除噪声。
2.计算图像中每个像素的梯度幅值和方向,可以使用Sobel算子等方式计算。
3.对每一个像素,沿着梯度方向上取两个相邻像素,将当前像素的梯度幅值与相邻两个像素的梯度幅值进行比较,如果当前像素梯度幅值最大,则保留该像素值,否则将其值设为0,完成NMS。
4.根据高阈值和低阈值对像素值进行阈值判定,对于高于高阈值的像素点,设为强边缘;对于低于低阈值的像素点,判定为非边缘点;对于介于两者之间的像素点,如果与其邻域中有强边缘点,则将其判定为强边缘,否则为非边缘点。
5.对强边缘点进行边缘跟踪,通过扫描相邻的非边缘点,判断其是否与强边缘相邻,如果相邻则将其标记为边缘,最后形成完整的边缘。
import cv2
import numpy as np
def canny(image, low_threshold, high_threshold):
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯平滑滤波
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
# 计算梯度幅值和方向
grad_x = cv2.Sobel(blurred, cv2.CV_16S, 1, 0)
grad_y = cv2.Sobel(blurred, cv2.CV_16S, 0, 1)
gradient=cv2.addWeighted(cv2.convertScaleAbs(grad_x),0.5,cv2.convertScaleAbs(grad_y), 0.5, 0)
theta = cv2.phase(grad_x, grad_y, angleInDegrees=True)
# 非极大值抑制
rows, cols = gradient.shape
for i in range(1, rows - 1):
for j in range(1, cols - 1):
if (0 <= theta[i, j] < 22.5) or (157.5 <= theta[i, j] <= 180):
if (gradient[i, j] < gradient[i, j - 1]) or (gradient[i, j] < gradient[i, j + 1]):
gradient[i, j] = 0
elif (22.5 <= theta[i, j] < 67.5):
if (gradient[i, j] < gradient[i - 1, j + 1]) or (gradient[i, j] < gradient[i + 1, j - 1]):
gradient[i, j] = 0
elif (67.5 <= theta[i, j] < 112.5):
if (gradient[i, j] < gradient[i - 1, j]) or (gradient[i, j] < gradient[i + 1, j]):
gradient[i, j] = 0
elif (112.5 <= theta[i, j] < 157.5):
if (gradient[i, j] < gradient[i - 1, j - 1]) or (gradient[i, j] < gradient[i + 1, j + 1]):
gradient[i, j] = 0
# 双阈值滞后阈值
strong_edges = (gradient > high_threshold).astype(np.uint8)
canny_edges = cv2.Canny(blurred, low_threshold, high_threshold)
strong_edges_connectivity = cv2.bitwise_and(strong_edges, canny_edges)
# 边缘跟踪
hysteresis_edges = np.zeros_like(strong_edges_connectivity)
rows, cols = hysteresis_edges.shape
for i in range(1, rows - 1):
for j in range(1, cols - 1):
if strong_edges_connectivity[i, j] == 1:
if ((strong_edges_connectivity[i - 1, j - 1:j + 2] == 1).any() or
(strong_edges_connectivity[i, j - 1:j + 2] == 1).any() or
(strong_edges_connectivity[i + 1, j - 1:j + 2] == 1).any()):
hysteresis_edges[i, j] = 1
return hysteresis_edges
3.最小二乘拟合
最小二乘拟合主要用于对一组二维或三维点进行曲线拟合。假设有n个点,每个点的坐标为(x_i, y_i)或(x_i, y_i, z_i),我们希望找到一个函数 y=f(x) 或 z=f(x, y),使得这些点到拟合曲线的距离最小。
4.Hough变换
Hough变换是图像处理中常用的一种算法,可以用于检测图像中的直线、圆等形状。在计算机视觉领域,常用Hough变换进行直线检测和圆检测。
假如要在图像中检测直线。首先我们需要进行边缘检测(例如使用Canny算法),得到二值化的边缘图像。然后,对于图像中的每一个边缘点,按照以下方式在Hough空间中进行投票:
-
遍历每个边缘点。
-
对于每个边缘点,沿着与之相切的每个可能的直线方向,将其对应的直线在Hough空间中进行投票。
-
最终,Hough空间中被投票的点表示的线段即为拟合直线。
对于每个可能的直线方向(theta),都需要在Hough空间中分配足够的位置。一般来说,我们将theta的取值范围限定为0到180度之间。对于每一个theta值,需要在Hough空间中分配足够的位置。而Hough空间是一个二维参数空间,其中坐标轴分别表示rho和theta。rho表示距离原点的距离(从原点到直线的垂线长度),而theta表示直线与x轴的夹角。因此,每个边缘点可以投票到Hough空间中的很多点,每个点都代表着一条直线,这条直线通过原点并且与theta值对应。如果在某个给定的点上投票次数超过了给定阈值,则表示在该点上存在一条直线。
import cv2
import numpy as np
# Load image and perform edge detection
image = cv2.imread('lines.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
# Perform Hough Transform to detect lines
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
# Draw detected lines on the original image
for rho, theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*a)
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*a)
cv2.line(image, (x1,y1), (x2,y2), (0,0,255), 2)
# Display the results
cv2.imshow('Line Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.角点提取
角点提取是计算机视觉中常用的一种技术,主要用于在图像中检测出一些具有显著变化的角点。在图像处理中,角点通常指的是图像中特别明显的发生了变化、有特殊结构的像素点。角点提取技术可以用于许多计算机视觉应用,如目标跟踪、图像配准、立体视觉等领域。
角点检测算法的基本思想是在图像中寻找像素值变化比较大的区域作为角点。在一片图像区域中,如果像素灰度值在任意方向发生明显变化,那么就可以认为这个区域可能是一个角点。角点检测通常是通过计算像素灰度值在不同方向上的变化量,以及计算这些方向的一个方向矩阵,以此来确定角点的位置和响应值。
常见的角点检测算法有Harris角点检测、Shi-Tomasi角点检测、FAST角点检测等。其中,Harris角点检测算法是最早提出的角点检测算法之一,也是最广泛使用的算法之一。下面是一个Python实现使用Harris角点检测算法提取图像中角点的例子:
import cv2
import numpy as np
# Load image and convert to grayscale
image = cv2.imread('corner.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Calculate Harris corner responses
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# Threshold corner responses
dst_thresh = dst > 0.01 * dst.max()
# Draw detected corners on the original image
image[dst_thresh] = [0,0,255]
# Display the results
cv2.imshow('Harris Corner Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
6.兴趣点提取
兴趣点提取,也被称为特征点提取,和角点提取类似,是计算机视觉中极为重要的一种技术。它是为了应对图像平移、旋转、噪声等因素所带来的变化而设计的一种技术,可以帮助我们更鲁棒地进行图像匹配、目标跟踪等任务。
相比于角点提取,兴趣点提取更加广泛、多样。常用的兴趣点算法包括SIFT、SURF、ORB等。这些算法都是通过计算图像局部区域的特征来描述特征点的,常见的特征有方向、尺度、梯度、形状等等。通过提取出这些特征,我们可以在不同图像间进行匹配、跟踪等操作。