cv2 SimpleBlobDetector 困难
cv2 SimpleBlobDetector difficulties
我尝试在业余爱好项目中检测一些骰子上的一些点。
骰子切得很好,也有或多或少的好照片。
然后将照片灰度化,中值滤镜抗噪,做成np.array
让cv2喜欢
现在我尝试计算点数,然后......好吧...... SimpleBlobDetector
根据参数的精确调整,发现到处都是斑点,或者根本没有斑点,而且从来没有发现那些最明显的点最佳。特别是如果我激活“圆度”大于 0.7 或“惯性”,它什么也找不到。
这是怎么回事?我需要进一步预处理我的图片,还是在下面的参数中?
我尝试用高斯模糊交换滤镜,我还尝试对图像进行色调分离,以获得具有完全相同灰度值的相当大的区域。没有任何帮助。
我现在尝试了很多变体,当前的变体结果如下图所示。
blob_params = cv2.SimpleBlobDetector_Params()
blob_params.minDistBetweenBlobs = 1
blob_params.filterByCircularity = True
blob_params.minCircularity = 0.5
blob_params.minThreshold = 1
blob_params.thresholdStep = 1
blob_params.maxThreshold = 255
#blob_params.filterByInertia = False
#blob_params.minInertiaRatio = 0.2
blob_params.minArea = 6
blob_params.maxArea = 10000
detector = cv2.SimpleBlobDetector_create(blob_params)
keypoints = detector.detect(die_np) # detect blobs... just it doesn't work
image = cv2.drawKeypoints(die_np,
keypoints,
np.array([]),
(255,255,0),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
im = Image.fromarray(image)
im
好的,解决方案是:
有些参数甚至在您开始之前就设置好了。这些参数针对在浅色背景中查找深色和圆形斑点进行了优化。在我的形象中不是这样!这让我感到惊讶 - 在打印出每个参数并更正所有不适合我的用例的内容后,我终于能够使用此功能。现在它很容易找到几种不同类型的骰子上的骰子点,我试过了。
如果 openCV 参数列表更易于访问,例如 dict 或更好的注释,这会更容易。
我将在此处留下我的代码 - 它包含此函数使用的参数的完整列表,在注释中还说明了如何使用其中的一些参数,以及使用该函数的函数。我也留下了the link to the simpleBlobDetector documentation here,网上有点难找
来自C/C++背景,这个功能完全不是pythonic。它不接受所有图像格式,因为它在 python 上下文中是正常的,相反它需要一个非常特定的数据类型。在 python 中至少它会告诉你它想要什么,但是这个函数保持安静以免破坏谜语。然后它继续抛出异常而没有解释。
所以我正在制作一个函数,该函数至少接受彩色和 black/white 格式的 numpy,以及 PIL.Image。这使该功能的可用性提高了一点。
OpenCV,当您阅读本文时 - 通常在 python 中为“'triple marks'”中的每个函数提供可读文本。强调“可读性”。
import cv2
import numpy as np
from PIL import Image
def blobize(im, blob_params):
'''
Takes an image and tries to find blobs on this image.
Parameters
----------
im : nd.array, single colored. In case of several colors, the first
color channel is taken. Alternatively you can provide an
PIL.Image, which is then converted to "L" and used directly.
blob_params : a cv2.SimpleBlobDetector_Params() parameter list
Returns
-------
blobbed_im : A greyscale image with the found blobs circled in red
keypoints : an OpenCV keypoint list.
'''
if Image.isImageType(im):
im = np.array(im.convert("L"))
if isinstance(im, np.ndarray):
if (len(im.shape) >= 3
and im.shape[2] > 1):
im = im[:,:,0]
detector = cv2.SimpleBlobDetector_create(blob_params)
try:
keypoints = detector.detect(im)
except:
keypoints = None
if keypoints:
blobbed_im = cv2.drawKeypoints(im, keypoints, np.array([]),
(255,0,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
else:
blobbed_im = im
return blobbed_im, keypoints
blob_params = cv2.SimpleBlobDetector_Params()
# images are converted to many binary b/w layers. Then 0 searches for dark blobs, 255 searches for bright blobs. Or you set the filter to "false", then it finds bright and dark blobs, both.
blob_params.filterByColor = False
blob_params.blobColor = 0
# Extracted blobs have an area between minArea (inclusive) and maxArea (exclusive).
blob_params.filterByArea = True
blob_params.minArea = 3. # Highly depending on image resolution and dice size
blob_params.maxArea = 400. # float! Highly depending on image resolution.
blob_params.filterByCircularity = True
blob_params.minCircularity = 0. # 0.7 could be rectangular, too. 1 is round. Not set because the dots are not always round when they are damaged, for example.
blob_params.maxCircularity = 3.4028234663852886e+38 # infinity.
blob_params.filterByConvexity = False
blob_params.minConvexity = 0.
blob_params.maxConvexity = 3.4028234663852886e+38
blob_params.filterByInertia = True # a second way to find round blobs.
blob_params.minInertiaRatio = 0.55 # 1 is round, 0 is anywhat
blob_params.maxInertiaRatio = 3.4028234663852886e+38 # infinity again
blob_params.minThreshold = 0 # from where to start filtering the image
blob_params.maxThreshold = 255.0 # where to end filtering the image
blob_params.thresholdStep = 5 # steps to go through
blob_params.minDistBetweenBlobs = 3.0 # avoid overlapping blobs. must be bigger than 0. Highly depending on image resolution!
blob_params.minRepeatability = 2 # if the same blob center is found at different threshold values (within a minDistBetweenBlobs), then it (basically) increases a counter for that blob. if the counter for each blob is >= minRepeatability, then it's a stable blob, and produces a KeyPoint, otherwise the blob is discarded.
res, keypoints = blobize(im2, blob_params)
我尝试在业余爱好项目中检测一些骰子上的一些点。 骰子切得很好,也有或多或少的好照片。
然后将照片灰度化,中值滤镜抗噪,做成np.array
让cv2喜欢
现在我尝试计算点数,然后......好吧...... SimpleBlobDetector
根据参数的精确调整,发现到处都是斑点,或者根本没有斑点,而且从来没有发现那些最明显的点最佳。特别是如果我激活“圆度”大于 0.7 或“惯性”,它什么也找不到。
这是怎么回事?我需要进一步预处理我的图片,还是在下面的参数中?
我尝试用高斯模糊交换滤镜,我还尝试对图像进行色调分离,以获得具有完全相同灰度值的相当大的区域。没有任何帮助。
我现在尝试了很多变体,当前的变体结果如下图所示。
blob_params = cv2.SimpleBlobDetector_Params()
blob_params.minDistBetweenBlobs = 1
blob_params.filterByCircularity = True
blob_params.minCircularity = 0.5
blob_params.minThreshold = 1
blob_params.thresholdStep = 1
blob_params.maxThreshold = 255
#blob_params.filterByInertia = False
#blob_params.minInertiaRatio = 0.2
blob_params.minArea = 6
blob_params.maxArea = 10000
detector = cv2.SimpleBlobDetector_create(blob_params)
keypoints = detector.detect(die_np) # detect blobs... just it doesn't work
image = cv2.drawKeypoints(die_np,
keypoints,
np.array([]),
(255,255,0),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
im = Image.fromarray(image)
im
好的,解决方案是:
有些参数甚至在您开始之前就设置好了。这些参数针对在浅色背景中查找深色和圆形斑点进行了优化。在我的形象中不是这样!这让我感到惊讶 - 在打印出每个参数并更正所有不适合我的用例的内容后,我终于能够使用此功能。现在它很容易找到几种不同类型的骰子上的骰子点,我试过了。
如果 openCV 参数列表更易于访问,例如 dict 或更好的注释,这会更容易。
我将在此处留下我的代码 - 它包含此函数使用的参数的完整列表,在注释中还说明了如何使用其中的一些参数,以及使用该函数的函数。我也留下了the link to the simpleBlobDetector documentation here,网上有点难找
来自C/C++背景,这个功能完全不是pythonic。它不接受所有图像格式,因为它在 python 上下文中是正常的,相反它需要一个非常特定的数据类型。在 python 中至少它会告诉你它想要什么,但是这个函数保持安静以免破坏谜语。然后它继续抛出异常而没有解释。
所以我正在制作一个函数,该函数至少接受彩色和 black/white 格式的 numpy,以及 PIL.Image。这使该功能的可用性提高了一点。
OpenCV,当您阅读本文时 - 通常在 python 中为“'triple marks'”中的每个函数提供可读文本。强调“可读性”。
import cv2
import numpy as np
from PIL import Image
def blobize(im, blob_params):
'''
Takes an image and tries to find blobs on this image.
Parameters
----------
im : nd.array, single colored. In case of several colors, the first
color channel is taken. Alternatively you can provide an
PIL.Image, which is then converted to "L" and used directly.
blob_params : a cv2.SimpleBlobDetector_Params() parameter list
Returns
-------
blobbed_im : A greyscale image with the found blobs circled in red
keypoints : an OpenCV keypoint list.
'''
if Image.isImageType(im):
im = np.array(im.convert("L"))
if isinstance(im, np.ndarray):
if (len(im.shape) >= 3
and im.shape[2] > 1):
im = im[:,:,0]
detector = cv2.SimpleBlobDetector_create(blob_params)
try:
keypoints = detector.detect(im)
except:
keypoints = None
if keypoints:
blobbed_im = cv2.drawKeypoints(im, keypoints, np.array([]),
(255,0,0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
else:
blobbed_im = im
return blobbed_im, keypoints
blob_params = cv2.SimpleBlobDetector_Params()
# images are converted to many binary b/w layers. Then 0 searches for dark blobs, 255 searches for bright blobs. Or you set the filter to "false", then it finds bright and dark blobs, both.
blob_params.filterByColor = False
blob_params.blobColor = 0
# Extracted blobs have an area between minArea (inclusive) and maxArea (exclusive).
blob_params.filterByArea = True
blob_params.minArea = 3. # Highly depending on image resolution and dice size
blob_params.maxArea = 400. # float! Highly depending on image resolution.
blob_params.filterByCircularity = True
blob_params.minCircularity = 0. # 0.7 could be rectangular, too. 1 is round. Not set because the dots are not always round when they are damaged, for example.
blob_params.maxCircularity = 3.4028234663852886e+38 # infinity.
blob_params.filterByConvexity = False
blob_params.minConvexity = 0.
blob_params.maxConvexity = 3.4028234663852886e+38
blob_params.filterByInertia = True # a second way to find round blobs.
blob_params.minInertiaRatio = 0.55 # 1 is round, 0 is anywhat
blob_params.maxInertiaRatio = 3.4028234663852886e+38 # infinity again
blob_params.minThreshold = 0 # from where to start filtering the image
blob_params.maxThreshold = 255.0 # where to end filtering the image
blob_params.thresholdStep = 5 # steps to go through
blob_params.minDistBetweenBlobs = 3.0 # avoid overlapping blobs. must be bigger than 0. Highly depending on image resolution!
blob_params.minRepeatability = 2 # if the same blob center is found at different threshold values (within a minDistBetweenBlobs), then it (basically) increases a counter for that blob. if the counter for each blob is >= minRepeatability, then it's a stable blob, and produces a KeyPoint, otherwise the blob is discarded.
res, keypoints = blobize(im2, blob_params)