12、图像高通滤波、特征检测、修复、分割及深度估计技术解析

图像高通滤波、特征检测、修复、分割及深度估计技术解析

1. 高通滤波器与特征检测

高通滤波器的概念与低通滤波器相反,它允许信息(如信号和图像)的高频分量通过,因此得名。在图像中,边缘属于高频分量,高通滤波器使用的内核会增强图像中的强烈分量,所以对图像应用高通滤波器时,输出结果就是图像的边缘。

OpenCV 提供了许多实现高通滤波器的库函数,下面介绍几个常用函数及其参数:
| 参数 | 含义 |
| ---- | ---- |
| src | 要检测边缘的源图像 |
| ddepth | 决定目标图像的深度,-1 表示源图像和目标图像深度相同 |
| dx | X 方向的导数阶数(Laplacian() 函数不需要) |
| dy | Y 方向的导数阶数(Laplacian() 函数不需要) |
| ksize | 内核矩阵的大小(Sobel() 函数可以是 1、3、5 或 7;Laplacian() 函数是正奇数;Scharr() 函数不需要) |
| scale | 可选的缩放因子,默认不应用缩放 |
| delta | 可选的常数,添加到最终输出 |
| borderType | 边界像素的外推方法 |

以下是使用 Sobel()、Laplacian() 和 Scharr() 函数计算输入图像的拉普拉斯和一阶 X 导数的代码:

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('/home/pi/book/dataset/4.1.05.tiff', 0)
laplacian = cv2.Laplacian(img, ddepth=cv2.CV_32F, ksize=17,
                          scale=1, delta=0,
                          borderType=cv2.BORDER_DEFAULT)
sobel = cv2.Sobel(img, ddepth=cv2.CV_32F, dx=1, dy=0,
                  ksize=11, scale=1, delta=0,
                  borderType=cv2.BORDER_DEFAULT)
scharr = cv2.Scharr(img, ddepth=cv2.CV_32F, dx=1, dy=0,
                    scale=1, delta=0,
                    borderType=cv2.BORDER_DEFAULT)
images=[img, laplacian, sobel, scharr]
titles=['Original', 'Laplacian', 'Sobel', 'Scharr']
for i in range(4):
    plt.subplot(2, 2, i+1)
    plt.imshow(images[i], cmap = 'gray')
    plt.title(titles[i])
    plt.axis('off')
plt.show()

使用 Laplacian()、Scharr() 和 Sobel() 函数计算图像的 X 导数会返回输入图像中的垂直边缘。

我们还可以连接两个按钮到 7 和 11 GPIO 引脚,通过编程调整 dx 和 dy 的值,代码如下:

import RPi.GPIO as GPIO
import cv2
x = 0
y = 1
cap = cv2.VideoCapture(0)
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
button1 = 7
button2 = 11
GPIO.setup(button1, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(button2, GPIO.IN, GPIO.PUD_UP)
while True:
    print(x, y)
    ret, frame = cap.read()
    button1_state = GPIO.input(button1)
    if button1_state == GPIO.LOW:
        x = 0
        y = 1
    button2_state = GPIO.input(button2)
    if button2_state == GPIO.LOW:
        x = 1
        y = 0
    output = cv2.Scharr(frame, ddepth=cv2.CV_32F,
                        dx=x, dy=y,
                        scale=1, delta=0,
                        borderType=cv2.BORDER_DEFAULT)
    cv2.imshow('Salt and pepper Noise App', output)
    if cv2.waitKey(1) == 27:
        break
cap.release()
cv2.destroyAllWindows()

另外,我们可以将同一实时视频流的 X 导数和 Y 导数(使用 Scharr 计算)相加,代码如下:

import cv2
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    output1 = cv2.Scharr(frame, ddepth=cv2.CV_32F,
                        dx=0, dy=1,
                        scale=1, delta=0,
                        borderType=cv2.BORDER_DEFAULT)
    output2 = cv2.Scharr(frame, ddepth=cv2.CV_32F,
                        dx=1, dy=0,
                        scale=1, delta=0,
                        borderType=cv2.BORDER_DEFAULT)
    cv2.imshow('Addition of Vertical and Horizontal',
               cv2.add(output1, output2))
    if cv2.waitKey(1) == 27:
        break
cap.release()
cv2.destroyAllWindows()
2. Canny 边缘检测器

Canny 边缘检测算法由 John Canny 开发,该算法大量使用了高通滤波器的概念,具有多个步骤:
1. 对输入图像应用 5x5 像素的高斯核以去除噪声。
2. 计算滤波后图像强度的梯度,可以使用 L1 或 L2 范数。
3. 应用非极大值抑制,识别可能的边缘候选集。
4. 最后进行滞后阈值处理,根据传递给图像的阈值确定最终的边缘。

OpenCV 的 cv2.Canny() 函数实现了 Canny 算法,其参数如下:
| 参数 | 含义 |
| ---- | ---- |
| img | 需要检测边缘的输入源图像 |
| threshold1 | 阈值的下限 |
| threshold2 | 阈值的上限 |
| L2gradient | 如果为 True,使用 L2 范数计算边缘集,更准确但计算量大;如果为 False,使用 L1 范数计算,计算量小但准确性低 |

以下代码演示了 Canny 边缘检测:

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('/home/pi/book/dataset/4.1.05.tiff', 0)
edges1 = cv2.Canny(img, 50, 300, L2gradient=False)
edges2 = cv2.Canny(img, 100, 150, L2gradient=True)
images = [img, edges1, edges2]
titles = ['Original', 'L1 Gradient', 'L2 Gradient']
for i in range(3):
    plt.subplot(1, 3, i+1)
    plt.imshow(images[i], cmap = 'gray')
    plt.title(titles[i])
    plt.axis('off')
plt.show()

我们还可以通过 OpenCV 的跟踪条实时调整阈值来计算边缘,代码如下:

import cv2
cv2.namedWindow('Canny')
img = cv2.imread('/home/pi/book/dataset/4.1.05.tiff', 0)
def empty(z):
    pass
cv2.createTrackbar('Threshold 1', 'Canny', 50, 100, empty)
cv2.createTrackbar('Threshold 2', 'Canny', 150, 300, empty)
while(True):
    l1 = cv2.getTrackbarPos('Threshold 1', 'Canny')
    l2 = cv2.getTrackbarPos('Threshold 2', 'Canny')
    output = cv2.Canny(img, l1, l2, L2gradient=False)
    cv2.imshow('Canny', output)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
3. 霍夫变换检测圆和线

OpenCV 的 cv2.HoughCircles() 函数可以使用霍夫方法检测图像中的圆,它返回检测到的圆的圆心和半径。以下是使用该函数检测 USB 网络摄像头实时视频流中圆的代码:

import cv2
cap = cv2.VideoCapture(0)
while (True):
    ret , frame = cap.read()
    grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blur = cv2.blur(grey, (5, 5))
    circles = cv2.HoughCircles(blur,
                               method=cv2.HOUGH_GRADIENT,
                               dp=1, minDist=200,
                               param1=50, param2=13,
                               minRadius=30, maxRadius=175)
    if circles is not None:
        for i in circles [0,:]:
            cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
            cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
    cv2.imshow('Detected', frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

OpenCV 的 cv2.HoughLines() 函数可以检测图像中的线,它接受灰度图像、rho(累加器的距离精度)、theta(累加器的角度精度)和累加器的阈值作为参数。以下是使用该函数检测 USB 网络摄像头实时视频流中线的代码:

import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while True:
    ret, img = cap.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 250, apertureSize=5,
                      L2gradient=True)
    lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
    if lines is not None:
        for rho,theta in lines[0]:
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a*rho
            y0 = b*rho
            pts1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
            pts2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
            cv2.line(img, pts1, pts2, (0, 0, 255), 2)
    cv2.imshow('Detected Lines', img)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()
4. Harris 角点检测

OpenCV 的 cv2.cornerHarris() 函数用于检测角点,其参数如下:
| 参数 | 含义 |
| ---- | ---- |
| img | 输入图像,必须是灰度图且为 float32 类型 |
| blockSize | 角点检测时考虑的邻域大小 |
| ksize | 使用的 Sobel 导数的孔径参数 |
| k | 方程中使用的自由 Harris 检测器参数 |

以下是实现 Harris 角点检测的示例代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('/home/pi/book/dataset/4.1.05.tiff', 0)
img = np.float32(img)
dst = cv2.cornerHarris(img, 2, 3, 0.04)
ret, dst = cv2.threshold(dst, 0.01*dst.max(), 255, 0)
dst = np.uint8(dst)
plt.imshow(dst, cmap='gray')
plt.axis('off')
plt.show()
5. 图像修复、分割与深度图

图像修复是从图像的现有部分重建受损部分的计算过程。图像可能会因为多种原因受损,如照片纸随时间退化、传感器故障、相机镜头上的灰尘和污垢等。OpenCV 的 cv2.inpaint() 函数实现了两种图像修复方法,该函数接受受损源图像、图像修复掩码、修复邻域大小和修复方法作为参数。

以下是使用两种方法进行图像修复的代码:

import cv2
import matplotlib.pyplot as plt
image = cv2.imread('/home/pi/book/dataset/Damaged.tiff')
mask = cv2.imread('/home/pi/book/dataset/Mask.tiff', 0)
input = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
output_TELEA = cv2.inpaint(input, mask, 5, cv2.INPAINT_TELEA)
output_NS = cv2.inpaint(input, mask, 5, cv2.INPAINT_NS)
plt.subplot(221)
plt.imshow(input)
plt.title('Damaged Image')
plt.axis('off')
plt.subplot(222)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.axis('off')
plt.subplot(223)
plt.imshow(output_TELEA)
plt.title('Telea Method')
plt.axis('off')
plt.subplot(224)
plt.imshow(output_NS)
plt.title('Navier Stokes Method')
plt.axis('off')
plt.show()

图像分割是将图像分成不同区域的过程,阈值处理是一种基本的分割形式。最后,还可以计算视差图并估计图像中物体的深度。

综上所述,这些技术在工业自动化、智能车辆和机器人技术等领域有着广泛的应用。通过掌握这些技术,我们可以对图像进行更深入的处理和分析。

图像高通滤波、特征检测、修复、分割及深度估计技术解析

6. 图像修复、分割与深度图的详细分析

在前面我们已经了解了图像修复的基本概念和使用 OpenCV 的 cv2.inpaint() 函数进行修复的方法。下面我们进一步分析图像修复的两种方法及其应用场景。

  • Telea 方法 :基于 2004 年 Alexandru Telea 发表的论文中描述的技术。该方法在处理一些纹理较为简单、连续性较好的图像损伤时效果较好,能够快速且有效地填充受损区域,使修复后的图像在视觉上较为自然。
  • Navier - Stokes 方法 :基于 2001 年 Bertalmio Marcelo、Andrea L. Bertozzi 和 Guillermo Sapiro 发表的论文中描述的技术。这种方法在处理复杂纹理和具有一定结构的图像损伤时表现出色,它能够更好地保留图像的原有结构和纹理信息。

以下是这两种方法的对比表格:
| 方法 | 原理依据 | 适用场景 | 优点 |
| ---- | ---- | ---- | ---- |
| Telea 方法 | An Image Inpainting Technique Based on the Fast Marching Method | 纹理简单、连续性好的图像损伤 | 修复速度快,视觉效果自然 |
| Navier - Stokes 方法 | Navier - Stokes, Fluid Dynamics, and Image and Video Inpainting | 复杂纹理和有结构的图像损伤 | 更好地保留图像结构和纹理信息 |

图像分割是将图像划分成不同区域的过程,它在许多领域都有重要应用,如目标检测、图像识别等。常见的图像分割方法有以下几种:
1. 阈值分割 :这是最基本的分割方法,通过设定一个或多个阈值,将图像像素分为不同的类别。例如,对于灰度图像,可以根据像素的灰度值与阈值的比较结果,将像素分为前景和背景。
2. 基于边缘的分割 :利用图像中的边缘信息进行分割。边缘通常对应着图像中不同区域的边界,通过检测边缘可以将图像分割成不同的部分。前面介绍的 Canny 边缘检测算法就可以用于基于边缘的分割。
3. 基于区域的分割 :根据图像中像素的相似性(如颜色、纹理等)将图像划分为不同的区域。常见的方法有区域生长、分水岭算法等。

下面是一个简单的阈值分割示例代码:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('/home/pi/book/dataset/4.1.05.tiff', 0)
ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

plt.imshow(thresh, cmap='gray')
plt.axis('off')
plt.show()

深度估计是计算机视觉中的一个重要任务,它可以帮助我们了解图像中物体的三维信息。通过计算视差图可以实现深度估计,视差图反映了左右图像中对应点的水平位移差异。一般来说,视差越大,物体离相机越近。

7. 技术应用流程总结

为了更清晰地展示这些技术的应用流程,我们可以使用 mermaid 流程图来表示。以下是一个综合的图像特征检测、修复、分割及深度估计的流程图:

graph LR
    A[输入图像] --> B{选择处理类型}
    B --> |特征检测| C[高通滤波]
    B --> |图像修复| D[选择修复方法]
    B --> |图像分割| E[选择分割方法]
    B --> |深度估计| F[计算视差图]
    C --> G[边缘检测(Canny 等)]
    C --> H[角点检测(Harris 等)]
    C --> I[圆和线检测(霍夫变换)]
    D --> J[Telea 方法]
    D --> K[Navier - Stokes 方法]
    E --> L[阈值分割]
    E --> M[基于边缘的分割]
    E --> N[基于区域的分割]
    F --> O[获取深度信息]
    G --> P[输出边缘图像]
    H --> Q[输出角点图像]
    I --> R[输出圆和线检测结果]
    J --> S[输出修复后图像(Telea)]
    K --> T[输出修复后图像(Navier - Stokes)]
    L --> U[输出分割结果(阈值)]
    M --> V[输出分割结果(边缘)]
    N --> W[输出分割结果(区域)]
    O --> X[输出深度图]
8. 技术优化与拓展

在实际应用中,为了提高这些技术的性能和效果,我们可以进行一些优化和拓展。
- 参数调整 :对于高通滤波、Canny 边缘检测、霍夫变换等算法,合理调整参数可以显著提高检测效果。例如,在霍夫变换检测圆时,可以根据实际情况调整 minDist param1 param2 等参数,以减少误检和漏检。
- 多算法结合 :将不同的算法结合使用可以发挥各自的优势。例如,在图像分割中,可以先使用 Canny 边缘检测得到边缘信息,再结合区域生长算法进行更精确的分割。
- 深度学习方法 :近年来,深度学习在计算机视觉领域取得了巨大的成功。可以使用深度学习模型进行图像修复、分割和特征检测,如 U - Net 用于图像分割,Pix2Pix 用于图像修复等。

以下是一个简单的参数调整示例,以霍夫变换检测圆为例:

import cv2

cap = cv2.VideoCapture(0)
while (True):
    ret, frame = cap.read()
    grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blur = cv2.blur(grey, (5, 5))
    # 调整参数
    circles = cv2.HoughCircles(blur,
                               method=cv2.HOUGH_GRADIENT,
                               dp=1, minDist=150,
                               param1=60, param2=15,
                               minRadius=20, maxRadius=200)
    if circles is not None:
        for i in circles[0, :]:
            cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
            cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
    cv2.imshow('Detected', frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()
9. 总结

通过对图像高通滤波、特征检测、修复、分割及深度估计技术的详细介绍,我们了解了这些技术的原理、实现方法和应用场景。高通滤波和特征检测可以帮助我们提取图像中的重要特征,如图像边缘、角点、圆和线等;图像修复技术可以恢复受损图像的质量;图像分割可以将图像划分为不同的区域,便于后续的分析和处理;深度估计可以让我们获取图像中物体的三维信息。

这些技术在工业自动化、智能车辆、机器人技术、医学图像分析等领域都有广泛的应用前景。在实际应用中,我们需要根据具体需求选择合适的算法和方法,并进行必要的优化和拓展,以达到最佳的处理效果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值