如何计算背景嘈杂的图像中的小种子

How to count small seeds in an image with a noisy background

我有一张西红柿种子的图像,图像中的种子数量是32。我正在尝试使用 OpenCV 来计算这些种子。图像有一些噪音导致错误计数。

我的方法是计算圆心。一般的想法是设置阈值,然后从背景像素进行洪水填充以填充背景(洪水填充就像照片编辑应用程序中的油漆桶工具),这样您只能看到中心。

这是我的代码:

img = cv2.imread('tomato.jpg', 0)
dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
img = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
seed_pt = (25, 25)
fill_color = 0
mask = np.zeros_like(img)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
for th in range(60, 120):
    prev_mask = mask.copy()
    mask = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)[1]
    mask = cv2.floodFill(mask, None, seed_pt, fill_color)[1]
    mask = cv2.bitwise_or(mask, prev_mask)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

n_centers = cv2.connectedComponents(mask)[0] - 1
print('There are %d cells in the image.'%n_centers)

输出为:

There are 34 cells in the image.

原计数为32.

我该如何解决这个问题?

我的解决方案是将 RGB 掩码与使用 inRange 的 HSV 掩码相结合,还有一些需要改进的地方,但概念是在不止一种颜色中进行掩码-space:

output: There are 32 cells in the image.

import cv2
import numpy as np
import matplotlib.pyplot as plt

def HSV_mask(img, hsv_range):
    """
    Function: check_HSV, to get the ratio of the marked pixels of specific color in the frame,
      using HSV space.
    ---
    Parameters:
    @param: img, ndarray, image frame of shape [height, width, 3(BGR)].
    @param: hsv_range, tuple of 6, defines the hsv ranges low high for Hue, Saturation, and Value.
    ---
    @return: mask, ndarray, the masked image for the given color.
    """
    hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

    mask=cv2.inRange(hsv_img,hsv_range[0::2],hsv_range[1::2])

    return mask


img = cv2.imread('001.jpg')

# RGB Mask
rgb_mask = img.copy()
rgb_mask[rgb_mask[...,0]>140]=(0, 0, 0)
rgb_mask[rgb_mask[...,1]>140]=(0, 0, 0)
rgb_mask[rgb_mask[...,2]<70]=(0, 0, 0)
rgb_mask[np.sum(rgb_mask, axis=2)>0]=(1, 1, 1)

masked = img*rgb_mask


# HSV Mask
H1 = (1, 8)
H2 = (175, 180)
S = (40, 255)
V = (100, 150)

myRange1 = (H1 + S + V)
myRange2 = (H2 + S + V)
hsv_mask1 = HSV_mask(masked, myRange1)
hsv_mask2 = HSV_mask(masked, myRange2)
hsv_mask = hsv_mask1#cv2.bitwise_or(hsv_mask1, hsv_mask2)

# Morphology
k = 7
# Get the structuring element:
maxKernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, ksize=(k, k))
# Perform closing:
mask = cv2.morphologyEx(hsv_mask, cv2.MORPH_CLOSE, maxKernel, None, None, 1, cv2.BORDER_CONSTANT)


# Median Filter
filteredMask = cv2.medianBlur(mask,5)

plt.figure(num='Tomato Seeds')

plt.subplot(221)
plt.imshow(img[...,[2, 1, 0]])
plt.title('Original')

plt.subplot(222)
plt.imshow(masked[...,[2,1,0]])
plt.title('rgb masked')

plt.subplot(223)
plt.imshow(hsv_mask)
plt.title('HSV mask')

plt.subplot(224)
plt.imshow(filteredMask)
plt.title('Median Filter')

plt.show()

n_centers = cv2.connectedComponents(filteredMask)[0] - 1
print('There are %d cells in the image.'%n_centers)