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

时间:2019-04-05 23:11:56

标签: python image opencv image-processing python-imaging-library

我有一系列有趣的细胞生长图像,我的公司正在尝试以编程方式量化盘子中有多少细胞,而没有多少。

我在下面提供了一个图像,作为我拥有的示例。任何封闭区域都是细胞生长,而其他非黑色区域则不是。

我尝试了几种不同的过滤器和泛洪算法在细胞生长区域之间进行搜索,但是在图像处理方面经验不足并没有取得太大的成功。这是我从互联网上整理来的一些代码,用于计算黑色像素的数量。但是,它是如此之慢,我认为最好向所有人询问。

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)

enter image description here

编辑

我在Google周围搜索并管理了几件事。首先,我有一个高效的黑色像素计算器。其次,我有一个细胞生长区域的入门计算器。谁会知道如何计算下面的封闭黄色边界或完全有不同的解决方案?

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 个答案:

答案 0 :(得分:2)

一种简单的方法是将所有黄色变成白色,将所有紫色变成黑色。然后获取图像的均值,然后乘以宽度和高度。这将计算出黄色的像素数(即面积)。也许您应该将图像保存为灰度或二进制格式,而不是对其进行着色。例如,这是使用ImageMagick的一种方法。但是您可能可以使用Python Wand,OpenCV或scipy(skimage)进行相同操作。

请注意,我已经下载了您的图片并裁剪了该图片以删除其他标记。因此,您将需要使用完整图像。

init(bytes:length:encoding:)

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

答案 1 :(得分:1)

由于您的细胞生长呈非连续形状,因此我们无法使用形状检测器。因此,另一种选择是对细胞进行斑点检测,然后找到面积以获得定量数。为了检测斑点,我们首先将图像变成灰度并使用Canny edge detection来帮助我们隔离细胞生长。

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)