How to calculate nucleus amount of cell?

后端 未结 2 2013
名媛妹妹
名媛妹妹 2021-02-06 03:28

I am using Python 3.5 and OpenCV 3 to analyze pictures of cells in biology. My pictures look like this:

I want to be able to calculate a ratio of the area of th

2条回答
  •  星月不相逢
    2021-02-06 04:08

    # light purple color segmentation (to get cells)
    cell_hsvmin = (110,40,145)
    cell_hsvmax = (150,190,255)
    
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    color_thresh = cv2.inRange(hsv, cell_hsvmin, cell_hsvmax)
    # masked = cv2.bitwise_and(frame,frame, mask=color_thresh)
    # cv2.imshow('masked0', masked)
    ksize = 5
    open_thresh = cv2.morphologyEx(color_thresh, cv2.MORPH_OPEN, np.ones((ksize,ksize),'uint8'), iterations=1)
    masked = cv2.bitwise_and(frame,frame, mask=open_thresh)
    cv2.imshow('masked', masked)
    
    # dark purple color segmentation (to get nucleus)
    nucleus_hsvmin = (125,65,160)
    nucleus_hsvmax = (150,190,255)
    
    nucleus_color_thresh = cv2.inRange(hsv, nucleus_hsvmin, nucleus_hsvmax)
    ksize = 3
    nucleus_open_thresh = cv2.morphologyEx(nucleus_color_thresh, cv2.MORPH_OPEN, np.ones((ksize,ksize),'uint8'), iterations=1)
    nucleus_masked = cv2.bitwise_and(masked,masked, mask=nucleus_open_thresh)
    cv2.imshow('nucleus_masked', nucleus_masked)
    
    """
    HULL APPROXIMATES THE CELLS TO A CIRCLE TO FILL IN GAPS CREATED BY THRESHOLDING AND CLOSING.
    FOR NON-CIRCULAR CELLS LIKE IN YOUR SECOND IMAGE, THIS MIGHT CAUSE BAD AREA CALCULATIONS
    """
    # doHULL = False
    doHULL = True
    
    cells = []
    cells_ratio = []
    minArea = frame.shape[0]*frame.shape[1]* 0.01
    _, contours, _ = cv2.findContours(open_thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area >= minArea:
            cells.append(cnt)
            nucleus_mask = np.zeros(frame.shape[:2], 'uint8')
            if doHULL:
                hull = cv2.convexHull(cnt)
                cv2.drawContours(nucleus_mask, [hull], -1, 255, -1);
            else:
                cv2.drawContours(nucleus_mask, [cnt], -1, 255, -1);
            nucleus_mask = cv2.bitwise_and(nucleus_open_thresh, nucleus_mask)
            nucleus_area = np.count_nonzero(nucleus_mask)
    
            ratio = nucleus_area / area
            cells_ratio.append(ratio)
    
            # nucleus_img = cv2.bitwise_and(frame, frame, mask=nucleus_mask)
            # cv2.imshow('nucleus_img', nucleus_img)
            # cv2.waitKey(0)
    
    doDRAWCELLS = False
    # doDRAWCELLS = True
    if doDRAWCELLS:
        for cell_cnt in cells:
            cells_mask = np.zeros(frame.shape[:2], 'uint8')
            if doHULL:
                hull = cv2.convexHull(cell_cnt)
                cv2.drawContours(cells_mask, [hull], -1, 255, -1);
            else:
                cv2.drawContours(cells_mask, [cell_cnt], -1, 255, -1);
            cells_img = cv2.bitwise_and(frame, frame, mask=cells_mask)
            cv2.imshow('cells_img', cells_img)
            cv2.waitKey(0)
    

    this will only work for cells that are not connected. you can use this as a base to work with the watershed algorithm. Also, the color segmentation parameters have been tuned according to the 2 images you posted. other slides might deviate from the color range so you might have to adjust them. if adjusting them doesnt get you a good compromise, you might have to look into otsu binarization or adaptive thresholding to segment the colors.

    Another option is to look at cv2.MORPH_GRADIENT which works like an edge detector. or

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    kernel = np.array([[1,1,1],[1,-8,1],[1,1,1]],dtype='float32')
    laplace = cv2.filter2D(cv2.GaussianBlur(gray,(blur_ksize,blur_ksize),0), -1, kernel)
    cv2.imshow('laplace', laplace)
    

    and use the edges to segment the cells?

提交回复
热议问题