如何在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




