Somebody posted a quiz question on a prominent social network that asked how many sesame seeds there are on a burger bun.
My, first reaction was “I’m definitely not gonna count them” but then I thought I’d love to make a computer count them for me. And so I decided to try it.
First thing, take a photo of the bun. My experiments showed that it’s best to use the flash, because overhead lighting minimizes the lightness variations due to ridges of the bread.
Then fire The Gimp and make sure the seeds stand out more.
- Crop the photo tightly around the burger. You might want to use the eraser to remove anything that is not the bun.
- Then duplicate the image layer.
- Blur the layer above, (Filters > Gaussian Blur). Set the radius at around double the seed radius in pixels. You might need iterate and tweak that to get better results.
- Set the Layer Mode to Grain Extract. The seeds are now clearly lighter than the rest of the bun.
- Use Colors > Threshold to convert the image to black and white. Play with the threshold value until you get clear white blobs where the seeds were.
- Invert the image
- I did a few Dilate and Erode rounds so that I could get rid of the tiny specs and make the seeds more smooth/rounded but that might be unnecessary. This is the final image.
Time to code! Thanks to the very well written tutorial I found at learnopencv.com this part was easy. I will not bother explaining it because Satya Mallick explains it much better than I could, but here is the modified code. I had to play with the circularity and area parameters in order for the computer to detect most seeds.
# Standard imports import cv2 import numpy as np; # Read image im = cv2.imread("blob.jpg", cv2.IMREAD_GRAYSCALE) origim = cv2.imread("burger.jpg") # Setup SimpleBlobDetector parameters. params = cv2.SimpleBlobDetector_Params() # Change thresholds params.minThreshold = 10; params.maxThreshold = 200; # Filter by Area. params.filterByArea = True params.minArea = 80 # Filter by Circularity params.filterByCircularity = True params.minCircularity = 0.2 # Filter by Convexity params.filterByConvexity = False params.minConvexity = 0.87 # Filter by Inertia params.filterByInertia = True params.minInertiaRatio = 0.01 # Create a detector with the parameters ver = (cv2.__version__).split('.') if int(ver) < 3 : detector = cv2.SimpleBlobDetector(params) else : detector = cv2.SimpleBlobDetector_create(params) # Detect blobs. keypoints = detector.detect(im) # Draw detected blobs as red circles. # cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob im_with_keypoints = cv2.drawKeypoints(origim, keypoints, np.array(), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) print len(keypoints) # Show keypoints cv2.imshow("Keypoints", im_with_keypoints) cv2.imwrite("burgerpoints.jpg", im_with_keypoints); cv2.waitKey(0)
This is the final result. The computer counted 284 seeds. I can count (by eyeball) around 30 seeds that went undetected but there are a few false positives (you might want to crop more tightly than I did, or use the Gimp’s eraser tool to remove the cheddar) and a few seeds on the side of the bun that are not visible in the photo so I believe the count is fairly accurate.
So now you know that there are around 300 sesame seeds on a burger bun.