[Python与图像处理]利用Python与Kmeans聚类分析图像主色彩

如何使用OpenCV,Python和k-means聚类算法来查找图像中最主要的颜色

  该任务可用于分析一张优秀摄影作品的色彩分布,并建立色卡图,将其用于本地调色。
K-Means聚类,那么k-means究竟是什么意思呢?
  K-means是一种聚类算法。目标是将n个数据点分成k个簇。 n个数据点中的每一个都将被分配给具有最接近平均值的簇。每个簇的平均值称为“质心”或“中心”。
  总的来说,应用k均值产生原始n个数据点的k个单独的簇。特定集群内的数据点被认为与属于其他集群的数据点彼此“更相似”。
  在我们的任务中,我们将聚类RGB图像的像素强度。给定MxN大小的图像,我们因此具有MxN个像素,每个像素由三个分量组成:红色,绿色和蓝色。我们将这些MxN像素视为我们的数据点,并使用k-means对它们进行聚类。
  k-means的一个条件是我们需要指定我们想要提前生成的集群数量,有些算法会自动选择k的最佳值,但在这里不做讨论。
具体的效果如下图所示:

代码如下所示,需要指定图像位置与聚类类别数目:

#coding:utf-8
#*********************************************************************************************************
'''
说明:利用python/k-means聚类提取图像中的主要色彩,并建立色彩,可用于摄影调色中的图像色彩分析
算法思路:
        1)加载RGB图像,并转换为Kmeans可聚类的数据形式;
        2)设置聚类中心数目,采用Kmeans聚类;
		3)设置色卡图像,显示聚类结果
具体参数:图像resize到(640, 640*ratio),clusters=4
'''
import cv2
import numpy as np
import argparse
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
ap.add_argument("-c", "--clusters", required = True, type = int,help = "# of clusters")
args = vars(ap.parse_args())
    
if __name__ == '__main__':
    print( '[INFO] 读取图像......' )
    img = cv2.imread( args[ 'image' ] )
    if ( img is None ):
        print( ' Not read img. ' )
    #获取初始图像的宽高比例,以便resize不改变图像比例
    ratio = img.shape[0] / img.shape[1]
    img_resize = cv2.resize( img, ( 640, int( 640*ratio ) ), interpolation=cv2.INTER_CUBIC )
    #将Opencv中图像默认BGR转换为通用的RGB格式
    img_rgb = cv2.cvtColor( img_resize, cv2.COLOR_BGR2RGB )
    (height, width, channels) = img_rgb.shape
    #将图像数据转换为需要进行Kmeans聚类的Data
    img_data = img_rgb.reshape( height*width, channels )
    
    print( '[INFO] Kmeans 颜色聚类......' )
    #调用sklearn中Kmeans函数
    kmeans = KMeans( n_clusters = args[ 'clusters' ] )
    kmeans.fit(img_data)
    #建立颜色与标签的对应字典
    color_label = {}
    for i in range( len( kmeans.cluster_centers_ ) ):
        color_label[i] = kmeans.cluster_centers_[i]
    print( '    颜色以及其对应的标签为: {}'.format( color_label ) )
    #计算聚类结果, 各颜色及其所含像素数目 
    color_num = {} 
    for m in range( len( np.unique( kmeans.labels_ ) ) ):
        print( np.sum( kmeans.labels_ == m ) )
        print( color_label[m] )#标签m对应的色彩
        color_num[ np.sum( kmeans.labels_ == m ) ] =  color_label[m] 
    print( '    色彩排序前字典映射为: {}'.format( color_num ) )
    color_num_sorted = sorted( color_num.items(), key = lambda x:x[0], reverse = True )
    print( '    色彩排序后字典映射为: {}'.format( color_num_sorted) )
    color_num_ratio = []
    for i in range( len( color_num_sorted )   ):
        color_num_ratio.append( color_num_sorted[i][0] )
    color_num_ratio = color_num_ratio / np.sum( color_num_ratio )
    print( '    色彩数目求取比例之后: {}'.format( color_num_ratio ) )
    
    print( '[INFO] 显示色卡图像......' )
    #创建带有色卡的图像
    color_card = np.zeros( shape = ( height, width + 100, 3 ), dtype = np.int32 )
    #图像左侧区域复制源图像
    for i in range(height):
        for j in range(width):
            color_card[i][j] = img_rgb[i][j]
    #图像右侧显示色卡
    start = 0
    for i in range( len( kmeans.cluster_centers_ ) ):
        color = color_num_sorted[i][1]
        row_start = int ( color_num_ratio[i] * height )
        #由于前面的比例为小数,转为Int导致最后部分区域没有色彩,采用最后一种颜色进行填充
        if i == len( kmeans.cluster_centers_ ) - 1:
            color_card[start:, width:width+100] = color
        color_card[start: start +row_start, width:width+100] = color
        start += row_start
        
    plt.imshow( color_card )
    plt.show()
  • 8
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
以下是一个基于PythonOpenCV的细胞聚类分析代码的示例: ```python import cv2 import numpy as np # 加载图像 image = cv2.imread("cell_image.jpg") # 转换图像为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用中值滤波,以减少噪声 gray = cv2.medianBlur(gray, 5) # 二值化图像 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # 执行形态学操作,以去除小的噪点和连接细胞 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) # 执行形态学操作,以分离连接的细胞 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15)) morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel) # 执行连通组件分析 ret, labels = cv2.connectedComponents(morph) # 创建一个具有与输入图像相同尺寸的空白图像 output = np.zeros_like(image) # 遍历所有连通组件,并为每个组件分配一个随机颜色 for i in range(1, ret): mask = labels == i output[mask] = np.random.randint(0, 255, 3) # 显示结果 cv2.imshow("Output", output) cv2.waitKey(0) ``` 上述代码中,我们首先加载输入图像,并将其转换为灰度图像。然后,我们应用中值滤波来平滑图像,以减少噪声。接下来,我们使用Otsu阈值法将图像二值化。然后,我们执行一系列形态学操作,以去除小噪点和连接细胞,并分离连接的细胞。最后,我们执行连通组件分析,并为每个组件分配一个随机颜色。最终,我们将输出图像显示在屏幕上。 请注意,这只是一个基本的示例代码,可能需要根据您的具体应用场景进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值