OpenCV与AI深度学习 | 实战 | 基于OpenCV和K-Means聚类实现颜色分割(步骤 + 代码)

本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。

原文链接:实战 | 基于OpenCV和K-Means聚类实现颜色分割(步骤 + 代码)

介 绍

    颜色分割是计算机视觉中使用的一种技术,可根据颜色识别和区分图像中的不同物体或区域。聚类算法可以自动将相似的颜色归为一组,而无需为每种颜色指定阈值。当处理颜色范围很广的图像或事先不知道确切阈值时,此功能非常有用。

    本文中,我们将探索如何使用 K-Means聚类算法进行颜色分割,并计算每种颜色的对象数量。我们将使用“泡泡射击”游戏中的图像作为示例,根据轮廓查找和过滤气泡对象,并应用 K 均值算法将颜色相似的气泡分组在一起。这将使我们能够计算和提取颜色相似的气泡的蒙版,以供进一步的下游应用使用。我们将使用OpenCV和scikit-learn库进行图像分割和颜色聚类。

from matplotlib import pyplot as plt
import cv2
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
%matplotlib inlin
image = cv2.imread(r'bubbles.jpeg', cv2.IMREAD_UNCHANGED)
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.axis('off')

使用阈值提取二进制掩码

    第一步是从背景中提取所有气泡。为此,我们将首先使用cv2.cvtColor()函数将图像转换为灰度,然后使用cv2.threshold()它将其转换为二进制图像,其中像素为 0 或 255。阈值设置为 60,因此所有低于 60 的像素都设置为 0,其他像素设置为 255。由于一些气泡在二进制图像上略有重叠,我们使用函数cv2.erode()将它们分开。腐蚀是一种形态学操作,可减小图像中对象的大小。它可用于去除小的白噪声,以及分离连接的对象。

image = cv2.imread(r'bubbles.jpeg', cv2.IMREAD_UNCHANGED)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_ , mask = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)
mask = cv2.erode(mask, np.ones((7, 7), np.uint8))

使用轮廓提取对象边界

    下一步是在二值图像中查找对象。我们cv2.findContours()在二值图像上使用函数来检测对象的边界。轮廓定义为构成图像中对象边界的连续曲线。当使用cv2.RETR_EXTERNAL标志时,仅返回最外层的轮廓。该算法输出轮廓列表,每个轮廓代表图像中单个对象的边界。

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

过滤轮廓并提取平均颜色

    为了去除不代表气泡的轮廓,我们将迭代生成的轮廓并仅选择面积较大的轮廓(大于 3000 像素)。这将使我们能够隔离气泡的轮廓并丢弃任何较小的物体,例如字母或背景的一部分。

filtered_contours = []
df_mean_color = pd.DataFrame()
for idx, contour in enumerate(contours):
    area = int(cv2.contourArea(contour))

    # if area is higher than 3000:
    if area > 3000:
        filtered_contours.append(contour)
        # get mean color of contour:
        masked = np.zeros_like(image[:, :, 0])  # This mask is used to get the mean color of the specific bead (contour), for kmeans
        cv2.drawContours(masked, [contour], 0, 255, -1)

        B_mean, G_mean, R_mean, _ = cv2.mean(image, mask=masked)
        df = pd.DataFrame({'B_mean': B_mean, 'G_mean': G_mean, 'R_mean': R_mean}, index=[idx])
        df_mean_color = pd.concat([df_mean_color, df])

    为了找到每个气泡的平均颜色,我们首先通过在黑色图像上用白色绘制气泡轮廓来为每个气泡创建一个蒙版。然后,我们将使用该cv2.mean()函数使用原始图像和气泡的蒙版计算气泡的平均蓝色、绿色和红色 (BGR) 通道值。每个气泡的平均 BGR 值存储在 pandas DataFrame 中。

使用 K-means 算法对相似颜色进行聚类

    最后,我们将应用 K 均值聚类算法将颜色相似的气泡分组在一起。我们将使用轮廓的平均颜色值作为库KMeans中算法的输入数据sklearn。n_clusters超参数指定算法要创建的聚类数。在本例中,由于气泡有 6 种颜色,我们将该值设置为 6。

    K 均值算法是一种流行的聚类方法,可用于将相似的数据点分组在一起。该算法的工作原理是将一组数据点作为输入,并将它们分成指定数量的聚类,每个聚类由一个质心表示。质心被初始化为数据空间内的随机位置,算法迭代地将每个数据点分配给由最接近的质心所代表的聚类。一旦所有数据点都被分配到一个聚类,质心就会更新为数据点在其聚类中的平均位置。这个过程重复进行,直到质心收敛到稳定的位置,数据点不再被重新分配到不同的聚类。通过使用 K 均值算法并以每个气泡的平均 BGR 值作为输入,我们可以将具有相似颜色的气泡分组在一起。

    一旦KMeans类初始化完毕,fit_predict就会调用该方法执行聚类。该fit_predict方法返回每个对象的聚类标签,然后将其分配给数据集中的新“标签”列。这使我们能够识别哪些数据点属于哪个聚类。

km = KMeans( n_clusters=6)
df_mean_color['label'] = km.fit_predict(df_mean_color)

    draw_segmented_objects然后定义函数来创建一个新的蒙版图像,其中包含相同颜色的气泡。首先创建一个二进制蒙版:在黑色图像上用白色绘制所有具有相同标签的气泡的轮廓。然后,使用来自的函数将原始图像与蒙版组合,bitwise_and得到cv2一个只有具有相同标签的气泡可见的图像。为方便起见,使用函数在图像上绘制每种颜色的气泡数量cv2.putText()。

def draw_segmented_objects(image, contours, label_cnt_idx, bubbles_count):
    mask = np.zeros_like(image[:, :, 0])
    cv2.drawContours(mask, [contours[i] for i in label_cnt_idx], -1, (255), -1)
    masked_image = cv2.bitwise_and(image, image, mask=mask)
    masked_image = cv2.putText(masked_image, f'{bubbles_count} bubbles', (200, 1200), cv2.FONT_HERSHEY_SIMPLEX,
                        fontScale = 3, color = (255, 255, 255), thickness = 10, lineType = cv2.LINE_AA)
    return masked_image

    对每组具有相同标签的气泡调用该draw_segmented_objects函数,以生成每种颜色的蒙版图像。可以通过计算按颜色分组后的 DataFrame 中的行数来确定每种颜色的珠子数量。

img = image.copy()
for label, df_grouped in df_mean_color.groupby('label'):
    bubbles_amount = len(df_grouped)
    masked_image = draw_segmented_objects(image, contours, df_grouped.index, bubbles_amount)
    img = cv2.hconcat([img, masked_image])

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB) )

结果图:

总 结

    使用 K-means 聚类进行颜色分割可以成为一种强大的工具,可根据颜色识别和量化图像中的对象。在本教程中,我们演示了如何使用 K-means 算法以及 OpenCV 和 scikit-learn 来执行颜色分割并计算图像中每种颜色的对象数量。此技术可应用于各种需要根据颜色分析和分类图像中对象的场景。

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值