I would like to detect circular erosions and dilations on a line. For dilations, I tried to recursively erode the image and on every recursion, I check width/height aspect ratio. If the ratio is smaller than 4, I assume that it the contour is circular and for each such contour I calculate circle center and radius from moments and area. This is the function that detects circular dilations:

```
def detect_circular_dilations(img, contours):
contours_current, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(contours_current) == 0:
return get_circles_from_contours(contours)
for c in contours_current:
x, y, w, h = cv2.boundingRect(c)
if w > h:
aspect_ratio = float(w) / h
else:
aspect_ratio = float(h) / w
if aspect_ratio < 4 and w < 20 and h < 20 and w > 5 and h > 5:
contours.append(c)
return detect_circular_dilations(cv2.erode(img, None, iterations=1), contours)
```

An example of circular dilations that I want to detect are the following:

Another problem that I haven't solve is the detection of circular erosions. An example of circular erosion is the following:

Here I've marked the circular erosion I would like to detect with red rectangle. There might be some smaller circular patterns (on the left) that shouldn't be treated as actual circular erosion.

Does anyone know what is the best way to detect such circular shapes? For circular dilations, I would appreciate any comment/suggestion in order to potentially make detection more robust.

Thank you!

What I would try is to find two edges of the line with

`cv2.Canny()`

and search for contours. If you sort your contour by the width of their bounding box, the first two contours will be your lines edges. After that you can calculate the minimum distance of each point in one edge to the other edge. Then you can calculate the median of the distances and say that if a point has bigger or shorter distance than the median (+- tolerance) than that point is ether the dilation or erosion of the line and append it to a list. You can sort out noises if needed by itterating through the lists and remove the points if they are not consecutive (on x axis).Here is a simple example:

Result:

Edit:

If the picture has a line that is broken (that means more contours) you would have to treat each contour as a seperate line. You could achieve this by making a region of interest with the help of

`cv2.boundingRect()`

. But as I tried it with the new uploaded picture the process is not very robust since you have to change the tolerance to get the desired result. Since I don't know what other images look like, you may need a better way to get the average distance and the tolerance factor. Any way here is a sample of what I described (with 15 for tolerance):Result: