Facebook
From Gamboge Pintail, 3 Years ago, written in Python.
Embed
Download Paste or View Raw
Hits: 71
  1. # import libraries here
  2. import math
  3.  
  4. import cv2
  5. import numpy as np
  6.  
  7.  
  8. def count_blood_cells(image_path):
  9.     """
  10.    Procedura prima putanju do fotografije i vraca broj crvenih krvnih zrnaca, belih krvnih zrnaca i
  11.    informaciju da li pacijent ima leukemiju ili ne, na osnovu odnosa broja krvnih zrnaca
  12.  
  13.    Ova procedura se poziva automatski iz main procedure i taj deo kod nije potrebno menjati niti implementirati.
  14.  
  15.    :param image_path: <String> Putanja do ulazne fotografije.
  16.    :return: <int>  Broj prebrojanih crvenih krvnih zrnaca,
  17.             <int> broj prebrojanih belih krvnih zrnaca,
  18.             <bool> da li pacijent ima leukemniju (True ili False)
  19.    """
  20.     red_blood_cell_count = 0
  21.     white_blood_cell_count = 0
  22.     has_leukemia = None
  23.  
  24.     # Ucitavanje slike
  25.     img_bgr = cv2.imread(image_path)
  26.  
  27.     # TODO - Prebrojati crvena i bela krvna zrnca i vratiti njihov broj kao povratnu vrednost ove procedure
  28.     white_blood_cell_count, wbc_contours, wbc_radius = count_white_cells(img_bgr)
  29.     red_blood_cell_count = count_red_cells(img_bgr, wbc_contours, wbc_radius)
  30.  
  31.     # TODO - Odrediti da li na osnovu broja krvnih zrnaca pacijent ima leukemiju i vratiti True/False kao povratnu vrednost ove procedure
  32.     has_leukemia = (white_blood_cell_count or 0) / (red_blood_cell_count or 1) > 0.085
  33.  
  34.     return red_blood_cell_count, white_blood_cell_count, has_leukemia
  35.  
  36.  
  37. def count_white_cells(img_bgr):
  38.     # Binary image from HSV
  39.     img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
  40.  
  41.     min_blue = (50, 50, 20)
  42.     max_blue = (145, 255, 255)
  43.  
  44.     img_hsw_filtered = cv2.inRange(img_hsv, min_blue, max_blue)
  45.  
  46.     # Binary image from threshold
  47.     img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
  48.  
  49.     _, img_thresh_filtered = cv2.threshold(img_gray, 150, 255, cv2.THRESH_BINARY)
  50.     img_thresh_filtered = cv2.bitwise_not(img_thresh_filtered)
  51.  
  52.     # Concatenate both images
  53.     img = cv2.bitwise_or(img_hsw_filtered, img_thresh_filtered)
  54.  
  55.     # Fill holes
  56.     kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
  57.     img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
  58.  
  59.     _, contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  60.  
  61.     contours_by_size = sorted(contours, key=cv2.contourArea, reverse=True)
  62.  
  63.     wbc_contours = []
  64.     contours_to_remove = []
  65.     min_area = 0
  66.     for c in contours_by_size:
  67.         area = cv2.contourArea(c)
  68.         if area > min_area:
  69.             wbc_contours.append(c)
  70.             min_area = area / 3
  71.         else:
  72.             contours_to_remove.append(c)
  73.  
  74.     # Remove small contours
  75.     for c in contours_to_remove:
  76.         cv2.drawContours(img, [c], -1, 0, -1)
  77.  
  78.     if not wbc_contours:
  79.         return 0, None, 0
  80.  
  81.     # Assume that last item in wbc_contours is a single cell
  82.     wbc_area = cv2.contourArea(wbc_contours[-1])
  83.     radius = np.round(2 * math.sqrt(wbc_area / math.pi))
  84.  
  85.     min_radius = np.int(radius * 0.3)
  86.     max_radius = np.int(radius * 1.3)
  87.  
  88.     img_edges = cv2.Canny(img, 75, 200)
  89.     circles = cv2.HoughCircles(img_edges, cv2.HOUGH_GRADIENT, 1.3, radius, param1=200, param2=30, minRadius=min_radius,
  90.                                maxRadius=max_radius)
  91.  
  92.     wbc_count = 0
  93.  
  94.     if circles is not None:
  95.         circles = np.round(circles[0, :]).astype("int")
  96.         circles = sorted(circles, key=lambda x: x[2], reverse=True)
  97.         biggest_radius = circles[0][2]
  98.  
  99.         for (x, y, r) in circles:
  100.             for c in wbc_contours:
  101.                 # If center is in contour or near contour
  102.                 closes_contour_point = cv2.pointPolygonTest(c, (x, y), True)
  103.                 if closes_contour_point >= 0 or -closes_contour_point < min_radius:
  104.                     # cv2.circle(img_bgr, (x, y), r, (0, 255, 0), 2)
  105.                     # cv2.rectangle(img_bgr, (x - 2, y - 2), (x + 2, y + 2), (0, 128, 255), -1)
  106.                     wbc_count += np.int(biggest_radius / r)
  107.                     break
  108.  
  109.     print(wbc_count)
  110.  
  111.     return wbc_count, wbc_contours, radius
  112.  
  113.  
  114. def count_red_cells(img_bgr, wbc_contours, wbc_radius):
  115.     img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
  116.     img = cv2.medianBlur(img_gray, 5)
  117.     img = cv2.GaussianBlur(img, (5, 5), 0)
  118.     img = cv2.equalizeHist(img)
  119.  
  120.     img = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 41, 5)
  121.     img = cv2.bitwise_not(img)
  122.  
  123.     # Remove wbc countours
  124.     for c in wbc_contours:
  125.         cv2.drawContours(img, [c], -1, 0, -1)
  126.  
  127.     kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
  128.  
  129.     _, contours, _ = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
  130.     for c in contours:
  131.         cv2.drawContours(img, [c], 0, 255, -1)
  132.  
  133.     _, contours, _ = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  134.  
  135.     rbc_radii = []
  136.     for c in contours:
  137.         if len(c) >= 5:
  138.             ellipse = cv2.fitEllipse(c)
  139.             widthE = ellipse[1][0]
  140.             heightE = ellipse[1][1]
  141.             if widthE > heightE:
  142.                 coef = heightE / widthE
  143.             else:
  144.                 coef = widthE / heightE
  145.  
  146.             if coef > 0.8:
  147.                 (x, y), r = cv2.minEnclosingCircle(c)
  148.                 rbc_radii.append(r)
  149.  
  150.     min_radius = 0
  151.     similar_radii = []
  152.     for r in sorted(rbc_radii, reverse=True):
  153.         if r > min_radius:
  154.             min_radius = r * 0.8
  155.             similar_radii.append(r)
  156.  
  157.     radius = np.average(similar_radii)
  158.  
  159.     min_radius = np.int(radius * 0.6)
  160.  
  161.     # Detect
  162.     rbc_contours = []
  163.     rbc_count = 0
  164.     for c in contours:
  165.         (x, y), r = cv2.minEnclosingCircle(c)
  166.         if r > min_radius:
  167.             cv2.circle(img_bgr, (int(x), int(y)), int(r), (0, 255, 0), 2)
  168.             rbc_contours.append(c)
  169.             rbc_count += int(r / min_radius)
  170.  
  171.     return len(rbc_contours)
  172.