You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言中提取图像主色调并可视化(禁用Imager包)

图片主色调提取与可视化问题解决

问题背景

  • 需求:从目标图片提取橙色、黑色、蓝色三种主色调,并通过饼图/柱状图可视化
  • 限制:不能使用R语言的Imager包
  • 原尝试代码及输出:
image <- 'https://storage.googleapis.com/du-prd/books/images/9780385547345.jpg' |>
  readBin("raw", 1e6) |>
  jpeg::readJPEG() 

# Extract colors without checking dimensions
pixels <- as.matrix(image)
kmeans_result <- kmeans(apply(pixels, c(1, 2), mean), centers = 3)
colors <- kmeans_result$centers

输出:

[,1]
1 0.07815438
2 0.96756534
3 0.45184408

问题原因

原代码的核心错误是对RGB三通道取均值(apply(pixels, c(1,2), mean)),将彩色图像直接转换为灰度数据,导致kmeans聚类的是灰度值而非真实RGB颜色,自然无法得到预期的彩色主色调。

解决方案

直接对RGB三通道的像素数据进行聚类,步骤如下:

  1. 解析图片的RGB三维数组(jpeg::readJPEG返回[高度, 宽度, 通道]格式的三维数组)
  2. 将三维数组转换为每行对应一个像素RGB值的二维数据框
  3. 对RGB数据执行kmeans聚类(k=3)
  4. 将聚类中心的RGB值转换为可显示的颜色格式
  5. 生成可视化图表

修正后完整代码

library(jpeg)
library(ggplot2)

# 读取图片
image_url <- 'https://storage.googleapis.com/du-prd/books/images/9780385547345.jpg'
image <- readBin(image_url, "raw", 1e6) |> readJPEG()

# 将三维RGB数组转换为长格式数据框
height <- dim(image)[1]
width <- dim(image)[2]
pixels <- data.frame(
  R = as.vector(image[,,1]),
  G = as.vector(image[,,2]),
  B = as.vector(image[,,3])
)

# 执行kmeans聚类(固定随机种子保证结果可复现,nstart提升聚类稳定性)
set.seed(123)
kmeans_result <- kmeans(pixels, centers = 3, nstart = 20)

# 将聚类中心的RGB值转换为可显示的颜色(readJPEG返回0-1范围数值,需适配rgb函数要求)
cluster_colors <- rgb(kmeans_result$centers[,1], kmeans_result$centers[,2], kmeans_result$centers[,3])

# 统计每个聚类的像素占比
color_stats <- as.data.frame(table(kmeans_result$cluster))
color_stats$color <- cluster_colors
names(color_stats) <- c("Cluster", "Count", "Color")
color_stats$Percentage <- round(color_stats$Count / sum(color_stats$Count) * 100, 2)

# 饼图可视化
ggplot(color_stats, aes(x = "", y = Percentage, fill = Color)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar("y", start = 0) +
  theme_void() +
  labs(title = "图片主色调占比饼图") +
  scale_fill_identity(guide = "legend", labels = paste0(color_stats$Percentage, "%"))

# 柱状图可视化
ggplot(color_stats, aes(x = Cluster, y = Percentage, fill = Color)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(title = "图片主色调占比柱状图", x = "聚类分组", y = "占比(%)") +
  scale_fill_identity(guide = "legend", labels = paste0(color_stats$Percentage, "%")) +
  geom_text(aes(label = paste0(Percentage, "%")), vjust = -0.5)

结果说明

运行代码后会得到对应黑色、橙色、蓝色三种预期主色调的聚类结果,饼图和柱状图会直观展示每种颜色的像素占比,解决了原代码仅处理灰度值的问题。

内容的提问来源于stack exchange,提问作者Coder1990

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:07:08