本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:OpenCV是一个广泛应用于图像处理与计算机视觉的开源库,支持图像读取、变换、滤波、分割、特征检测和人脸识别等功能。本主题通过Java示例讲解OpenCV处理图像的基本流程,涵盖图像变换、颜色空间转换、边缘检测及人脸检测等关键技术。学习者可通过实战项目掌握图像处理的核心技能,适用于学术研究与工业应用。
openCV处理图片

1. OpenCV图像处理基础概念

图像处理构成了现代计算机视觉系统的核心基础,而OpenCV(Open Source Computer Vision Library)作为业界广泛使用的开源视觉库,提供了涵盖图像读取、变换、滤波、边缘检测等全流程的丰富功能接口。本章将从图像的基本构成讲起,深入解析图像数据在内存中的存储方式(如Mat对象结构),并介绍常见的图像格式及其通道排列(如BGR、灰度图等)。同时,我们还将理解图像处理在计算机视觉任务中的关键作用,例如目标识别、图像增强与特征提取等场景。通过本章的学习,读者将建立起对OpenCV图像处理流程的整体认知框架,并为后续章节的代码实践打下坚实的理论基础。

2. OpenCV图像读取、显示与输出

在图像处理流程中,图像的读取、显示与输出是构建计算机视觉系统的基础步骤。OpenCV提供了简洁高效的接口函数,如 imread imshow imwrite 等,使得开发者能够快速完成图像的加载、展示与保存操作。本章将深入探讨这些基础函数的使用方法、数据结构原理以及图像格式的处理机制,帮助读者掌握图像处理的起始环节。

2.1 图像读取与数据结构

OpenCV图像处理的第一步是图像的读取。图像的加载不仅涉及文件格式的支持,还涉及内存中数据的表示方式。掌握这些基础知识有助于后续图像处理操作的顺利进行。

2.1.1 使用imread函数读取图像文件

OpenCV中使用 imread 函数从文件中读取图像。其基本调用方式如下:

import cv2

image = cv2.imread("image.jpg")
参数说明:
  • "image.jpg" :图像文件路径。
  • cv2.IMREAD_COLOR (默认):读取为彩色图像(BGR格式)。
  • cv2.IMREAD_GRAYSCALE :读取为灰度图像。
  • cv2.IMREAD_UNCHANGED :保留图像的原始通道信息(例如包含透明通道的PNG图像)。
代码逻辑分析:
  • 第一行导入OpenCV模块。
  • 第二行调用 imread 函数,将指定路径的图像文件读取为一个NumPy数组,并赋值给变量 image
  • 若文件路径错误或图像格式不支持,返回值为 None
示例:读取图像并判断是否成功
import cv2

image = cv2.imread("image.jpg")

if image is None:
    print("图像加载失败,请检查文件路径或格式!")
else:
    print("图像加载成功,尺寸为:", image.shape)

该段代码在读取失败时输出错误提示,并在成功时输出图像的尺寸(高度、宽度、通道数)。

2.1.2 图像数据在内存中的表示(Mat对象)

OpenCV中图像数据是以 Mat 对象的形式存储的,该对象本质上是一个多维数组(NumPy数组)。图像数据的维度、通道数以及像素值的存储方式直接影响后续处理的效率。

Mat对象的结构:
属性 描述
rows 图像高度(行数)
cols 图像宽度(列数)
channels 通道数(1为灰度图,3为BGR彩色图)
data 像素值数组(字节形式)
type 数据类型(如CV_8UC3表示8位无符号3通道)
示例:查看图像Mat对象属性
import cv2

image = cv2.imread("image.jpg")

print("图像尺寸:", image.shape)  # 输出 (height, width, channels)
print("数据类型:", image.dtype)
print("总像素数:", image.size)
执行逻辑说明:
  • image.shape :返回图像的维度信息,包括高度、宽度和通道数。
  • image.dtype :返回图像的数据类型,通常是 uint8 (8位无符号整数)。
  • image.size :返回图像的总像素数量,等于 rows * cols * channels

2.1.3 支持的图像格式与通道数解析

OpenCV支持多种图像格式的读取,包括常见的BMP、PNG、JPEG、TIFF、WEBP等。不同格式的图像在读取时可能会有不同的通道数。

支持格式与通道数对照表:
图像格式 通道数 说明
BMP 3 BGR格式
PNG 4 BGR + Alpha(透明通道)
JPEG 3 BGR格式
TIFF 可变 支持多通道与压缩
WEBP 4 BGR + Alpha
示例:读取不同格式图像并查看通道数
import cv2

img_bmp = cv2.imread("image.bmp")
img_png = cv2.imread("image.png")
img_jpeg = cv2.imread("image.jpg")

print("BMP图像通道数:", img_bmp.shape[2])
print("PNG图像通道数:", img_png.shape[2])
print("JPEG图像通道数:", img_jpeg.shape[2])
逻辑分析:
  • 调用 imread 分别读取不同格式图像。
  • 使用 shape[2] 提取图像的通道数并打印。
  • PNG图像通常包含Alpha通道(透明度),因此通道数为4。

2.2 图像的显示与窗口管理

图像显示是图像处理流程中不可或缺的环节。OpenCV通过 imshow 函数实现图像的可视化,结合 waitKey 等函数可实现多窗口管理和交互响应。

2.2.1 使用imshow函数显示图像

cv2.imshow() 函数用于创建一个窗口并显示图像,其基本语法如下:

cv2.imshow("Window Title", image)
示例:显示图像并等待按键关闭
import cv2

image = cv2.imread("image.jpg")
cv2.imshow("显示图像", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
逻辑分析:
  • cv2.imshow() :创建一个标题为“显示图像”的窗口,并显示图像。
  • cv2.waitKey(0) :等待键盘输入,参数为0表示无限等待。
  • cv2.destroyAllWindows() :关闭所有OpenCV创建的窗口。

2.2.2 多图像窗口管理技巧

在处理多个图像时,可以使用多个窗口分别显示。OpenCV允许创建多个独立窗口,并可通过 waitKey 控制窗口的生命周期。

示例:显示两张图像在不同窗口
import cv2

img1 = cv2.imread("image1.jpg")
img2 = cv2.imread("image2.jpg")

cv2.imshow("Image 1", img1)
cv2.imshow("Image 2", img2)

cv2.waitKey(0)
cv2.destroyAllWindows()
逻辑分析:
  • 读取两张图像。
  • 使用两个不同的窗口标题分别显示。
  • 所有窗口在按键后关闭。

2.2.3 键盘事件响应(waitKey)

waitKey 函数不仅可以用于暂停图像显示,还可以捕获键盘事件,实现图像交互功能。

示例:按键控制图像关闭与保存
import cv2

image = cv2.imread("image.jpg")
cv2.imshow("Interactive Image", image)

while True:
    key = cv2.waitKey(1)
    if key == ord('q'):
        print("退出程序")
        break
    elif key == ord('s'):
        cv2.imwrite("saved_image.jpg", image)
        print("图像已保存为 saved_image.jpg")

cv2.destroyAllWindows()
逻辑分析:
  • waitKey(1) :每1毫秒检测一次按键。
  • ord('q') :检测是否按下“q”键,按下则退出循环。
  • ord('s') :检测是否按下“s”键,按下则调用 imwrite 保存图像。

2.3 图像的保存与输出

图像处理完成后,通常需要将结果保存为文件。OpenCV的 imwrite 函数提供图像保存功能,并支持多种格式与参数设置。

2.3.1 使用imwrite函数保存处理后的图像

基本调用方式如下:

cv2.imwrite("output.jpg", image)
示例:保存灰度图像
import cv2

image = cv2.imread("image.jpg")
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray_image.jpg", gray_image)
逻辑分析:
  • 读取原始图像。
  • 使用 cvtColor 将图像转换为灰度图。
  • 使用 imwrite 将处理后的图像保存为 gray_image.jpg

2.3.2 图像保存格式与压缩参数设置

某些图像格式(如PNG、JPEG)支持压缩参数设置。OpenCV通过传递参数列表控制保存质量。

JPEG图像压缩示例:
import cv2

image = cv2.imread("image.jpg")
params = [int(cv2.IMWRITE_JPEG_QUALITY), 90]  # 设置JPEG质量为90
cv2.imwrite("compressed.jpg", image, params)
参数说明:
  • cv2.IMWRITE_JPEG_QUALITY :JPEG图像质量参数,范围0~100。
  • 90 :质量设置值,数值越大图像质量越高,文件体积也越大。
PNG图像压缩示例:
params = [int(cv2.IMWRITE_PNG_COMPRESSION), 9]  # 压缩等级0~9
cv2.imwrite("compressed.png", image, params)
  • cv2.IMWRITE_PNG_COMPRESSION :PNG压缩等级参数,数值越大压缩率越高,但处理时间也更长。

2.3.3 图像输出的完整流程实践

将图像读取、显示、处理、保存整合为一个完整的图像处理流程:

import cv2

# 读取图像
image = cv2.imread("image.jpg")
if image is None:
    print("图像加载失败")
    exit()

# 显示原始图像
cv2.imshow("Original Image", image)

# 图像处理:转换为灰度图
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 显示灰度图
cv2.imshow("Gray Image", gray_image)

# 保存处理后的图像
cv2.imwrite("processed_image.jpg", gray_image)

# 等待用户按键
while True:
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

cv2.destroyAllWindows()
逻辑分析:
  • 首先加载图像并判断是否成功。
  • 显示原始图像和灰度图。
  • 将灰度图保存为新文件。
  • 使用循环等待用户按键,按“q”退出程序。

本章总结
本章详细讲解了OpenCV中图像读取、显示与输出的全过程,从图像的加载、内存表示、格式支持,到图像显示窗口管理、键盘响应,再到图像保存与压缩参数设置。通过代码示例和参数说明,帮助读者全面掌握图像处理的基础操作流程,为后续的图像变换、滤波、边缘检测等进阶操作打下坚实基础。

3. 图像的基本变换操作

图像变换是图像预处理阶段的核心内容之一,尤其在计算机视觉、目标检测、图像增强等任务中,变换操作能够帮助调整图像视角、尺寸和位置,提升后续处理的准确性和鲁棒性。OpenCV 提供了丰富的图像变换接口,包括平移、缩放、旋转等几何变换操作。本章将深入讲解这些变换的原理、实现方式及其实际应用,通过代码示例和参数分析,帮助读者全面掌握图像基本变换的使用方法。

3.1 图像平移变换

图像的平移(Translation)是最基础的几何变换之一,其核心思想是将图像在二维平面上沿 x 轴和 y 轴方向移动一定距离。平移变换常用于图像对齐、坐标变换、目标定位等场景。

3.1.1 平移矩阵的构造方法

图像平移可以通过构造一个 2x3 的仿射变换矩阵 实现。假设图像沿 x 轴方向移动 tx 像素,沿 y 轴方向移动 ty 像素,则平移矩阵 M 可表示为:

M = \begin{bmatrix}
1 & 0 & tx \
0 & 1 & ty
\end{bmatrix}

该矩阵可以直接用于 OpenCV 的 warpAffine 函数进行图像变换。

示例:构造平移矩阵
import cv2
import numpy as np

# 读取图像
img = cv2.imread('example.jpg')

# 定义平移距离
tx = 100  # x 方向平移
ty = 50   # y 方向平移

# 构造平移矩阵
M = np.float32([[1, 0, tx], [0, 1, ty]])

参数说明:
- np.float32 :确保矩阵数据类型为浮点型,符合 OpenCV 接口要求。
- tx ty :分别表示图像在 x 和 y 方向上的偏移量,单位为像素。

3.1.2 使用 warpAffine 实现图像平移

OpenCV 提供了 warpAffine 函数来实现仿射变换,其语法如下:

cv2.warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
  • src :输入图像
  • M :变换矩阵
  • dsize :输出图像的大小(width, height)
  • flags :插值方法,默认为 INTER_LINEAR
  • borderMode :边界填充方式,默认为 BORDER_CONSTANT
  • borderValue :边界填充颜色(默认黑色)
示例:执行图像平移
# 获取图像尺寸
height, width = img.shape[:2]

# 执行平移操作
translated_img = cv2.warpAffine(img, M, (width, height))

# 显示图像
cv2.imshow('Original', img)
cv2.imshow('Translated', translated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

执行逻辑分析:
- img.shape[:2] 获取图像的高度和宽度,用于构造目标图像的尺寸。
- cv2.warpAffine() 根据平移矩阵 M 将原图平移,并保持输出图像尺寸不变。
- cv2.imshow() 显示原图与变换后的图像进行对比。

💡 注意 :平移后图像边缘会空出一部分区域,默认使用黑色填充。可以通过 borderMode borderValue 参数自定义填充方式。

3.2 图像缩放与插值方法

图像缩放(Scaling)是改变图像尺寸的基本操作,广泛应用于图像预处理、可视化和图像匹配等任务。OpenCV 提供了 resize 函数来实现图像缩放,并支持多种插值方法,影响图像缩放后的质量。

3.2.1 resize 函数的参数详解

OpenCV 中图像缩放主要使用 cv2.resize() 函数,其语法如下:

cv2.resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
  • src :源图像
  • dsize :输出图像的尺寸(width, height)
  • fx , fy :沿 x、y 方向的缩放因子(可选)
  • interpolation :插值方法,常用包括:
  • INTER_NEAREST :最近邻插值,速度快但质量低
  • INTER_LINEAR :双线性插值,默认方法
  • INTER_CUBIC :三次样条插值,质量高但速度慢
  • INTER_AREA :区域插值,适合缩小图像
示例:固定尺寸缩放
# 缩放为 300x200 像素
resized_img = cv2.resize(img, (300, 200), interpolation=cv2.INTER_LINEAR)
示例:按比例缩放
# 缩放为原图的 0.5 倍
resized_img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)

参数说明:
- dsize fx/fy 互斥,选择其一即可。
- 插值方法根据缩放方向选择,放大推荐 INTER_LINEAR INTER_CUBIC ,缩小推荐 INTER_AREA

3.2.2 不同插值算法对图像质量的影响

为了对比不同插值算法的效果,我们对同一张图像分别使用 INTER_NEAREST INTER_LINEAR INTER_CUBIC 进行放大。

插值方法 特点 适用场景
INTER_NEAREST 最快,图像锯齿明显 实时性要求高
INTER_LINEAR 质量适中,平衡速度与质量 默认推荐
INTER_CUBIC 质量最高,计算开销大 图像质量要求高
INTER_AREA 缩小时效果最佳 图像缩小处理
示例:比较不同插值方法
resized_nearest = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_NEAREST)
resized_linear = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
resized_cubic = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

# 显示结果对比
cv2.imshow('INTER_NEAREST', resized_nearest)
cv2.imshow('INTER_LINEAR', resized_linear)
cv2.imshow('INTER_CUBIC', resized_cubic)
cv2.waitKey(0)
cv2.destroyAllWindows()

执行逻辑分析:
- 图像被放大两倍,不同插值方法在放大过程中对像素值的计算方式不同,从而导致图像质量差异。
- 可以观察到 INTER_NEAREST 会产生明显的锯齿,而 INTER_CUBIC 效果更平滑但计算更耗时。

3.3 图像旋转与仿射变换

图像旋转是图像处理中常用的几何变换操作之一,通常用于图像矫正、方向调整等任务。OpenCV 提供了获取旋转矩阵的函数 getRotationMatrix2D ,结合 warpAffine 即可实现图像旋转。

3.3.1 获取旋转矩阵(getRotationMatrix2D)

函数原型如下:

cv2.getRotationMatrix2D(center, angle, scale)
  • center :旋转中心点坐标 (x, y)
  • angle :旋转角度(正数为逆时针)
  • scale :缩放比例(1 表示不缩放)
示例:构造旋转矩阵
# 设置旋转中心为图像中心
center = (width // 2, height // 2)

# 旋转角度为 45 度,缩放比例为 1
M = cv2.getRotationMatrix2D(center, angle=45, scale=1)

参数说明:
- center :旋转中心,默认为图像中心点。
- angle :旋转角度,单位为度,正值为逆时针方向。
- scale :可选参数,用于控制图像缩放。

3.3.2 仿射变换与图像旋转实践

结合 getRotationMatrix2D warpAffine 即可实现图像旋转。

示例:图像旋转操作
# 获取图像尺寸
height, width = img.shape[:2]

# 执行旋转
rotated_img = cv2.warpAffine(img, M, (width, height))

# 显示结果
cv2.imshow('Rotated', rotated_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

执行逻辑分析:
- M 是通过 getRotationMatrix2D 生成的旋转矩阵。
- warpAffine 将图像按照旋转矩阵进行仿射变换。
- 输出图像尺寸不变,旋转后边缘可能被裁剪,可通过修改 dsize 扩展图像区域。

3.3.3 多变换组合操作(旋转+平移)

在实际应用中,常常需要对图像进行多个变换的组合操作,例如先旋转再平移。可以通过矩阵乘法将多个变换矩阵合并,实现一次性操作。

示例:旋转+平移组合
# 构造旋转矩阵
M_rotate = cv2.getRotationMatrix2D(center, angle=30, scale=1)

# 构造平移矩阵
M_translate = np.float32([[1, 0, 100], [0, 1, 50]])

# 合并矩阵(先旋转后平移)
M_combined = np.vstack([M_rotate, [0, 0, 1]]) @ np.vstack([M_translate, [0, 0, 1]])
M_combined = M_combined[:2, :]

# 执行组合变换
transformed_img = cv2.warpAffine(img, M_combined, (width, height))

# 显示结果
cv2.imshow('Combined Transform', transformed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

执行逻辑分析:
- 使用 np.vstack() 将 2x3 矩阵扩展为 3x3 齐次变换矩阵,便于进行矩阵乘法。
- 通过矩阵乘法合并旋转和平移变换,最终生成的 M_combined 是一个复合变换矩阵。
- warpAffine 使用复合矩阵完成一次性的图像变换。

3.4 小结与进阶思考

本章详细介绍了图像的三种基本几何变换:平移、缩放和旋转。通过构造变换矩阵并结合 warpAffine 函数,可以灵活地实现图像的多种变换操作。同时,我们探讨了不同插值方法对图像缩放质量的影响,并通过矩阵乘法实现了多变换的组合操作。

🧠 拓展思考:

  • 如何实现图像绕任意点旋转?
  • 通过修改 getRotationMatrix2D center 参数即可。
  • 如何防止图像旋转后被裁剪?
  • 可以动态计算旋转后的图像尺寸,扩展输出区域。
  • 图像变换是否会影响后续特征提取?
  • 是的,变换可能引入畸变,需结合插值方法进行优化。

在下一章中,我们将进入图像颜色空间的转换与增强技术,深入探讨如何通过颜色空间优化图像处理流程。

4. 颜色空间转换与图像增强

图像的颜色空间决定了图像中颜色信息的表示方式,而图像增强则是为了提升图像的视觉质量或为后续的图像分析提供更优的输入。OpenCV 提供了多种颜色空间转换方法和图像增强技术,合理使用这些技术可以显著提升图像处理的效果。本章将从颜色空间的基本概念出发,深入讲解 OpenCV 中常用的颜色空间转换操作,以及图像增强的核心技术与实际应用。

4.1 常见颜色空间概述

在图像处理中,颜色空间是图像数据的基本表示方式之一。不同的颜色空间适用于不同的图像处理任务,例如 RGB 适合图像显示,HSV 更适合颜色分割,YUV 常用于视频编码等。

4.1.1 RGB与BGR的区别

RGB 是最常见的颜色空间,它使用红(Red)、绿(Green)、蓝(Blue)三个通道来表示颜色。OpenCV 中默认的图像存储格式是 BGR ,而不是常见的 RGB 。这是因为在 OpenCV 的早期版本中,图像数据是按照 BGR 顺序读取的,这是出于性能优化的考虑。

import cv2

# 读取图像(默认BGR格式)
image_bgr = cv2.imread("image.jpg")

# 转换为RGB格式
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)

逐行解释
- cv2.imread :读取图像,返回的矩阵是 BGR 格式。
- cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB) :将图像从 BGR 转换为 RGB 格式,便于后续处理或显示。

BGR 与 RGB 的差异对比表:
特性 BGR RGB
存储顺序 Blue, Green, Red Red, Green, Blue
OpenCV 默认
适用场景 图像处理、OpenCV 显示 图像显示、图像合成、机器学习

4.1.2 HSV、YUV等颜色空间的特点

除了 RGB/BGR 之外,还有多种颜色空间在图像处理中有其独特优势:

  • HSV(Hue, Saturation, Value) :表示颜色的色相、饱和度和亮度。适用于基于颜色的图像分割。
  • YUV :用于视频压缩和传输,Y 表示亮度,UV 表示色度。
  • Lab :感知均匀的颜色空间,适用于颜色匹配和图像增强。
  • HLS(Hue, Lightness, Saturation) :与 HSV 类似,但 Lightness 表示明暗。
颜色空间对比表:
颜色空间 组成通道 优势领域 OpenCV 转换函数
HSV Hue, Saturation, Value 颜色分割、阈值处理 cvtColor(..., COLOR_BGR2HSV)
YUV Y, U, V 视频压缩、肤色检测 cvtColor(..., COLOR_BGR2YUV)
Lab L, a, b 颜色匹配、图像增强 cvtColor(..., COLOR_BGR2Lab)
HLS Hue, Lightness, Saturation 颜色分割、光照变化适应 cvtColor(..., COLOR_BGR2HLS)

4.2 颜色空间转换实践

OpenCV 提供了 cvtColor 函数用于在不同颜色空间之间进行转换。该函数使用灵活,支持多种颜色空间之间的相互转换。

4.2.1 使用cvtColor函数实现颜色转换

import cv2

# 读取图像
image = cv2.imread("image.jpg")

# 转换为 HSV 颜色空间
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 转换为 Lab 颜色空间
image_lab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)

# 转换为灰度图
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

逐行解释
- cv2.cvtColor(image, cv2.COLOR_BGR2HSV) :将图像从 BGR 转换为 HSV 格式。
- cv2.cvtColor(image, cv2.COLOR_BGR2Lab) :将图像从 BGR 转换为 Lab 格式。
- cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) :将图像从 BGR 转换为灰度图。

颜色转换流程图(mermaid 格式):
graph TD
    A[原始图像 BGR] --> B{选择目标颜色空间}
    B -->|HSV| C[调用 cvtColor(COLOR_BGR2HSV)]
    B -->|Lab| D[调用 cvtColor(COLOR_BGR2Lab)]
    B -->|Gray| E[调用 cvtColor(COLOR_BGR2GRAY)]
    C --> F[HSV 图像]
    D --> G[Lab 图像]
    E --> H[灰度图像]

4.2.2 灰度图在图像处理中的应用

灰度图是单通道图像,常用于图像预处理阶段,如边缘检测、形态学操作、图像二值化等。灰度图像的优势在于减少了数据维度,提升了处理效率。

应用场景:
  • 边缘检测(Canny、Sobel)
  • 图像二值化(threshold)
  • 模板匹配(Template Matching)
  • 特征提取(如 HOG、SIFT)
# 显示原始图像与灰度图像对比
import cv2
import matplotlib.pyplot as plt

image = cv2.imread("image.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

plt.subplot(1, 2, 1)
plt.title("Original")
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))

plt.subplot(1, 2, 2)
plt.title("Grayscale")
plt.imshow(gray, cmap='gray')
plt.show()

逐行解释
- cv2.cvtColor(image, cv2.COLOR_BGR2RGB) :将图像从 BGR 转为 RGB 用于 matplotlib 显示。
- cmap='gray' :设置灰度图显示为黑白图像。

4.2.3 HSV空间在图像分割中的应用

HSV 空间特别适合基于颜色的图像分割。例如,在检测特定颜色的对象(如红色苹果、蓝色车辆)时,可以通过设置 HSV 的色相范围来提取目标区域。

import cv2
import numpy as np

# 读取图像并转换为 HSV
image = cv2.imread("red_apple.jpg")
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 定义红色的 HSV 阈值范围
lower_red = np.array([0, 120, 70])
upper_red = np.array([10, 255, 255])

# 创建掩膜
mask = cv2.inRange(hsv, lower_red, upper_red)

# 应用掩膜
result = cv2.bitwise_and(image, image, mask=mask)

cv2.imshow("Original", image)
cv2.imshow("Mask", mask)
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

逐行解释
- cv2.inRange(hsv, lower_red, upper_red) :创建一个掩膜,用于提取红色区域。
- cv2.bitwise_and :将原图与掩膜结合,只保留红色区域。

HSV颜色分割流程图:
graph TD
    A[原始图像] --> B[转换为HSV]
    B --> C[定义颜色阈值]
    C --> D[创建掩膜]
    D --> E[应用掩膜提取目标]

4.3 图像增强技术

图像增强旨在提升图像的视觉效果或为后续处理提供更清晰的数据。常见的增强技术包括对比度和亮度调整、直方图均衡化、颜色空间增强等。

4.3.1 对比度与亮度调整

对比度和亮度是影响图像视觉质量的两个关键因素。OpenCV 提供了 convertScaleAbs 函数来实现这两个参数的调整。

import cv2

# 读取图像
image = cv2.imread("image.jpg")

# 调整对比度与亮度
alpha = 1.5  # 对比度增益
beta = 30    # 亮度增益
enhanced = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)

cv2.imshow("Original", image)
cv2.imshow("Enhanced", enhanced)
cv2.waitKey(0)
cv2.destroyAllWindows()

逐行解释
- alpha 控制对比度,值越大图像对比度越高。
- beta 控制亮度,值越大图像越亮。
- convertScaleAbs :将像素值进行线性变换并取绝对值。

对比度与亮度调整对照表:
参数 作用 推荐范围
alpha 对比度增益 0.5 ~ 2.0
beta 亮度增益 -100 ~ 100

4.3.2 直方图均衡化提升图像质量

直方图均衡化是一种常用的图像增强技术,适用于图像对比度较低的场景。它通过调整图像的灰度分布,使得图像的亮度分布更加均匀。

import cv2

# 读取灰度图像
gray = cv2.imread("low_contrast.jpg", 0)

# 直方图均衡化
equalized = cv2.equalizeHist(gray)

cv2.imshow("Original", gray)
cv2.imshow("Equalized", equalized)
cv2.waitKey(0)
cv2.destroyAllWindows()

逐行解释
- cv2.equalizeHist(gray) :对灰度图像进行直方图均衡化处理。
- 该方法适用于单通道图像,不适用于彩色图像。

直方图均衡化流程图:
graph TD
    A[输入图像] --> B[计算灰度直方图]
    B --> C[计算累积分布函数]
    C --> D[映射像素值]
    D --> E[输出均衡化图像]

4.3.3 颜色空间下的图像增强技巧

在 HSV 或 Lab 空间中进行图像增强,可以更有效地调整图像的颜色、亮度等属性。例如,在 HSV 空间中调整 V 通道可以提升图像的亮度,而不影响颜色。

import cv2
import numpy as np

image = cv2.imread("image.jpg")
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV).astype("float32")

# 增加亮度值(V通道)
hsv[..., 2] = np.clip(hsv[..., 2] * 1.5, 0, 255)

# 转换回 BGR
enhanced = cv2.cvtColor(hsv.astype("uint8"), cv2.COLOR_HSV2BGR)

cv2.imshow("Original", image)
cv2.imshow("Enhanced", enhanced)
cv2.waitKey(0)
cv2.destroyAllWindows()

逐行解释
- hsv[..., 2] :选择 HSV 图像的 V(亮度)通道。
- np.clip(..., 0, 255) :防止亮度值超出 0~255 范围。
- astype("float32") :便于进行乘法运算,防止溢出。

颜色空间增强对比表:
方法 优势 适用场景
HSV 亮度增强 仅增强亮度,不影响颜色 低光照图像增强
Lab 通道调整 调整明暗通道(L通道)增强对比度 图像质量提升、特征增强
RGB 通道增益 精确控制红、绿、蓝三色亮度 色彩还原、特定颜色增强

本章从颜色空间的基本概念出发,系统讲解了 OpenCV 中常见的颜色空间及其转换方法,并结合实际代码演示了图像增强技术的应用。通过 HSV 颜色空间的图像分割、灰度图的处理、对比度与亮度调整、直方图均衡化等内容,读者可以掌握如何在实际项目中利用颜色空间和图像增强技术提升图像质量和处理效果。这些技术是后续图像分割、特征提取和机器学习任务的重要基础。

5. 图像滤波与边缘检测

图像滤波与边缘检测是图像处理中两个关键步骤,它们分别承担着噪声抑制和特征提取的任务。滤波操作通过局部像素的加权平均,可以有效去除图像中的高频噪声,为后续的边缘检测提供更干净的输入。而边缘检测则是识别图像中物体边界的重要手段,常用于图像分割、目标识别等高级视觉任务。本章将从图像滤波技术入手,逐步介绍均值滤波、高斯滤波、中值滤波的原理与实现方式,随后深入解析边缘检测的核心算法(如Sobel、Canny),并通过具体代码示例展示其应用方式,帮助读者掌握如何在实际项目中进行图像预处理与特征提取。

5.1 图像滤波技术

图像滤波是图像处理中最基础也是最重要的操作之一,广泛应用于去噪、模糊、锐化等场景。滤波的核心思想是通过一个滤波核(或称卷积核)对图像的局部像素进行加权平均,从而改变图像的视觉效果和特征。常见的图像滤波方法包括均值滤波、高斯滤波和中值滤波。这些方法各有优劣,适用于不同的噪声类型和应用场景。

5.1.1 均值滤波与blur函数

均值滤波是一种线性滤波方法,其核心思想是将图像中每个像素的值替换为周围像素的平均值。这种方法可以有效去除图像中的高斯噪声,但可能会导致图像边缘变得模糊。

均值滤波原理

均值滤波器使用一个固定大小的卷积核(如3x3或5x5),对图像中的每个像素进行加权平均处理。例如,3x3的均值滤波核如下:

[1/9 1/9 1/9
 1/9 1/9 1/9
 1/9 1/9 1/9]

OpenCV提供了 cv2.blur() 函数用于实现均值滤波。

示例代码
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像并转换为灰度图
img = cv2.imread('noisy_image.jpg', 0)

# 应用均值滤波
blurred = cv2.blur(img, (5, 5))

# 显示原始图像与滤波后的图像
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blurred, cmap='gray'), plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
代码解析
  • cv2.imread('noisy_image.jpg', 0) :以灰度模式读取图像。
  • cv2.blur(img, (5, 5)) :使用5x5的均值滤波核对图像进行平滑处理。
  • plt.imshow(...) :使用Matplotlib显示图像。
适用场景

均值滤波适用于去除图像中的高斯噪声,但对椒盐噪声效果不佳。由于其线性特性,容易造成图像边缘模糊。

5.1.2 高斯滤波与GaussianBlur函数

高斯滤波是一种加权平均滤波器,其权重按照二维高斯分布进行分配,能够更好地保留图像边缘,同时有效去除高斯噪声。

高斯滤波原理

高斯滤波的核心在于使用一个高斯核对图像进行卷积。该核的权重分布呈钟形曲线,中心像素的权重最大,周围像素的权重逐渐减小。例如,5x5的高斯核如下:

[1  4  6  4  1
 4 16 24 16 4
 6 24 36 24 6
 4 16 24 16 4
 1  4  6  4  1]

OpenCV提供了 cv2.GaussianBlur() 函数实现高斯滤波。

示例代码
# 应用高斯滤波
gaussian_blurred = cv2.GaussianBlur(img, (5, 5), 0)

# 显示图像
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(gaussian_blurred, cmap='gray'), plt.title('Gaussian Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
代码解析
  • cv2.GaussianBlur(img, (5, 5), 0) :使用5x5大小的高斯核进行滤波,第三个参数为标准差,设为0表示由核大小自动计算。
优势分析

与均值滤波相比,高斯滤波能更好地保留图像的边缘细节,同时有效去除高斯噪声,是图像预处理中常用的滤波方式。

5.1.3 中值滤波与椒盐噪声去除

中值滤波是一种非线性滤波方法,特别适用于去除图像中的椒盐噪声(Salt and Pepper Noise)。其原理是将窗口内的像素值排序,取中值作为当前像素的输出值。

中值滤波原理

中值滤波不依赖像素的加权平均,而是选择窗口内像素的中位数。这种方法能有效消除孤立的噪声点,同时保留图像边缘。

示例代码
# 添加椒盐噪声
def add_salt_pepper_noise(image, salt_prob=0.01, pepper_prob=0.01):
    noisy = np.copy(image)
    total_pixels = image.size

    # Salt noise
    num_salt = int(np.ceil(salt_prob * total_pixels))
    coords = [np.random.randint(0, i, num_salt) for i in image.shape]
    noisy[coords[0], coords[1]] = 255

    # Pepper noise
    num_pepper = int(np.ceil(pepper_prob * total_pixels))
    coords = [np.random.randint(0, i, num_pepper) for i in image.shape]
    noisy[coords[0], coords[1]] = 0

    return noisy

# 添加噪声
noisy_img = add_salt_pepper_noise(img)

# 使用中值滤波去噪
median_blurred = cv2.medianBlur(noisy_img, 5)

# 显示图像
plt.subplot(121), plt.imshow(noisy_img, cmap='gray'), plt.title('Noisy Image')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(median_blurred, cmap='gray'), plt.title('Median Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
代码解析
  • add_salt_pepper_noise(...) :自定义函数模拟椒盐噪声。
  • cv2.medianBlur(noisy_img, 5) :使用5x5窗口的中值滤波器进行去噪。
适用场景

中值滤波特别适合去除椒盐噪声,在医学图像、遥感图像等存在大量离群点的场景中表现优异。

5.1.4 三种滤波方式对比

滤波方式 噪声类型 边缘保留能力 适用场景
均值滤波 高斯噪声 简单去噪、图像模糊处理
高斯滤波 高斯噪声 保留边缘的同时去噪
中值滤波 椒盐噪声 去除离群点、医学图像处理

5.1.5 流程图:图像滤波流程

graph TD
    A[输入图像] --> B[选择滤波类型]
    B --> C{噪声类型?}
    C -->|高斯噪声| D[选择均值或高斯滤波]
    C -->|椒盐噪声| E[选择中值滤波]
    D --> F[设置滤波核大小]
    E --> F
    F --> G[执行滤波操作]
    G --> H[输出滤波后图像]

5.2 边缘检测原理与实现

边缘是图像中亮度变化剧烈的区域,通常对应于物体的轮廓或边界。边缘检测在图像处理中具有重要意义,广泛应用于目标检测、图像分割、特征提取等任务。OpenCV提供了多种边缘检测算法,如Sobel、Laplacian、Canny等。本节将重点介绍Sobel算子和Canny边缘检测算法的原理与实现。

5.2.1 Sobel算子与梯度计算

Sobel算子是一种基于梯度的一阶导数边缘检测算子,能够检测图像中水平和垂直方向的边缘。其基本思想是通过两个3x3的卷积核分别计算水平和垂直方向的梯度,然后综合得到边缘强度。

Sobel算子公式

水平方向卷积核:

[-1 0 1
 -2 0 2
 -1 0 1]

垂直方向卷积核:

[-1 -2 -1
  0  0  0
  1  2  1]

OpenCV中使用 cv2.Sobel() 函数实现Sobel边缘检测。

示例代码
# Sobel边缘检测
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobel_combined = cv2.magnitude(sobelx, sobely)

# 显示结果
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(sobel_combined, cmap='gray'), plt.title('Sobel Edge')
plt.xticks([]), plt.yticks([])
plt.show()
代码解析
  • cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) :计算水平方向梯度, cv2.CV_64F 表示输出图像的深度。
  • cv2.magnitude(sobelx, sobely) :合并水平与垂直方向的梯度,得到最终边缘强度图。
优势与局限

Sobel算子计算速度快,适合实时处理,但容易受到噪声影响,边缘可能不够连续。

5.2.2 Canny边缘检测算法原理

Canny边缘检测是一种多阶段的边缘检测算法,被认为是当前最有效的边缘检测方法之一。其步骤包括:

  1. 高斯滤波 :去除图像噪声。
  2. 计算梯度幅值与方向 :使用Sobel算子。
  3. 非极大值抑制 :保留局部最大值,抑制非边缘点。
  4. 双阈值检测 :区分强边缘、弱边缘与非边缘。
  5. 边缘连接 :仅保留与强边缘相连的弱边缘。

OpenCV中使用 cv2.Canny() 函数实现Canny边缘检测。

示例代码
# Canny边缘检测
edges = cv2.Canny(img, threshold1=100, threshold2=200)

# 显示结果
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray'), plt.title('Canny Edge')
plt.xticks([]), plt.yticks([])
plt.show()
参数说明
  • threshold1 :低阈值,用于边缘连接。
  • threshold2 :高阈值,用于边缘检测。
优势分析

Canny算法能够有效抑制噪声,提取连续、准确的边缘,是图像分割和目标识别中常用的边缘检测方法。

5.2.3 Canny函数的使用与参数调优

合理设置阈值是使用Canny算法的关键。以下是一个自动调整阈值的示例:

# 自动阈值调整
v = np.median(img)
lower = int(max(0, 0.66 * v))
upper = int(min(255, 1.33 * v))

edges_auto = cv2.Canny(img, lower, upper)

plt.imshow(edges_auto, cmap='gray')
plt.title('Auto-thresholded Canny Edge')
plt.xticks([]), plt.yticks([])
plt.show()
参数调优技巧
  • 若图像噪声较大,应提高高阈值。
  • 若边缘不连续,应适当降低低阈值。
  • 自动阈值方法适用于大多数场景,但在特定图像中仍需手动调节。

5.2.4 流程图:Canny边缘检测流程

graph TD
    A[输入图像] --> B[高斯滤波去噪]
    B --> C[计算梯度幅值与方向]
    C --> D[非极大值抑制]
    D --> E[双阈值检测]
    E --> F[边缘连接]
    F --> G[输出边缘图像]

5.3 边缘检测的应用场景

边缘信息是图像中最显著的特征之一,广泛应用于计算机视觉任务中。本节将介绍边缘检测在图像轮廓提取、物体边界识别和图像分割中的实际应用。

5.3.1 图像轮廓提取

图像轮廓是物体外部边界的集合。通过边缘检测可以提取图像中物体的轮廓,为后续的形状分析提供基础。

示例代码
# 提取轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓
contour_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2)

# 显示结果
plt.imshow(cv2.cvtColor(contour_img, cv2.COLOR_BGR2RGB))
plt.title('Object Contours')
plt.xticks([]), plt.yticks([])
plt.show()
代码解析
  • cv2.findContours(...) :查找图像中的轮廓。
  • cv2.drawContours(...) :绘制轮廓。

5.3.2 物体边界识别

边缘信息可用于识别图像中物体的边界,辅助进行目标定位和识别。

示例代码
# 使用边缘信息识别物体边界
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 找出最大轮廓
max_contour = max(contours, key=cv2.contourArea)

# 绘制最大轮廓
boundary_img = np.zeros_like(img)
cv2.drawContours(boundary_img, [max_contour], -1, 255, 2)

plt.imshow(boundary_img, cmap='gray')
plt.title('Object Boundary')
plt.xticks([]), plt.yticks([])
plt.show()

5.3.3 边缘信息用于图像分割

边缘信息可作为图像分割的基础,通过边缘连接或区域生长算法实现更精确的图像分割。

示例代码
# 使用Canny边缘作为分割基础
seg_mask = np.zeros_like(img)
cv2.fillPoly(seg_mask, [max_contour], 255)

# 显示分割结果
plt.imshow(seg_mask, cmap='gray')
plt.title('Segmentation Mask')
plt.xticks([]), plt.yticks([])
plt.show()
小结

边缘检测不仅用于图像分析,更是图像分割、目标识别、形状分析等任务的重要基础。掌握其原理与应用方式,有助于构建更高效的图像处理系统。

6. 图像二值化与形态学操作

图像二值化和形态学操作是图像预处理中极为重要的两个步骤,尤其在图像分割、特征提取和目标识别中起着关键作用。图像二值化通过设定阈值将图像转换为黑白两色,从而突出图像中的目标区域。而形态学操作(如腐蚀、膨胀、开运算、闭运算等)则用于改善二值图像的结构特征,去除噪声、连接断裂区域、细化或粗化目标轮廓。

本章将从图像二值化的常用方法入手,逐步深入到形态学基本操作及其高级应用,帮助读者掌握图像从灰度处理到结构优化的完整流程。

6.1 图像二值化方法

图像二值化是将灰度图像转化为黑白图像的过程,通常通过设定一个阈值,将像素值高于该阈值的设为白色(255),低于该阈值的设为黑色(0)。

6.1.1 全局阈值法(threshold函数)

OpenCV中使用 cv2.threshold() 函数进行图像的全局阈值处理。

import cv2
import numpy as np

# 读取图像并转为灰度图
img = cv2.imread('image.jpg', 0)
# 全局阈值处理
ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

cv2.imshow('Binary Image', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • img :输入的灰度图像
  • 127 :设定的阈值
  • 255 :最大值,超过阈值的部分设为该值
  • cv2.THRESH_BINARY :二值化类型,表示大于阈值为255,否则为0

6.1.2 自适应阈值法(adaptiveThreshold)

当图像光照不均匀时,使用自适应阈值法更为合适,OpenCV提供了 cv2.adaptiveThreshold() 函数。

# 自适应阈值处理
thresh_adapt = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, 
                                     cv2.THRESH_BINARY, 11, 2)

cv2.imshow('Adaptive Threshold', thresh_adapt)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • ADAPTIVE_THRESH_MEAN_C :根据邻域像素的平均值计算阈值
  • 11 :邻域大小
  • 2 :常数,从平均值中减去该值

6.1.3 Otsu算法与自动阈值选取

Otsu算法可以自动计算最佳阈值,适用于图像前景与背景对比度较大的情况。

# Otsu算法
ret_otsu, thresh_otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

print("Otsu自动阈值:", ret_otsu)
cv2.imshow('Otsu Threshold', thresh_otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • THRESH_OTSU :自动计算最佳阈值

6.2 形态学基本操作

形态学操作是基于图像形状的处理方法,常用于二值图像的结构优化,主要包括腐蚀、膨胀、开运算和闭运算。

6.2.1 腐蚀操作(erode)与噪声去除

腐蚀操作可以缩小前景物体的边界,常用于去除小的噪声点。

# 定义结构元素
kernel = np.ones((5,5), np.uint8)
# 腐蚀操作
erosion = cv2.erode(thresh_otsu, kernel, iterations=1)

cv2.imshow('Erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • kernel :结构元素,定义操作区域
  • iterations :迭代次数,越大腐蚀越强

6.2.2 膨胀操作(dilate)与区域连接

膨胀操作与腐蚀相反,可以扩大前景物体的边界,有助于连接断裂的区域。

# 膨胀操作
dilation = cv2.dilate(thresh_otsu, kernel, iterations=1)

cv2.imshow('Dilation', dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.2.3 开运算与闭运算的组合应用

  • 开运算 :先腐蚀后膨胀,用于去除小的噪点
  • 闭运算 :先膨胀后腐蚀,用于填充前景物体中的小洞
# 开运算
opening = cv2.morphologyEx(thresh_otsu, cv2.MORPH_OPEN, kernel)
# 闭运算
closing = cv2.morphologyEx(thresh_otsu, cv2.MORPH_CLOSE, kernel)

cv2.imshow('Opening', opening)
cv2.imshow('Closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3 形态学操作的高级应用

形态学操作不仅限于基础的腐蚀和膨胀,还可以组合出更复杂的图像处理效果,适用于边缘提取、细节增强和图像分割等场景。

6.3.1 形态学梯度提取边缘

形态学梯度是膨胀与腐蚀的差值,可以提取图像的边缘信息。

# 形态学梯度
gradient = cv2.morphologyEx(thresh_otsu, cv2.MORPH_GRADIENT, kernel)

cv2.imshow('Gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3.2 礼帽与黑帽操作增强细节

  • 礼帽操作 (Top Hat):原始图像与开运算的差值,突出比背景亮的小区域
  • 黑帽操作 (Black Hat):闭运算与原始图像的差值,突出比背景暗的小区域
# 礼帽操作
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# 黑帽操作
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

cv2.imshow('Top Hat', tophat)
cv2.imshow('Black Hat', blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3.3 在图像分割中的形态学应用

在图像分割中,形态学操作可以用于细化目标轮廓、连接断点、去除小区域干扰。例如,使用闭运算连接断点,再使用开运算去除小区域噪声,从而获得更清晰的目标区域。

# 图像分割后的形态学处理
final_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel)
final_mask = cv2.morphologyEx(final_mask, cv2.MORPH_OPEN, kernel)

cv2.imshow('Final Mask', final_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

mermaid流程图示意

graph TD
    A[原始图像] --> B[灰度化]
    B --> C[二值化]
    C --> D[腐蚀/膨胀]
    D --> E[开/闭运算]
    E --> F[形态学梯度/礼帽]
    F --> G[图像分割或边缘提取]

这一章我们深入探讨了图像二值化的多种方法及其对应的形态学操作,为后续的图像分析和目标识别奠定了坚实基础。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:OpenCV是一个广泛应用于图像处理与计算机视觉的开源库,支持图像读取、变换、滤波、分割、特征检测和人脸识别等功能。本主题通过Java示例讲解OpenCV处理图像的基本流程,涵盖图像变换、颜色空间转换、边缘检测及人脸检测等关键技术。学习者可通过实战项目掌握图像处理的核心技能,适用于学术研究与工业应用。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐