Menu
CoddyTech

图像颜色

本课属于 Coddy Machine Learning 学习旅程的“无监督学习”单元。第 41 课,共 51 课。

丝网印刷工只有几种油墨,没有数百万种颜色。k-means 会为任意图片挑选最合适的几种颜色:

并排展示的两张日落图片。左边是原图:天空从紫色渐变到橙色,黄色的太阳,深色的海面上倒映着橙色。右边是同一场日落,但只有 4 种纯色

彩色图像的形状为 (rows, columns, 3):每个像素包含红、绿、蓝三个通道,每个通道的值都在 0 到 1 之间。通过一次 reshape,就可以将像素转换为数据:

一张 2×3 的图像,包含橙色、黄色和深蓝色像素,箭头指向一个包含 6 行的表格,每行对应一个像素,并包含该像素的红、绿、蓝值

pixels = image.reshape(-1, 3)
km = KMeans(n_clusters=4, n_init=10, random_state=0).fit(pixels)
poster = km.cluster_centers_[km.labels_].reshape(image.shape)
ax.imshow(poster)

每个中心都对应一种颜色。用标签对中心进行索引,就能为每个像素赋予其中心的颜色;reshape 会将各行折叠回一张图片。

challenge icon

挑战

中等

一家海报工作室用 k 种油墨丝网印刷一幅山间湖泊图。起始代码绘制了 40 × 60 的 image,读取 k,并设置好带标题的图表。

  1. 将图像转换为每个像素占一行的形式,并用 k-means 找出 k 种颜色。
  2. 用中心颜色重新绘制每个像素,再将各行折回成一幅图。
  3. 在 ax 上绘制图像并显示出来。

例如,这幅用 5 种油墨绘制的日落图:

用 5 种纯色重新绘制的日落图,标题为“5 种油墨”:李子色和玫瑰色的天空色带、橙色色带、黄色太阳、带有橙色条纹的海军蓝色海面

你的程序不会打印任何内容:Coddy 会描述你的图像和所用的油墨。然后试试其他 k 值:k 取多少时,红色小船会拥有自己的油墨颜色?

亲手试试

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans


# 绘制一幅 40 × 60 的山间湖泊图:画面中有天空、雪峰、森林、湖水和一艘红船
def paint_lake():
    image = np.zeros((40, 60, 3))
    for r in range(40):
        for c in range(60):
            if 30 <= r <= 31 and 10 <= c <= 17 - (r - 30) * 2:
                image[r, c] = [0.8, 0.15, 0.1]
            elif r >= 27:
                t = (r - 27) / 12
                image[r, c] = [0.1, 0.45 - 0.2 * t, 0.65 - 0.2 * t]
            elif r >= 21:
                image[r, c] = [0.1, 0.35 + 0.05 * (c % 3), 0.15]
            elif r >= abs(c - 34) + 4 and r < 10:
                image[r, c] = [0.95, 0.95, 0.97]
            elif r >= abs(c - 34) + 4:
                image[r, c] = [0.45, 0.42, 0.45]
            else:
                image[r, c] = [0.55 + r / 50, 0.75 + r / 120, 0.95]
    return np.round(image, 3)


# 不要修改下面的代码
image = paint_lake()
k = int(input())
fig, ax = plt.subplots()
ax.set_title(f"{k} inks")
ax.axis("off")

# 在下方编写你的代码
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

无监督学习中的所有课

自己练习: Python 在线编译器