一般对象计数Python OpenCV

问题描述 投票:-4回答:2

我正在尝试使用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

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

python opencv computer-vision object-detection counting
2个回答
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)

0
投票

为了更好的可读性,我宁愿把它放在第二个答案中:你可以使用分段方法,例如watershed algorithm

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

Original image Segmented image

© www.soinside.com 2019 - 2024. All rights reserved.