OpenCV与Matplotlib:灰度图像

        

目录

读取灰度图像

代码解释

1. 导入库

2. 读取彩色图像

3. 转换为灰度图像

4. 将 BGR 图像转换为 RGB 格式

5. 创建子图并显示图像

总结:

整体代码

效果展示

衍生操作

1. 边缘检测

代码说明

整体代码

效果展示

2. 图像二值化

代码说明

整体代码

效果展示

3. 直方图均衡化

4. 轮廓检测

代码说明

整体代码

效果展示

5. 图像分割

代码说明

总结

整体代码

 效果展示

分割的是什么?

图像分割的结果

所分割的内容

总结


如何使用 OpenCV 和 Matplotlib 读取、处理并显示图像。即将为您解答:

读取灰度图像

代码解释

1. 导入库
import cv2
import matplotlib.pyplot as plt

首先,导入了两个重要的库:

  • cv2 是 OpenCV 库,用于图像处理。
  • matplotlib.pyplot 是 Matplotlib 的子模块,用于绘制图像和图表。
2. 读取彩色图像
 
image = cv2.imread('001.jpg')

        这里使用 cv2.imread 函数读取了一张名为 001.jpg 的图像文件。默认情况下,OpenCV 读取图像时会将其存储为 BGR(蓝-绿-红)格式的图像。

3. 转换为灰度图像
 
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

        接下来,使用 cv2.cvtColor 函数将彩色图像转换为灰度图像。灰度图像仅包含亮度信息,没有颜色信息,每个像素用单一灰度值表示。这种转换在图像处理和分析中非常常见,因为灰度图像更简单、更易于处理。

4. 将 BGR 图像转换为 RGB 格式
 
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

        由于 OpenCV 使用 BGR 顺序存储图像,而 Matplotlib 使用 RGB 顺序显示图像,所以在显示图像之前,需要将图像从 BGR 转换为 RGB。

5. 创建子图并显示图像
 
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')

plt.show()

  • plt.figure(figsize=(10, 5)):创建一个宽度为 10 英寸、高度为 5 英寸的图像窗口。
  • plt.subplot(1, 2, 1)plt.subplot(1, 2, 2):创建一个包含两幅子图的窗口。1, 2, 1 表示第一行有两个子图,这是第一个子图;1, 2, 2 表示第二个子图。
  • plt.imshow(image_rgb)plt.imshow(gray_image, cmap='gray'):显示 RGB 图像和灰度图像。cmap='gray' 参数用于指定灰度图像的颜色映射。
  • plt.title 设置每个子图的标题。
  • plt.axis('off'):隐藏坐标轴,专注于图像本身。
  • plt.show():显示图像窗口。
总结:

        这段代码展示了如何读取彩色图像,将其转换为灰度图像,然后使用 Matplotlib 显示这两种图像。通过理解这些步骤,学生可以学会如何使用 Python 进行基础的图像处理任务,包括图像的读取、格式转换和显示。


整体代码

import cv2
import matplotlib.pyplot as plt

# 读取彩色图像
image = cv2.imread('001.jpg')
# 转换为灰度图像
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 将 BGR 图像转换为 RGB 格式
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 创建子图进行显示
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')

plt.show()

效果展示


 

衍生操作

        既然已经读取了灰度图像,我们也不可能只是为了体验一下没有色彩的世界对吧,所以拿到灰度图像之后我们还可以做一些更有意义的事情。

1. 边缘检测

灰度图像通常是边缘检测的第一步,可以使用 Canny 算法进行边缘检测。

代码说明

  1. 读取彩色图像

    image = cv2.imread('001.jpg')

    从文件中读取图像,并存储在 image 变量中。

  2. 转换为灰度图像

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    将彩色图像转换为灰度图像,这是边缘检测的常见预处理步骤,因为边缘主要基于亮度变化。

  3. 进行边缘检测

    edges = cv2.Canny(gray_image, threshold1=100, threshold2=200)

    使用 Canny 算法进行边缘检测。threshold1threshold2 是低阈值和高阈值参数,用于控制检测到的边缘的敏感度。

  4. 图像转换与显示

    • image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB):将图像从 BGR 转换为 RGB 格式,以便在 Matplotlib 中正确显示颜色。
    • plt.subplot(1, 3, 1), plt.subplot(1, 3, 2), plt.subplot(1, 3, 3):创建包含三个子图的图像窗口。
    • plt.imshow(edges, cmap='gray'):显示边缘检测结果。
  5. 展示结果

    plt.show()

    显示包含原图像、灰度图像和边缘检测结果的图像窗口。

整体代码

import cv2
import matplotlib.pyplot as plt

# 读取彩色图像
image = cv2.imread('001.jpg')

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

# 使用Canny算法进行边缘检测
edges = cv2.Canny(gray_image, threshold1=100, threshold2=200)

# 将BGR图像转换为RGB格式(用于Matplotlib显示)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 创建子图进行显示
plt.figure(figsize=(15, 5))

plt.subplot(1, 3, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.imshow(gray_image, cmap='gray')
plt.title('Grayscale Image')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.imshow(edges, cmap='gray')
plt.title('Edge Detection')
plt.axis('off')

plt.show()

效果展示

        最右边为边缘检测的结果

应用: 用于检测图像中的物体边界和轮廓,如车道线检测、人脸轮廓识别等。

2. 图像二值化

二值化是一种将灰度图像转换为仅有黑白两色的图像的过程,可以使用阈值方法进行二值化。

代码说明

  • 读取彩色图像

    image = cv2.imread('001.jpg')

    从文件中读取图像,并存储在 image 变量中。

  • 转换为灰度图像

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    将彩色图像转换为灰度图像,以便进行二值化处理。

  • 应用二值化

    _, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
    

    使用 cv2.threshold 函数进行二值化。参数说明:

    • gray_image 是要处理的灰度图像。
    • 127 是二值化的阈值,像素值大于 127 的会被设为 255,像素值小于或等于 127 的会被设为 0。
    • 255 是像素值被设为白色的值。
    • cv2.THRESH_BINARY 是指定二值化操作的类型。
  • 图像转换与显示

    • image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB):将图像从 BGR 转换为 RGB 格式,以便在 Matplotlib 中正确显示颜色。
    • plt.subplot(1, 2, 1)plt.subplot(1, 2, 2):创建包含两个子图的图像窗口,一个显示原图像,一个显示二值化图像。
  • 展示结果

    plt.show()

    显示包含原图像和二值化图像的图像窗口。

整体代码

import cv2
import matplotlib.pyplot as plt

# 读取彩色图像
image = cv2.imread('001.jpg')

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

# 应用二值化,使用127作为阈值,将大于127的像素值设为255,其余设为0
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

# 将BGR图像转换为RGB格式(用于Matplotlib显示)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 创建子图进行显示
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image')
plt.axis('off')

plt.show()

效果展示

应用: 二值化图像常用于形状检测、对象分割、OCR(光学字符识别)等领域。

3. 直方图均衡化

通过直方图均衡化可以增强图像的对比度,使得原本对比度较低的图像变得更加清晰。

 
equalized_image = cv2.equalizeHist(gray_image)

plt.figure(figsize=(10, 5))
plt.imshow(equalized_image, cmap='gray')
plt.title('Histogram Equalization')
plt.axis('off')
plt.show()

应用: 常用于医学影像处理、卫星图像处理等场景,提高细节可见性。

4. 轮廓检测

可以在二值化图像上进行轮廓检测,识别图像中的形状和对象。

 

代码说明

  • 读取彩色图像

    image = cv2.imread('001.jpg')

    从文件中读取图像,并存储在 image 变量中。

  • 转换为灰度图像

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    将彩色图像转换为灰度图像,为后续的二值化和轮廓检测做准备。

  • 应用二值化

    _, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

    使用 cv2.threshold 进行二值化,将图像转为黑白图像(只有0和255两种值)。

  • 检测轮廓

    contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    

    使用 cv2.findContours 检测图像中的轮廓。参数说明:

    • binary_image 是输入的二值化图像。
    • cv2.RETR_EXTERNAL 表示只检测外轮廓。
    • cv2.CHAIN_APPROX_SIMPLE 使用简单的轮廓近似方法来节省内存。
  • 绘制轮廓

     
    contour_image = image.copy()
    cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2)
    

    在原图像的副本上绘制检测到的轮廓。(0, 255, 0) 指定轮廓的颜色为绿色,2 是线条的粗细。

  • 图像转换与显示

    • image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)contour_image_rgb = cv2.cvtColor(contour_image, cv2.COLOR_BGR2RGB):将图像从 BGR 转换为 RGB 格式,以便在 Matplotlib 中正确显示颜色。
    • plt.subplot(1, 3, 1)plt.subplot(1, 3, 2)plt.subplot(1, 3, 3):创建包含三个子图的图像窗口,分别显示原图像、二值化图像和带有轮廓的图像。
  • 展示结果

     
    plt.show()
    

    显示包含原图像、二值化图像和检测到的轮廓图像的窗口。

整体代码

import cv2
import matplotlib.pyplot as plt

# 读取彩色图像
image = cv2.imread('001.jpg')

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

# 应用二值化
_, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

# 检测轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 在原图像上绘制轮廓
contour_image = image.copy()
cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 2)

# 将BGR图像转换为RGB格式(用于Matplotlib显示)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
contour_image_rgb = cv2.cvtColor(contour_image, cv2.COLOR_BGR2RGB)

# 创建子图进行显示
plt.figure(figsize=(15, 5))

plt.subplot(1, 3, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.imshow(contour_image_rgb)
plt.title('Contours Detected')
plt.axis('off')

plt.show()

效果展示

应用: 用于对象检测、形状分析、物体追踪等。

5. 图像分割

可以通过基于阈值、区域增长、边缘检测等方法对图像进行分割,提取感兴趣的区域。

 

代码说明

  1. 读取彩色图像

     
    image = cv2.imread('001.jpg')
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    

    • cv2.imread('001.jpg') 读取图像文件,并将其存储在 image 变量中。OpenCV 默认以 BGR 格式读取图像。
    • cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 将图像从 BGR 格式转换为 RGB 格式,适用于 Matplotlib 显示。
  2. 图像数据的形状转换

     
    pixel_values = image_rgb.reshape((-1, 3))
    pixel_values = np.float32(pixel_values)
    

    • image_rgb.reshape((-1, 3)) 将图像重塑为一个二维数组,其中每行包含一个像素的 RGB 颜色值。这样,原始的 (height, width, 3) 形状变为 (height * width, 3)。
    • np.float32(pixel_values) 将像素值转换为浮点型,这是 K-Means 聚类所需的格式。
  3. 定义 K-Means 聚类参数

     
    k = 4
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
    _, labels, centers = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    

    • k = 4 表示我们要将图像分成 4 个不同的颜色簇。
    • criteria 是 K-Means 算法的终止条件,设定了迭代次数和精度要求。
    • cv2.kmeans 执行 K-Means 聚类算法,并返回 labelscenterslabels 表示每个像素所属的簇,centers 是每个簇的中心点(代表的颜色)。
  4. 转换为 8 位整数

     
    centers = np.uint8(centers)
    labels = labels.flatten()
    

    • centers 中的颜色值转换为 8 位整数以便显示。
    • labels.flatten() 将标签展平成一维数组,便于后续操作。
  5. 将每个像素值转换为其中心值

     
    segmented_image = centers[labels.flatten()]
    

    • 将每个像素的颜色值替换为其所属簇的中心值。这将使图像显示为仅包含 k 个颜色的版本。
  6. 重塑为原始图像形状

     
    segmented_image = segmented_image.reshape(image_rgb.shape)
    

    • 将图像从 (height * width, 3) 重新塑造为原始的 (height, width, 3) 形状,以便显示。
  7. 创建遮罩,用于分割图像

     
    labels_reshape = labels.reshape(image_rgb.shape[:2])
    mask = labels_reshape == 0
    

    • labels_reshape 将标签重塑为与图像的高和宽匹配的二维数组。
    • mask = labels_reshape == 0 创建了一个布尔掩码,选择标签为 0 的像素。这将用于分割出这个簇对应的部分。
  8. 提取对象

     
    segmented_image_2 = np.copy(image_rgb)
    segmented_image_2[~mask] = 0
    

    • segmented_image_2 复制原始图像。
    • segmented_image_2[~mask] = 0 将掩码之外的部分(即未选择的簇)设为黑色,保留选中的对象。
  9. 显示原图和分割后的图像

    plt.figure(figsize=(10, 5))
    plt.subplot(1, 3, 1)
    plt.imshow(image_rgb)
    plt.title('Original Image')
    plt.axis('off')
    
    plt.subplot(1, 3, 2)
    plt.imshow(segmented_image)
    plt.title('Segmented Image (K-Means)')
    plt.axis('off')
    
    plt.subplot(1, 3, 3)
    plt.imshow(segmented_image_2)
    plt.title('Object Extraction')
    plt.axis('off')
    
    plt.show()
    
    • 使用 Matplotlib 在同一窗口中显示原始图像、K-Means 分割后的图像,以及根据掩码提取的特定对象。

总结

        这个代码主要利用 K-Means 聚类算法对图像进行颜色分割。然后通过选择特定的颜色簇,提取出感兴趣的部分。可以通过修改 mask 的条件来提取不同的颜色区域,进行更复杂的图像分析和处理。

整体代码

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

# 读取彩色图像
image = cv2.imread('001.jpg')
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 图像数据的形状
pixel_values = image_rgb.reshape((-1, 3))
pixel_values = np.float32(pixel_values)

# 定义K-Means聚类参数
k = 4  # 聚类的数量
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
_, labels, centers = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

# 转换为8位整数
centers = np.uint8(centers)
labels = labels.flatten()

# 将每个像素值转换为其中心值
segmented_image = centers[labels.flatten()]

# 重塑为原始图像形状
segmented_image = segmented_image.reshape(image_rgb.shape)

# 创建遮罩,用于分割图像
labels_reshape = labels.reshape(image_rgb.shape[:2])
mask = labels_reshape == 0  # 可选择分割哪个簇

# 提取对象
segmented_image_2 = np.copy(image_rgb)
segmented_image_2[~mask] = 0

# 显示原图和分割后的图像
plt.figure(figsize=(10, 5))

plt.subplot(1, 3, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.imshow(segmented_image)
plt.title('Segmented Image (K-Means)')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.imshow(segmented_image_2)
plt.title('Object Extraction')
plt.axis('off')

plt.show()

 效果展示


        在这个代码中,使用了 K-Means 聚类 来对图像进行分割。K-Means 是一种常见的聚类算法,它将图像中的像素聚类成 kkk 个不同的组(簇)。然后我们可以根据这些聚类的结果选择要分割的对象。

分割的是什么?

        具体来说,K-Means 将图像中的每个像素根据颜色相似性划分到 kkk 个簇中。在这段代码中,k=4,这意味着图像中的像素会被分成 4 个不同的组(颜色簇)。每个簇表示图像中颜色相近的一组像素。分割的对象取决于你选择了哪个簇来提取。

        在代码中,以下部分决定了你要分割哪个簇:

mask = labels_reshape == 0 # 可选择分割哪个簇

        这里 labels_reshape == 0 意味着你选择了标签为 0 的簇,即第一组被聚类出来的像素。这个簇可能代表图像中的一个主要颜色区域。

图像分割的结果

  • 原始图像:展示了原始的 RGB 图像。
  • 分割后的图像 (Segmented Image):这是 K-Means 聚类后的图像,它会将图像中的颜色减少到 4 种颜色之一(因为 k=4)。
  • 对象提取 (Object Extraction):这个图像展示了从原始图像中提取出来的部分。只有那些被分配到标签 0 的像素保留了原始颜色,其他区域被设为黑色。

所分割的内容

        由于 K-Means 是基于颜色的聚类算法,具体分割的内容取决于图像本身及其颜色分布。举例来说:

  • 如果图像中有明显的蓝天、绿草和红花,K-Means 可能会将这些部分分成不同的簇。
  • 如果你选择 mask = labels_reshape == 0,那么代码将提取第一个簇中的像素,比如整个蓝天或某个颜色主导的区域。

要点:通过改变 mask = labels_reshape == 0 中的数字(比如 1, 2, 3),你可以选择提取不同的图像部分。这取决于你的目标是什么,比如提取特定颜色的物体或区域。

应用: 在医学影像中分割器官或肿瘤,在遥感图像中分割土地覆盖类型等。


总结

        其实他整体的应用还是有很多的,这些也只是一些最基本的应用,大家可以多多开展一下自己的思路,创造更多的好点子。

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值