如何计算图像中非连续形状的内部面积?

3
我有一系列关于细胞生长的有趣图片,我的公司正在尝试以编程的方式量化培养皿中含有多少细胞以及不含有多少细胞。
我在下面包含了一个示例图像。任何被圈起来的区域都是细胞生长区域,而其他非黑色区域则不是。
我尝试了几种不同的过滤器和洪水填充算法来搜索细胞生长区域之间的差异,但由于对图像处理缺乏经验,所以并没有取得太大的成功。这里有一些我从互联网上找到的代码,用于计算黑色像素的数量。然而,它运行速度非常慢,所以我认为最好请教各位。
image = Image.open("Images/24Hour/HB15_2.jpg")
image = image.getdata()

def is_black_enough(pixel):
    r, g, b = pixel
    return r < 10 and g < 10 and b < 10
w, h = np.asarray(image).shape
black_pixels = 0
for pixel in image:
    if is_black_enough(pixel)==True:
        black_pixels+=1
        print(black_pixels)
black_pixels/(w*h)

在此输入图片描述

编辑

我在网上搜索到了一些有用的东西。首先,我有一个高效的黑像素计算器。其次,我有一个开始计算细胞生长区域的计算器。有人知道如何计算下面所示的黄色边界或有完全不同的解决方案吗?

img = Image.open("Images/24Hour/HB15_2.jpg")
img = img.convert('L')
img = np.asarray(img)
img = 1 * (img < 130) * (img > 90)
m,n = img.shape
plt.figure(figsize=(20,10))
plt.imshow(img)

enter image description here

2个回答

2
一种简单的方法是将所有黄色变为白色,将所有紫色变为黑色。然后获取图像平均值并乘以宽度和高度。这将计算出黄色像素的数量(即面积)。也许你应该将图像保存为灰度或二进制而不是着色。以下是使用ImageMagick的示例方法。但是你可能可以使用Python Wand、OpenCV或scipy (skimage)来完成相同的操作。
请注意,我已经下载了您的图像并裁剪了它以去除其他标记。因此,您需要使用完整的图像。

enter image description here

convert img_sub.png -alpha off -fuzz 10% -fill black -opaque "rgb(68,1,84)" -fill white +opaque black +write binary.png -format "%[fx:mean*w*h]\n" info:

58464

这是保存的二进制图像。

enter image description here


2
由于您的细胞生长形状不连续,我们无法使用形状检测器。因此,另一个选择可能是对细胞进行斑点检测,然后找到面积以获得定量数字。为了检测斑点,我们首先将图像转换为灰度,并使用Canny边缘检测来帮助我们隔离细胞生长。

enter image description here

接下来,我们可以获取所有轮廓,并使用cv2.contourArea()找到每个轮廓的面积。我们将每个单独的轮廓面积相加以获得总面积。这是一种简单的方法,不是完美的方法,但它可以捕获大多数斑点。

enter image description here

import cv2
import numpy

def grab_contours(cnts):
    # OpenCV v2.4, v4-official
    if len(cnts) == 2:
        return cnts[0]
    # OpenCV v3
    elif len(cnts) == 3:
        return cnts[1]

image = cv2.imread("test.png")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edged = cv2.Canny(gray, 120, 255, 1)
cv2.imshow("canny", edged)

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)
cnts = grab_contours(cnts)

contour_image = edged.copy()
area = 0

for c in cnts:
    area += cv2.contourArea(c) 
    cv2.drawContours(contour_image,[c], 0, (100,5,10), 3)

print(area)
cv2.putText(contour_image, str(area), (50,50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (100,255,100), 2)
cv2.imshow("area", contour_image)
cv2.waitKey(0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接