title: How to count different grains in an image using cv2?
body: <p>I have an image that has cereal items below:
  <a href="https://i.stack.imgur.com/yeMOr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/yeMOr.png" alt="grains" /></a></p>
  <p>The image has:</p>
  <ul>
  <li>3 walnuts</li>
  <li>3 raisins</li>
  <li>3 pumpkin seeds</li>
  <li>27 similar looking cereal</li>
  </ul>
  <p>I wish to count them separately using opencv, I do not want to recognize them. So far, I have tailored the AdaptiveThreshold method to count all the seeds, but not sure how to do it separately. This is my scripts:</p>
  <pre><code>import cv2
  import numpy as np
  import matplotlib.pyplot as plt
  
  img = cv2.imread('/Users/vaibhavsaxena/Desktop/Screen Shot 2021-04-27 at 12.22.46.png', 0)
  #img = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
  windowSize = 31
  windowConstant = 40
  mask = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, windowSize, windowConstant)
  plt.imshow(mask)
  
  stats = cv2.connectedComponentsWithStats(mask, 8)[2]
  label_area = stats[1:, cv2.CC_STAT_AREA]
  
  min_area, max_area = 345, max(list(label_area))  # min/max for a single circle
  singular_mask = (min_area &lt; label_area) &amp; (label_area &lt;= max_area)
  circle_area = np.mean(label_area[singular_mask])
  
  n_circles = int(np.sum(np.round(label_area / circle_area)))
  
  print('Total circles:', n_circles)
  
  36
  </code></pre>
  <p>But this one seems extremely hard coded. For example, if I zoom in or zoom out the image, it yields a different count.</p>
  <p>Can anyone please help?</p>