You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在R中计算图像特定颜色占比并识别多色液滴?

嘿Timo,我来帮你搞定这个图像液滴统计的问题!下面是一步步的解决方案,完全贴合你提到的研究方法和需求:

基于密度曲线的颜色阈值确定与液滴统计方案

第一步:预处理数据并可视化颜色特征的密度分布

首先我们需要处理计算过程中产生的NaN值(比如纯黑色像素会导致white=0,除法后出现异常),然后通过密度曲线直观区分背景和目标液滴的颜色特征分界:

# 过滤无效像素(排除NaN和white=0的情况)
valid_pixels <- !is.na(excess_blue) & white > 0
excess_blue_clean <- excess_blue[valid_pixels]

# 用base R绘制过蓝值的密度曲线
plot(density(excess_blue_clean), 
     main = "Density of Excess Blue Values", 
     xlab = "Excess Blue", 
     col = "darkblue", 
     lwd = 2)
# 先手动标记一个阈值示例(后续可以自动优化)
abline(v = 0.2, col = "red", lty = 2)

如果想要更美观的可视化,也可以用ggplot2

library(ggplot2)
ggplot(data.frame(excess_blue = excess_blue_clean), aes(x = excess_blue)) +
  geom_density(fill = "darkblue", alpha = 0.3) +
  geom_vline(xintercept = 0.2, color = "red", linetype = "dashed") +
  labs(title = "Density Distribution of Excess Blue", x = "Excess Blue Value") +
  theme_minimal()

第二步:自动确定阈值(替代手动目测)

如果不想手动判断阈值,可以用峰检测工具自动找到密度曲线的谷值(背景和液滴的分界点):

library(pracma)

# 获取密度曲线的数值点
dens <- density(excess_blue_clean)
# 找到密度的峰值(局部最大值)
peaks <- findpeaks(dens$y, sortstr = TRUE)
# 提取峰值对应的x轴值并排序
peak_x <- dens$x[peaks[,2]]
peak_x_sorted <- sort(peak_x)
# 找到两个峰值之间的谷值位置
valley_idx <- which(dens$x > peak_x_sorted[1] & dens$x < peak_x_sorted[2])
blue_threshold <- dens$x[valley_idx[which.min(dens$y[valley_idx])]]

# 重新绘制曲线并标记自动阈值
plot(density(excess_blue_clean), 
     main = "Excess Blue Density with Auto Threshold", 
     xlab = "Excess Blue", 
     col = "darkblue", 
     lwd = 2)
abline(v = blue_threshold, col = "green", lty = 2, lwd = 2)

第三步:统计蓝色液滴的数量与表面积

确定阈值后,我们可以筛选出蓝色液滴的像素,计算核心指标:

# 创建蓝色液滴掩码(1=液滴像素,0=背景)
blue_mask <- rep(0, length(excess_blue))
blue_mask[valid_pixels & excess_blue > blue_threshold] <- 1

# 还原为原图像的矩阵形状
blue_mask_matrix <- matrix(blue_mask, nrow = nrow(image), ncol = ncol(image))

# 计算像素数量
blue_pixel_count <- sum(blue_mask_matrix)

# 计算表面积:需要根据图像实际分辨率调整像素尺寸
# 示例:假设图像是300dpi,1英寸=25.4mm,单像素边长=25.4/300 mm
pixel_size_mm <- 25.4 / 300 
blue_surface_area <- blue_pixel_count * (pixel_size_mm)^2

cat("蓝色液滴像素数量:", blue_pixel_count, "\n")
cat("蓝色液滴表面积:", round(blue_surface_area, 2), "mm²\n")

第四步:区分红色液滴(复用相同逻辑)

参照过蓝值的方法定义过红值,重复上述流程即可统计红色液滴:

# 计算过红值
excess_red <- (2*rcc - (gcc + bcc))
excess_red_clean <- excess_red[valid_pixels]

# 自动确定红色阈值
dens_red <- density(excess_red_clean)
peaks_red <- findpeaks(dens_red$y, sortstr = TRUE)
peak_x_red <- dens_red$x[peaks_red[,2]]
peak_x_red_sorted <- sort(peak_x_red)
valley_idx_red <- which(dens_red$x > peak_x_red_sorted[1] & dens_red$x < peak_x_red_sorted[2])
red_threshold <- dens_red$x[valley_idx_red[which.min(dens_red$y[valley_idx_red])]]

# 创建红色液滴掩码并统计
red_mask <- rep(0, length(excess_red))
red_mask[valid_pixels & excess_red > red_threshold] <- 1
red_mask_matrix <- matrix(red_mask, nrow = nrow(image), ncol = ncol(image))

red_pixel_count <- sum(red_mask_matrix)
red_surface_area <- red_pixel_count * (pixel_size_mm)^2

cat("红色液滴像素数量:", red_pixel_count, "\n")
cat("红色液滴表面积:", round(red_surface_area, 2), "mm²\n")

第五步:可视化验证结果(可选)

可以把原图像和液滴掩码放在一起对比,确认阈值是否准确:

par(mfrow = c(1,3))
# 显示原图像
plot(as.raster(image/255), main = "Original Image")
# 显示蓝色液滴区域
plot(as.raster(blue_mask_matrix), main = "Blue Droplets", col = c("white", "darkblue"))
# 显示红色液滴区域
plot(as.raster(red_mask_matrix), main = "Red Droplets", col = c("white", "darkred"))

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

火山引擎 最新活动