【问题标题】:How can I correctly count the number of the neighboring cells for each cell in the image?如何正确计算图像中每个单元格的相邻单元格的数量?
【发布时间】:2020-07-22 08:27:17
【问题描述】:

请,我想计算二值图像中六边形单元格的百分比(例如,具有 6 个相邻单元格的单元格数/单元格总数)并生成如下所示的彩色编码图像。

我尝试了下面的 python 代码,但没有得到正确的输出。例如,您可以看到二值图像中的红色单元格有 4、5、6 或 7 个相邻单元格,但计算错误,因为它们有 3,4 和 6 个相邻单元格。

附上二进制图像及其输出的示例。

import sys
import json
import cv2
import os
import scipy.io
import numpy as np
from scipy.ndimage import measurements, morphology
from skimage import measure
import time


def cells_measurements(path, orig_image, color="yellow", size=3, 
    pixel_sz=0.00104167):
    size = int(size)
    im = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
    _, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
    labeled_image, num_of_cells = measurements.label(255 - im)
    props = measure.regionprops(labeled_image)
     number_of_cells = len(props)

  colored_image = np.pad(cv2.cvtColor(~im, cv2.COLOR_GRAY2BGR), ((1, 1),(1, 1), (0, 0,)), mode='constant',constant_values=0)

  colors = [[0, 0, 128], [0, 0, 255], [0, 128, 255], [0, 255, 255],[128,255, 128], [255, 255, 0], [255, 128, 0],[255, 0, 0]]

   count_hex = 0
   labels = np.unique(labeled_image)
   for l in labels[1:]:
       i_temp = (labeled_image == l).astype(float) * 255
       i_temp = cv2.dilate(i_temp, np.ones((3, 3)), iterations=2) - i_temp
       i_temp2 = np.copy(labeled_image)
       i_temp2[i_temp == 0.] = 0
       adjacent = len(np.unique(i_temp2)) - 1
       if adjacent == 6:
          count_hex += 1
     cv2.floodFill(colored_image, None, (int(cell_center_all[l - 1][1]), 
     int(cell_center_all[l - 1][0])), colors[min(adjacent, 7)])

       hexagonal_cells = (count_hex / num_of_cells) * 100

     colored_image = np.pad(colored_image, ((0, 0), (0, 75), (0, 0)), 
    'constant', constant_values=255)
       for i in range(8):
           step = colored_image.shape[0] // 8
           colored_image[i * step:+(i + 1) * step, -60:-35] = colors[7 - i]
           colored_image[i * step, -60:-35] = 0
           colored_image[(i + 1) * step, -60:-35] = 0
           colored_image[i * step:(i + 1) * step, -60] = 0
           colored_image[i * step:(i + 1) * step, -35] = 0
           cv2.putText(colored_image, str(7 - i), (colored_image.shape[1] - 
           30, 5 + i * step + step // 2), cv2.FONT_HERSHEY_DUPLEX, 0.5, 0)

   color_path = 'Labeled Images/' + fn + "_color.png"
   cv2.imwrite(color_path, colored_image)

  Auto_Cells_Pleomorphism = []

  Mask_Path = 'generated_samples_masks/'
  Original_img_path = 'TestingSet/enhanced_imgs/'
  # please note that the "mask" image is the result of the segmentation 
  algorithm which I will provide today

  # Loop over images
  for i in range(1, 640):
      filename = str(i) + '.png'
      print(filename)
      Masks_Path = os.path.join(Mask_Path, filename)
      Original_image = os.path.join(Original_img_path, filename)
      [hexagonal_cells] = cells_measurements(Masks_Path, Original_image, 
      color="yellow", size=3) 

  Auto_Cells_Pleomorphism.append(round(hexagonal_cells))

如您所见,二值图像有一些模糊的边缘。如何提高他们的知名度?

【问题讨论】:

  • 你的代码有一个不匹配的' 字符(语法高亮出错的地方),他不会运行。这与您运行的代码完全相同吗?请复制粘贴您实际遇到问题的代码!
  • “二值图像有一些模糊的边缘”是什么意思?二值图像只有两个不同的值,不能有任何模糊。您在那里显示的图像不是二进制的。
  • 亲爱的 Cris Luengo 感谢您的帮助,确实这与我正在运行的代码相同。
  • 我的意思是模糊的边缘。

标签: python python-3.x image image-processing image-segmentation


【解决方案1】:

一种方法是使用分水岭算法进行分割。

在这里阅读:

https://scikit-image.org/docs/dev/auto_examples/segmentation/plot_watershed.html

https://www.pyimagesearch.com/2015/11/02/watershed-opencv/

您可以查看many other segmentation algorithms 看看有没有更好的方法(例如Felsenszwalb's algorithm)。 Here 是三种算法的简单比较,您可以轻松扩展此示例以查看它们在您的数据集上的比较情况。

一旦你有了所有元素(多边形)的轮廓,你就可以使用它们 创建一个“完整的地图”(识别所有单元格及其邻居,没有漏洞,没有未知元素)以确保您没有丢失任何单元格。您可以将其称为细胞的拓扑

可能有帮助的一件事是从分水岭算法返回的一次创建“更清晰”的多边形。

你可能需要

  • 如果节点非常接近,则合并节点
  • 如果连接处的角度约为 0°,则连接边

这称为“修复、修复、简化网格”。 它本身就是一个主题,当然有工具。 您可以阅读有关 Python 相关项目的信息 here, herehere.

完成后,您只需计算边数,创建所有相邻单元格的列表并交叉检查是否检测到所有相邻单元格。

这个算法不是开箱即用的, 您必须对其进行改进和调整,直到它起作用为止。

【讨论】:

  • 好答案。另外,看看 skimage 中的 Felzenszwalb 和 Huttenlocher
  • 我不是在寻找新的分割方法,我需要修复上面的代码并使其适用于该二进制图像。我是 python 新手,我不确定代码是否将此图像读取为二进制图像。
  • 图像中的模糊边缘可能可以通过形态学操作得到改善。 scikit-image.org/docs/0.13.x/auto_examples/xx_applications/… 看看扩张或关闭。在操作之间,您可能必须使用阈值来加强边界,然后重复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-18
  • 2016-07-21
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多