R语言:将带有规则点的图像转换为数据帧
我有许多紫外图像(*.png),每个图像都有96个“孔”,看起来像圆圈。这些井以8×12的方式布置。请参见下面的示例 在每张图像中,96个圆圈中的一些被点亮(对紫外线产生反应),而其中一些没有点亮。我想给每个圆圈一个数字,然后将它们标识为“点亮”或“未点亮”(带有预定义的截止线) 你认为在R中实现这一点最简单的方法是什么? 我一直在玩软件包R语言:将带有规则点的图像转换为数据帧,r,image,identification,R,Image,Identification,我有许多紫外图像(*.png),每个图像都有96个“孔”,看起来像圆圈。这些井以8×12的方式布置。请参见下面的示例 在每张图像中,96个圆圈中的一些被点亮(对紫外线产生反应),而其中一些没有点亮。我想给每个圆圈一个数字,然后将它们标识为“点亮”或“未点亮”(带有预定义的截止线) 你认为在R中实现这一点最简单的方法是什么? 我一直在玩软件包imager,但没有多大成功 还有一点需要注意的是:并不是我所有的图像都有相同的放大率(也就是说,在不同的文件中,圆圈的大小并不总是相同的,但在一个文件中,它
imager
,但没有多大成功
还有一点需要注意的是:并不是我所有的图像都有相同的放大率(也就是说,在不同的文件中,圆圈的大小并不总是相同的,但在一个文件中,它们的大小大致相同)
源代码(“https://bioconductor.org/biocLite.R")
生物晶石(“EBImage”)
图书馆(电子图像)
fn=您的文件
img这可能有点晚了,但这个问题解决了我经常面临的一个问题。也许其他人会对一个更普遍的解决办法感兴趣。下面是一个建议的解决方案,它使用了EBImage
包的一些其他功能,并与用户交互。它可以应用于任何几何形状的多井盘
# EBImage needs to be available
if (!require(EBImage)) {
source("https://bioconductor.org/biocLite.R")
biocLite("EBImage")
library(EBImage)
}
# Read the image and examine it
fn <- file.choose() # select saved image
img <- readImage(fn)
img <- channel(img, "gray") # gray scale for simplicity
plot(img)
# Define the geometry of the plate
nx <- 12 # number of columns
ny <- 8 # number of rows
nwells <- seq_len(nx*ny) # index of each well in plate
# Use locator() to interactively define the upper left "corner"
# of the top left and bottom right well with a red mark to confirm
p <- locator(2, type = "p", col = 2)
#使用computeFeatures函数族测量平均强度
M b.平均b.sd b.mad b.q001 b.q005 b.q05 b.q095 b.q099
> 1 0.2800 0.2114 0.18605 0.04706 0.05882 0.2118 0.7451 0.8959
> 2 0.1778 0.0981 0.09303 0.05490 0.06275 0.1569 0.3882 0.4745
> 3 0.1817 0.1028 0.10465 0.05098 0.05882 0.1569 0.4039 0.4824
> 4 0.1854 0.1029 0.10465 0.05490 0.06275 0.1608 0.3961 0.4880
> 5 0.3300 0.2425 0.23256 0.05490 0.06667 0.2510 0.7882 0.9451
> 6 0.1967 0.1076 0.11047 0.05490 0.06275 0.1765 0.4157 0.5216
#提取平均强度并使用简单的条形图进行检查
val 1 A 1 0.2800真
>2 A 20.1778错误
>3 A 30.1817错误
>4 A 4 0.1854错误
>5 A 5 0.3300真
>6 A 6 0.1967错误
#并进行视觉确认…或检查背景值
绘图(img)
文本(xx[df$正]、yy[df$正]、“+”、col=2、cex=2)
您能举几个其他尺寸的例子吗?油井是否始终采用8x12布置?图像有时可以旋转吗?谢谢你,马克。是的,(i)井始终处于8x12排列,(ii)图像始终处于相同的方向,(iii)通过“其他尺寸”,我的意思是,有时拍摄照片时的变焦距离会更远,而圆圈的比例保持不变。这有意义吗?我认为我最初的方法是修剪边缘周围多余的黑色,然后将剩下的部分调整为标准尺寸。然后我会有一个同样大小的面具,上面有所有96口井。然后把面具贴在标准化的图像上,数一数。谢谢你!你的代码很神奇!!!!我该如何感谢你,当我使用这个时,什么是最好的方式来信任你?后续问题:我是EBImage的新手,所以请原谅一个可能很简单的问题。我在第二张图像上运行了你的脚本,检测功能关闭了。我还在努力理解你的剧本。我要改变哪个部分来调整这个?任何指针都会有帮助。我已经非常感谢你了!!!第二幅图:嘿,斯巴鲁,你可以在每一步之后运行display(img)
,看看结果是否合理。我添加了一些评论,以便您能够了解我的想法。我还编辑了代码以删除图像的外部5px,因为您的第二张图像的右侧有一条白线,这会混淆bwlabel()
。关于评分:我认为堆栈溢出内容由sa抄送。如果你要发表一篇论文,你可以在致谢信中给我起个名字:)嗨,斯巴鲁。我在5月5日添加的答案与您链接中的备选图像一致。它期望板的图像与图像边界平行。如果不是,您可以调整代码以适应,或者更好地旋转图像使其平行。
# EBImage needs to be available
if (!require(EBImage)) {
source("https://bioconductor.org/biocLite.R")
biocLite("EBImage")
library(EBImage)
}
# Read the image and examine it
fn <- file.choose() # select saved image
img <- readImage(fn)
img <- channel(img, "gray") # gray scale for simplicity
plot(img)
# Define the geometry of the plate
nx <- 12 # number of columns
ny <- 8 # number of rows
nwells <- seq_len(nx*ny) # index of each well in plate
# Use locator() to interactively define the upper left "corner"
# of the top left and bottom right well with a red mark to confirm
p <- locator(2, type = "p", col = 2)
# Calculate distance between wells and create coordinates in xx, yy
dx <- abs(diff(p$x))/(nx - 1)
dy <- abs(diff(p$y))/(ny - 1)
ix <- (nwells - 1) %% nx # index for rows
iy <- (nwells - 1) %/% nx # index for columns
xx <- ix*dx + p$x[1] # the first point must be the upper left well
yy <- iy*dy + p$y[1]
# Confirm the calculated coordinates with red dots
points(xx, yy, pch = 16, col = 2)
# First a pure black image
mask <- Image(0, dim = dim(img)) # black image same size as image
# Add white rectangles allowing 5% space between rectangles
for (x in xx)
for (y in yy)
mask[x:(x + 0.95*dx), y:(y + 0.95*dy)] <- 1
# Convert image to an 'object mask'
mask <- bwlabel(mask)
# One could draw circular masks with drawCircle() but this is very,
# very inefficient and doesn't improve the quality of the data
#
# mask <- Image(0, dim = dim(img)) # black image same size as image
# for (x in xx)
# for (y in yy)
# mask <- drawCircle(mask, x + 0.5*dx, y + 0.5*dy,
# radius = 0.95*dx/2, col = 1, fill = TRUE)
# Show mask on top of original image
plot(paintObjects(mask, img, col = "white"))
# Use the computeFeatures family of functions to measure the mean intensity
M <- computeFeatures.basic(mask, img) # a matrix of values is returned
options(digits = 4)
head(M)
> b.mean b.sd b.mad b.q001 b.q005 b.q05 b.q095 b.q099
> 1 0.2800 0.2114 0.18605 0.04706 0.05882 0.2118 0.7451 0.8959
> 2 0.1778 0.0981 0.09303 0.05490 0.06275 0.1569 0.3882 0.4745
> 3 0.1817 0.1028 0.10465 0.05098 0.05882 0.1569 0.4039 0.4824
> 4 0.1854 0.1029 0.10465 0.05490 0.06275 0.1608 0.3961 0.4880
> 5 0.3300 0.2425 0.23256 0.05490 0.06667 0.2510 0.7882 0.9451
> 6 0.1967 0.1076 0.11047 0.05490 0.06275 0.1765 0.4157 0.5216
# Extract the mean intensity and examine with a simple barplot
val <- M[,"b.mean"]
barplot(val)
# Combination of median and mad provides a fair estimate of the cutoff
bgnd <- median(val) + mad(val)
abline(h = bgnd, col = 2)
# Collect values in labeled data.frame and score the values
df <- data.frame(row = factor(LETTERS[iy+1]), column = factor(ix+1),
val = val, positive = val > bgnd)
head(df)
> row column val positive
> 1 A 1 0.2800 TRUE
> 2 A 2 0.1778 FALSE
> 3 A 3 0.1817 FALSE
> 4 A 4 0.1854 FALSE
> 5 A 5 0.3300 TRUE
> 6 A 6 0.1967 FALSE
# And for visual confirmation...or to check the background value
plot(img)
text(xx[df$positive], yy[df$positive], "+", col = 2, cex = 2)