0

I'm working to detect cells within microscope images like the one below. There are often spurious contours that get drawn due to imperfections on the microscope slides, like the one below the legend in the figure below.

I'm currently using this solution to clean these up. Here's the basic idea.

# Create image of background
blank = np.zeros(image.shape[0:2])
background_image = cv2.drawContours(blank.copy(), background_contour, 0, 1, -1)

for i, c in enumerate(contours):
    # Create image of contour
    contour_image = cv2.drawContours(blank.copy(), contours, i, 1, -1)
    # Create image of focal contour + background
    total_image = np.where(background_image+contour_image>0, 1, 0)
        # Check if contour is outside postive space
        if total_image.sum() > background_image.sum():
            continue

enter image description here

This works as expected; if the total_image area is greater than the area of the background_image then c must be outside the region of interest. But drawing all of these contours is incredibly slow and checking thousands of contours takes hours. Is there a more efficient way to check if contours overlap that doesn't require drawing the contours?

Ian Gilman
  • 107
  • 2
  • 6

2 Answers2

1

I assume the goal is to exclude the external contour from further analysis? If so, the easiest is to use the red background contour as a mask. Then use the masked image to detect the blue cells.

# Create image of background
blank = np.zeros(image.shape[0:2], dtype=np.uint8)
background_image = cv2.drawContours(blank.copy(), background_contour, 0, (255), -1)

# mask input image (leaves only the area inside the red background contour)
res = cv2.bitwise_and(image,image,mask=background_image )

#[detect blue cells]

enter image description here

J.D.
  • 4,511
  • 2
  • 7
  • 20
  • Thank you! I used this in a slightly different way than you suggested. I first found the background and then used the `res` mask, as you did, to create a new image that I used for finding contours. By removing the junk background space first I avoided the problem of having to check the resulting contours at all. – Ian Gilman Nov 11 '19 at 20:39
0

assuming you are trying to find points on the different contours that are overlaping

consider contour as

vector<vector<Point> > contours;
..... //obtain you contrours.

vector<Point> non_repeating_points;
for(int i=0;i<contours.size();i++)
{
    for(int j=0;j<contours[i].size();j++)
    {
        Point this_point= countour[i][j];
        for(int k=0;k<non_repeating_points.size();k++)
        {//check this list for previous record
            if(non_repeating_points[k] == this_point)
            {
               std::cout<< "found repeat points at "<< std::endl;
               std::cout<< this_point << std::endl;
               break;
            }
        }
        //if not seen before just add it in the list
        non_repeating_points.push_back(this_point);
    }
}

I just wrote it without compile. but I think you can understand the idea.

the information you provide is not enough. In case you mean to find the nearest connected boundary. And there is no overlapping.

you can declare a local cluster near the point non_repeating_points[k]. Call it surround_non_repeating_points[k]; you can control the distance that can be considered as intercept and push all of them in this surround_non_repeating_points[k];

Then just check in a loop for if(surround_non_repeating_points[k] == this_point)

Dr Yuan Shenghai
  • 1,849
  • 1
  • 6
  • 19