Segmentation of white object on white background

Hello,

i have a problem with the segmentation of a picture.
The background of this picture is kind of white and when i change everything to gray i have some similar gray values from the background and the objects and so I have problems with the threshhold. I’ve tried a lot, also with HSV, algorithms (watershed,…) and stuff like this. At the moment I am trying it with adaptive threshhold, afterwards I use a median filter and remove small white remaining points. So I have the best result so far.


But as you see do I have splitted contours.
Now I want to ask if its possible to merge these contours and fill it afterwards or if you have a good solution.
This is the code so far:

img = cv2.imread('ducks.jpg', 1)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# Addaptive Gauss Threshholding
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY_INV,11,3)

# median filter
median_blur= cv2.medianBlur(thresh, 5)

# Remove small white point
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(median_blur, None, None, None, 8, cv2.CV_32S)

#get CC_STAT_AREA component as stats[label, COLUMN] 
areas = stats[1:,cv2.CC_STAT_AREA]

result = np.zeros((labels.shape), np.uint8)

for i in range(0, nlabels - 1):
    if areas[i] >= 100:   #keep
        result[labels == i + 1] = 255

cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

I would be really glad for some help.

This is the original picture:

fix the camera’s exposure settings, take a blank picture, then take this picture, take pixel differences

or run a median of size ~200 on this, take differences (then use inRange to get a background mask, or do something else):

or throw deep learning at it. it’s good at these things.