如何在 PIL 中选择与图像边缘相邻的所有黑色像素?

Joe*_*e B 5 python opencv image-processing computer-vision python-imaging-library

我有一组培养皿图像,不幸的是,它们的质量不是最高的(下面的示例,轴不是图像的一部分)。 菜1 我正在尝试选择背景并使用以下命令计算其面积(以像素为单位):

image = Image.open(path)
black_image = 1 * (np.asarray(image.convert('L')) < 12)
black_region = black_image.sum()
Run Code Online (Sandbox Code Playgroud)

这会产生以下结果:

在此输入图像描述

如果我对黑色像素的选择更严格,我会错过其他图像中的像素,如果我更宽松,我最终会选择太多的培养皿本身。有没有办法只能选择亮度值小于 12 并且与边缘相邻的像素?我也对 openCV 解决方案持开放态度。

Han*_*rse 5

希望我没有过度简化问题,但从我的角度来看,使用 OpenCV 进行简单的阈值处理、形态学操作,findContours应该可以完成这项工作。

请参阅以下代码:

import cv2
import numpy as np

# Input
input = cv2.imread('images/x0ziO.png', cv2.IMREAD_COLOR)

# Input to grayscale
gray = cv2.cvtColor(input, cv2.COLOR_BGR2GRAY)

# Binary threshold
_, gray = cv2.threshold(gray, 20, 255, cv2.THRESH_BINARY)

# Morphological improvements of the mask
gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
gray = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11)))

# Find contours
cnts, _ = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Filter large size contours; at the end, there should only be one left
largeCnts = []
for cnt in cnts:
    if (cv2.contourArea(cnt) > 10000):
        largeCnts.append(cnt)

# Draw (filled) contour(s)
gray = np.uint8(np.zeros(gray.shape))
gray = cv2.drawContours(gray, largeCnts, -1, 255, cv2.FILLED)

# Calculate background pixel area
bgArea = input.shape[0] * input.shape[1] - cv2.countNonZero(gray)

# Put result on input image
input = cv2.putText(input, 'Background area: ' + str(bgArea), (20, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.0, (255, 255, 255))

cv2.imwrite('images/output.png', input)
Run Code Online (Sandbox Code Playgroud)

中间的“掩模”图像如下所示:

面具

并且,最终输出如下所示:

输出