通用对象计数Python OpenCV

时间:2019-04-10 14:20:56

标签: python opencv computer-vision object-detection counting

我正在尝试使用python和openCV(可以尝试其他方法)制作通用的对象计数算法,但是我似乎无法很好地了解各种对象,也不知道如何适应那

https://imgur.com/a/yAkRxWH是一些示例测试图像。

这是为了加快较小物品的盘点。

**编辑 这是我当前的代码(简单的Blob检测器)

# Standard imports
import cv2
import numpy as np;

# Read image
im = cv2.imread("./images/screw_simple.jpg", cv2.IMREAD_GRAYSCALE)
im = cv2.resize(im, (1440, 880))

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 10 #10
params.maxThreshold = 200 #200

# Filter by Area.
params.filterByArea = True # True
params.minArea = 500 #1500

# Filter by Circularity
params.filterByCircularity = True #True
params.minCircularity = 0.1 #0.1

# Filter by Convexity
params.filterByConvexity = True #True
params.minConvexity = 0.0 #0.87

# Filter by Inertia
params.filterByInertia = True #True
params.minInertiaRatio = 0.0 #0.01

# Create a detector with the parameters
ver = (cv2.__version__).split('.')
if int(ver[0]) < 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
total_count = 0
for i in keypoints:
    total_count = total_count + 1


im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show blobs
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)

print(total_count)

这是我得到的结果:https://imgur.com/a/id6OlIA

如何改进该算法以更好地检测对象的一般用例,而不必每次都为每个对象修改参数?

2 个答案:

答案 0 :(得分:0)

  

您可以尝试使用OpenCV方法,也可以使用   SimpleBlobDetector

很明显,这是一个测试图像,我得到的结果也不完美,因为要设置的超参数很多。超参数使它非常灵活,因此它是一个不错的起点。

这就是检测器的功能(请参见详细here):

  1. 阈值:通过使用以minThreshold开始的阈值对源图像进行阈值处理,将源图像转换为多个二进制图像。这些阈值将增加thresholdStep直到maxThreshold。因此,第一个阈值为minThreshold,第二个阈值为minThreshold + thresholdStep,第三个阈值为minThreshold + 2 x thresholdStep,依此类推。
  2. 分组:在每个二进制图像中,连接的白色像素被分组在一起。我们称这些二进制blob。
  3. 合并:计算二进制图像中二进制blob的中心,并合并比minDistBetweenBlobs更近的blob。

  4. 中心和半径计算:计算并返回新合并的Blob的中心和半径。

找到下面的代码。

Output Image

# Standard imports
import cv2
import numpy as np

# Read image
im = cv2.imread("petri.png", cv2.IMREAD_COLOR)

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 0
params.maxThreshold = 255

# Set edge gradient
params.thresholdStep = 5

# Filter by Area.
params.filterByArea = True
params.minArea = 10

# Set up the detector with default parameters.
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(im, keypoints, np.array([]), (0, 0, 255),
                                      cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show keypoints
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)

答案 1 :(得分:0)

  

为了获得更好的可读性,我宁愿再回答一遍:您可以   使用细分方法,例如watershed algorithm

任何灰度图像都可以视为地形图表面,其中高强度表示山峰和丘陵,而低强度表示山谷。您开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水的上升,取决于附近的峰(梯度),来自不同山谷(显然具有不同颜色)的水将开始合并。为了避免这种情况,您可以在水汇合的位置建造障碍。您将继续填充水和建造障碍物的工作,直到所有山峰都在水下。然后,您创建的障碍将为您提供细分结果。这就是分水岭背后的“哲学”。

Original image Segmented image