【问题标题】:How to delete objects (cells) touching the image boundaries?如何删除接触图像边界的对象(单元格)?
【发布时间】:2021-07-27 15:43:33
【问题描述】:

我有一张我已经阈值化的细胞图像,并且还检测到了这些细胞(使用 cv2)。

我想创建一个值为 True 或 False 的数组,以显示每个组件是否触及图像的边界(True)或不(False)。

import cv2 as cv

# Read the image you want connected components of, IN BLACK AND WHITE
img = cv.imread('../images/37983_ERSyto/cellpaintingfollowup-reimage_a01_s1_w26ae36209-938b-45ef-b166-3aba3af125df.tif', cv.IMREAD_GRAYSCALE)

seed_pt = (100, 800) #point in the background
fill_color = 0
mask = np.zeros_like(img)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (6, 5))
for th in range(7,70):
    #creates a copy of the mask:
    prev_mask = mask.copy()
    #thresholded image:
    mask = cv.threshold(img, th, 22331, cv.THRESH_BINARY)[1]
    #FloodFill: fill a connected component starting from the seed point with the specified color.
    mask = cv.floodFill(mask, None, seed_pt, fill_color)[1]
    #cv.bitwise: calculates the per-element bit-wise disjunction of two arrays or an array and a scalar. Superposition of thresholded images
    mask = cv.bitwise_or(mask, prev_mask)
    #clean speckles
    mask = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel)
   

#compute the connected components labeled image of boolean image and also produce a statistics output for each label

connectivity = 8  #You need to choose 4 or 8 for connectivity type.

#OBTAIN FEATURE OF THE AREA IN PIXELS OF THE CELLS
stats = cv.connectedComponentsWithStats(mask, connectivity, cv.CV_32S)[2]
label_area = stats[1:, cv.CC_STAT_AREA] #we dont include the first element because it represents the area of the background

#OBTAIN FEATURES OF THE CENTROID POSITION
centroids = cv.connectedComponentsWithStats(mask, connectivity, cv.CV_32S)[3]
label_centroids_x = centroids[1:, 0] #dont include the first element because it represents the background
label_centroids_y = centroids[1:,1]

#HIGHT: The vertical size of the bounding box.
label_hight = stats[1:, cv.CC_STAT_HEIGHT]
#WIDTH: The horizontal size of the bounding box.
label_width = stats[1:, cv.CC_STAT_WIDTH]


#TOUCHING IMAGE BOUNDARIES: is the component touching the boundaries of the matrix/image?--> True/False

label_bounary = #boolean array

我最初考虑搜索每个组件的轮廓并定义一些限制,但是我无法理解每个组件的标签是如何存储的,因此我无法选择所需的组件。

这是图片:

非常感谢您。

【问题讨论】:

  • 我会得到轮廓及其边界框,然后测试边界框以查看是否有任何边 = width-1 或 height-1 图像。在边界框中找到 x 的最小值和 y 的最小值并针对 0 进行测试。找到 x 的最大值和 y 的最大值并针对宽度-1 和高度-1 进行测试。

标签: python opencv image-processing object-detection connected-components


【解决方案1】:

使用您的代码(感谢您的评论),我得到了这个面具。可能不一样,因为 .jpg 压缩会弄乱图像(它不是无损压缩方案)

@fmw42 完全正确,他在我完成代码之前发表了评论

import cv2 as cv
import numpy as np

# Read the image you want connected components of, IN BLACK AND WHITE
img = cv.imread('cells.jpg', cv.IMREAD_GRAYSCALE)

seed_pt = (100, 800) #point in the background
fill_color = 0
mask = np.zeros_like(img)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (6, 5))
for th in range(7,70):
    #creates a copy of the mask:
    prev_mask = mask.copy()
    #thresholded image:
    mask = cv.threshold(img, th, 22331, cv.THRESH_BINARY)[1]
    #FloodFill: fill a connected component starting from the seed point with the specified color.
    mask = cv.floodFill(mask, None, seed_pt, fill_color)[1]
    #cv.bitwise: calculates the per-element bit-wise disjunction of two arrays or an array and a scalar. Superposition of thresholded images
    mask = cv.bitwise_or(mask, prev_mask)
    #clean speckles
    mask = cv.morphologyEx(mask, cv.MORPH_OPEN, kernel)

# show mask
cv.imshow("Mask", mask);
cv.waitKey(0);

# contours OpenCV 3.4, if you're using OpenCV 2 or 4, it returns (contours, _)
_, contours, _ = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_NONE);

# get bounds and check if they're touching edge
height, width = mask.shape[:2];
touching_edge = []; # boolean array, index matches the contours list
for con in contours:
    # get bounds
    x, y, w, h = cv.boundingRect(con);

    # check if touching edge
    on_edge = False;
    if x <= 0 or (x + w) >= (width - 1):
        on_edge = True;
    if y <= 0 or (y + h) >= (height - 1):
        on_edge = True;

    # add to list
    touching_edge.append(on_edge);

# mark the contours on the edge
colored = cv.cvtColor(mask, cv.COLOR_GRAY2BGR);
for index in range(len(contours)):
    if touching_edge[index]:
        # drawContours(image, contour_list, index, color, thickness) # -1 is filled
        cv.drawContours(colored, contours, index, (50,50,200), -1);

# show
cv.imshow("Colored", colored);
cv.waitKey(0);

【讨论】:

  • @Ian Chu 感谢您详细介绍这个概念。
【解决方案2】:

如果你愿意使用scikit-image,你可以试试clear_border

>>> import numpy as np
>>> from skimage.segmentation import clear_border
>>> labels = np.array([[0, 0, 0, 0, 0, 0, 0, 1, 0],
...                    [1, 1, 0, 0, 1, 0, 0, 1, 0],
...                    [1, 1, 0, 1, 0, 1, 0, 0, 0],
...                    [0, 0, 0, 1, 1, 1, 1, 0, 0],
...                    [0, 1, 1, 1, 1, 1, 1, 1, 0],
...                    [0, 0, 0, 0, 0, 0, 0, 0, 0]])
>>> clear_border(labels)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 1, 1, 1, 1, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-14
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 2018-11-14
    相关资源
    最近更新 更多