numpy 对图像中的重叠细丝进行计数

iq3niunx  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(114)

我试图在二值图像中计数细丝。它们是细胞filopodia的分割掩模,并且它们经常重叠。这种重叠使得很难准确计数。
我正在尝试使用以下代码,它可以使用细化/ backbone 化和分支/端点计数,但没有运气:

def find_endpoints(img):
    (rows,cols) = np.nonzero(img)
    skel_coords = []
    for (r,c) in zip(rows,cols):
        # Extract an 8-connected neighbourhood
        (col_neigh,row_neigh) = np.meshgrid(np.array([c-1,c,c+1]), np.array([r-1,r,r+1]))
        # Cast to int to index into image
        col_neigh = col_neigh.astype('int')
        row_neigh = row_neigh.astype('int')
        # Convert into a single 1D array and check for non-zero locations
        pix_neighbourhood = img[row_neigh,col_neigh].ravel() != 0

        # If the number of non-zero locations equals 2, add this to our list of co-ordinates
        if np.sum(pix_neighbourhood) == 2:
            skel_coords.append((r,c))

    return len(skel_coords)

def num_filopodia_demerged(mask):
    thinned = thin(mask)
    img_thin_labeled = skimage.measure.label(thinned.astype(np.uint8), connectivity=2)
    stats_bbox = skimage.measure.regionprops(img_thin_labeled.astype(np.uint8))
    filopodia_count = 0
    for i in range(0, len(stats_bbox)):
        bbox = stats_bbox[i].bbox
        bbox_region = img_thin_labeled[bbox[0]:bbox[2], bbox[1]:bbox[3]]
        value_counts = Counter(bbox_region.flatten()).most_common()
        most_frequent_value = value_counts[1][0] if len(value_counts) > 1 else value_counts[0][0]
        bbox_region = (bbox_region == most_frequent_value) * 1

        bbox_region_padded = np.pad(bbox_region, pad_width=4, mode='constant', constant_values=0)
        n_endpoints = find_endpoints(bbox_region_padded)
        
        filopodia_count += (n_endpoints - 1)

    return max(filopodia_count, 0)

例如,以这些模式为例:

我该如何处理这个?考虑到在实际图像中这些细丝不是这样直,可能会重叠很多也在“结”模式(形状的“6”).一个例子“真实的的”面具:

cczfrluj

cczfrluj1#

HoughLines在您的情况下工作得很好。

#!/usr/bin/env python3

import cv2
import numpy as np

im_path = "/"
im_name = "1.png"

# Read Image
img = cv2.imread(im_path+im_name, cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Apply edge detection method on the image
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
  
# This returns an array of r and theta values
lines = cv2.HoughLines(edges, 1, np.pi/180, 50)

detected_angles = []

def draw_line(r, theta):
    # Stores the value of cos(theta) in a
    a = np.cos(theta)

    # Stores the value of sin(theta) in b
    b = np.sin(theta)

    # x0 stores the value rcos(theta)
    x0 = a*r

    # y0 stores the value rsin(theta)
    y0 = b*r

    # x1 stores the rounded off value of (rcos(theta)-1000sin(theta))
    x1 = int(x0 + 1000*(-b))

    # y1 stores the rounded off value of (rsin(theta)+1000cos(theta))
    y1 = int(y0 + 1000*(a))

    # x2 stores the rounded off value of (rcos(theta)+1000sin(theta))
    x2 = int(x0 - 1000*(-b))

    # y2 stores the rounded off value of (rsin(theta)-1000cos(theta))
    y2 = int(y0 - 1000*(a))

    # cv2.line draws a line in img from the point(x1,y1) to (x2,y2).
    # (0,0,255) denotes the colour of the line to be
    # drawn. In this case, it is red.
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

# The below for loop runs till r and theta values
# are in the range of the 2d array
for r_theta in lines:
    arr = np.array(r_theta[0], dtype=np.float64)
    r, theta = arr
    if(not detected_angles):
        detected_angles.append(theta)
        draw_line(r, theta)

    else:
        new_angle = True
        for angle in detected_angles:
            if(np.isclose(angle, theta, rtol=1e-01, atol=1e-08, equal_nan=False)):
                new_angle = False
        if(new_angle):
            detected_angles.append(theta)
            draw_line(r, theta)

print("There are ( {} ) lines in this image.".format(len(detected_angles)))

cv2.namedWindow('Detected_Lines', cv2.WINDOW_NORMAL)
cv2.imshow('Detected_Lines', img)
cv2.waitKey(0)

相关问题