Как правильно подсчитать количество соседних ячеек для каждой ячейки в изображении? - PullRequest
0 голосов
/ 09 апреля 2020

Пожалуйста, я бы хотел рассчитать процент гексагональных ячеек (например, количество ячеек, имеющих 6 соседних ячеек / общее количество ячеек) в двоичном изображении и получить цветное кодированное изображение, как показано ниже.

Я попробовал приведенный ниже код python, но не получил правильный вывод. Например, как вы можете видеть, что красные ячейки в двоичном изображении имеют либо 4,5,6, либо 7 соседних ячеек, но это неправильно рассчитано, поскольку у них есть 3,4 и 6 соседей.

An Пример двоичного изображения и его вывод прилагается.

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))

The binary image

Как видно, у двоичного изображения есть размытые края. Как мне улучшить их видимость?

Colored coded image

1 Ответ

1 голос
/ 09 апреля 2020

Одним из подходов может быть использование алгоритма Водораздела для сегментации.

Прочтите об этом здесь:

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

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

Есть множество других алгоритмов сегментации , на которые вы могли бы посмотреть, работает ли что-нибудь лучше (например, Алгоритм Felsenszwalb ). Здесь представляет собой простое сравнение трех алгоритмов, вы можете легко расширить этот пример, чтобы увидеть, как они сравниваются в вашем наборе данных.

Как только у вас есть контуры всех элементов (полигонов), вы можете использовать их для создания «полной карты» (идентифицируйте все ячейки и их соседей, без отверстий, без неизвестных элементов), чтобы убедиться, что вы не пропали любые клетки. Вы можете назвать это топологией ваших ячеек.

Одна вещь, которая может помочь, - это создать "более четкие" полигоны из тех, которые были возвращены алгоритмом водораздела.

Возможно, вам придется

  • объединить узлы, если они очень близки
  • соединить ребра, если углы их соединения составляют около 0 °

Это называется "исправление, исправление, упрощение меня sh". Это topi c сам по себе, и, конечно, для этого есть инструменты. Вы можете прочитать о Python связанных проектах здесь , здесь или здесь .

Как только это закончится, вы просто посчитаете края, создайте список всех соседних ячеек и перепроверьте, что все соседи обнаружены.

Этот алгоритм не является чем-то, что будет работать из коробки, вам придется улучшать и настраивать его, пока он не будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...