Подсчет ячеек на изображении с использованием python и OpenCV - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь написать алгоритм для подсчета точек (ячеек) на изображении.

Вот скрипт, который я сделал до сих пор:

import numpy as np
import cv2
import os

for dirname in os.listdir("images/"):

    for filename in os.listdir("images/" + dirname + "/"):

        # Image read
        img = cv2.imread("images/" + dirname + "/" + filename, 0)

        # Denoising
        denoisedImg = cv2.fastNlMeansDenoising(img);

        # Threshold (binary image)
        # thresh – threshold value.
        # maxval – maximum value to use with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
        # type – thresholding type
        th, threshedImg = cv2.threshold(denoisedImg, 200, 255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) # src, thresh, maxval, type

        # Perform morphological transformations using an erosion and dilation as basic operations
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
        morphImg = cv2.morphologyEx(threshedImg, cv2.MORPH_OPEN, kernel)

        # Find and draw contours
        contours, hierarchy = cv2.findContours(morphImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contoursImg = cv2.cvtColor(morphImg, cv2.COLOR_GRAY2RGB)
        cv2.drawContours(contoursImg, contours, -1, (255,100,0), 3)

        cv2.imwrite("results/" + dirname + "/" + filename + "_result.tif", contoursImg)
        textFile = open("results/results.txt","a")
        textFile.write(filename + " Dots number: {}".format(len(contours)) + "\n")
        textFile.close()

Вот мой входное изображение: Input

Вот мой результат: Result

На данный момент этот сценарий довольно хорошо работает с этим вводом, но когда Я переключаюсь на другие входы, как этот: Input

Я получаю очень дурацкий результат:

Result

Я хотел бы иметь возможность сохранять только те точки, которые:

  • Хорошо округлены

Или:

  • которые находятся в верхние 10% других точек с точки зрения яркости
  • , которые являются достаточно "большими" (относительно изображения, поэтому давайте удалим точки, которые находятся в нижних 10% с точки зрения поверхности).

Я читал о создании функции "is_contour_bad", которую я мог бы использовать, чтобы определить, является ли контур плохим и должен ли быть удален.

https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/

Я пытался понять это не получилось. Тем не менее, эта идея мне кажется хорошей.

Я также настроил порог и эрозии / расширения в зависимости от изображения, но на самом деле лучше всего было бы иметь возможность воздействовать на каждый из перечисленных выше параметров. Тем не менее, если у вас есть идеи по автоматическому поиску полезных свойств изображения для применения к нему правильных фильтров, это может быть интересно.

Если у вас есть идея или фрагмент кода, даже небольшой, чтобы помочь мне достичь эта цель была бы офигенной.

Заранее спасибо за помощь.

1 Ответ

2 голосов
/ 31 марта 2020

Один из способов удаления точек, которые недостаточно округлены и которые являются маленькими , заключается в использовании операции открытия (которую вы уже используете) с круговым структурирующим элементом минимального размера точки, который вы хотите (каждая точка, меньшая, чем структурирующий элемент, будет удалена). На следующих изображениях показан аналогичный вашей проблеме пример, в котором маленькие точки удаляются таким образом (источник: https://homepages.inf.ed.ac.uk/rbf/HIPR2/open.htm). Кроме того, OpenCV имеет реализацию этой операции (https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html).

enter image description here

Фактически вы уже используйте эту операцию, но, на мой взгляд, структурирующий элемент, определенный в следующей строке, кажется слишком маленьким:

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))

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

...