通过使用质心之间的欧氏距离提高检测精度
improving the detection accuracy by using euclidean distance between its Centroids
我正在做一个项目,我必须从鸟瞰的视频帧中检测彩色汽车
查看。
为了进行检测,我使用直方图反投影获得一个二值图像,该图像假设只包含感兴趣的目标区域。
这个过程运行良好,直到我尝试通过在包含具有相似颜色分布的对象的视频上测试它来概括检测(比如我在 table 下爬行并且我的部分 T 恤可见)
可以看到,汽车和无关物体都在移动,检测结果为:
如您所见,二值图像中显示了具有相似颜色分布的不相关对象。但是,感谢 Stack overflow 专家,我可以通过添加以下约束告诉算法选择代表目标对象的 blob 来改进检测:
1-矩形检查
2 面积和比例检查
在上述约束条件下,我可以去除检测到的大的无关对象。然而,对于小物体(见二值图像),它的作用不大 因为目标物体(红色小车)的矩形度范围在 (0.72 和 1)[=50 之间=]和无关紧要的小物件确实属于这个范围。所以我决定添加另一个约束,计算每 5 个连续帧移动的汽车质心之间的距离,并通过流动计算取决于该距离的阈值:
import scipy.spatial.distance
from collections import deque
#defining the Centroid
centroids=deque(maxlen=40) #double ended queue containing the detected centroids
.
.
.
centroids.appendleft(center)
#center comes from detection process. e.g centroids=[(120,130), (125,132),...
Distance = scipy.spatial.distance.euclidean(pts1_red[0], pts1_red[5])
if D<=50:
#choose that blob
所以在不同的视频上进行了测试,结果是质心之间的距离 范围在 0 到 50 之间(汽车停止时为 0)。
所以我的问题是:
有什么方法可以让我投资这个 属性 以便它可以帮助增强检测,从而使检测忽略 T 恤?,因为当汽车不再可见并且无关物体停留会计算无关物体的距离差,这个距离会变小,直到小于50!
提前致谢
根据OP提供的信息,这里有一个解决这个问题的方法。
示例图片
我创建了一些示例图像,大致代表了随时间移动的物体。中心对象代表我们正在寻找的汽车,其他对象已被分类器错误地检测到。
前四张图片表示一辆汽车(中心物体)从左向右移动,以及其他两个检测不正确的物体。在第五张图片中,汽车已经移出画面,但仍然存在两个错误检测。第六帧由一辆新车进入帧和其他错误检测组成。
解决方案-代码
评论包含有关算法的信息。我们正在计算每个 blob 的质心,并将其与之前 detected/extracted blob 的质心进行比较。
import os
import cv2
import numpy as np
# Reading files and sorting them in the right order
all_files = os.listdir(".")
all_images = [file_name for file_name in all_files if file_name.endswith(".png")]
all_images.sort(key=lambda k: k.split(".")[0][-1])
print(all_images) #
# Initially, no centroid information is available.
previous_centroid_x = -1
previous_centroid_y = -1
DIST_THRESHOLD = 30
for i, image_name in enumerate(all_images):
rgb_image = cv2.imread(image_name)
height, width = rgb_image.shape[:2]
gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray_image, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
blankImage = np.zeros_like(rgb_image)
for cnt in contours:
# Refer to https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#moments
M = cv2.moments(cnt)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# Refer to https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/
# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_properties/py_contour_properties.html#contour-properties
extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
extTop = tuple(cnt[cnt[:, :, 1].argmin()][0])
extBot = tuple(cnt[cnt[:, :, 1].argmax()][0])
color = (0, 0, 255)
if i == 0: # First frame - Assuming that you can find the correct blob accurately in the first frame
# Here, I am using a simple logic of checking if the blob is close to the centre of the image.
if abs(cY - (height / 2)) < DIST_THRESHOLD: # Check if the blob centre is close to the half the image's height
previous_centroid_x = cX # Update variables for finding the next blob correctly
previous_centroid_y = cY
DIST_THRESHOLD = (extBot[1] - extTop[1]) / 2 # Update centre distance error with half the height of the blob
color = (0, 255, 0)
else:
if abs(cY - previous_centroid_y) < DIST_THRESHOLD: # Compare with previous centroid y and see if it lies within Distance threshold
previous_centroid_x = cX
previous_centroid_y = cY
color = (0, 255, 0)
cv2.drawContours(blankImage, [cnt], 0, color, -1)
cv2.circle(blankImage, (cX, cY), 3, (255, 0, 0), -1)
cv2.imwrite("result_" + image_name, blankImage)
更新阈值使算法能够跨帧跟踪对象的质心。由于对象可以上下移动一点,我们希望将当前帧中找到的对象的质心与上一帧中找到的汽车的质心相匹配。
解决方案 - 结果
绿色 - 选定的 blob
红色 - 被拒绝的 blob
对象中心也已标记以供参考。
注意 - 这不是一个完美的解决方案。它有几个限制,但它可以帮助您为您的问题设计一个近似的解决方案。
我正在做一个项目,我必须从鸟瞰的视频帧中检测彩色汽车 查看。
为了进行检测,我使用直方图反投影获得一个二值图像,该图像假设只包含感兴趣的目标区域。
这个过程运行良好,直到我尝试通过在包含具有相似颜色分布的对象的视频上测试它来概括检测(比如我在 table 下爬行并且我的部分 T 恤可见)
可以看到,汽车和无关物体都在移动,检测结果为:
如您所见,二值图像中显示了具有相似颜色分布的不相关对象。但是,感谢 Stack overflow 专家,我可以通过添加以下约束告诉算法选择代表目标对象的 blob 来改进检测:
1-矩形检查 2 面积和比例检查
在上述约束条件下,我可以去除检测到的大的无关对象。然而,对于小物体(见二值图像),它的作用不大 因为目标物体(红色小车)的矩形度范围在 (0.72 和 1)[=50 之间=]和无关紧要的小物件确实属于这个范围。所以我决定添加另一个约束,计算每 5 个连续帧移动的汽车质心之间的距离,并通过流动计算取决于该距离的阈值:
import scipy.spatial.distance
from collections import deque
#defining the Centroid
centroids=deque(maxlen=40) #double ended queue containing the detected centroids
.
.
.
centroids.appendleft(center)
#center comes from detection process. e.g centroids=[(120,130), (125,132),...
Distance = scipy.spatial.distance.euclidean(pts1_red[0], pts1_red[5])
if D<=50:
#choose that blob
所以在不同的视频上进行了测试,结果是质心之间的距离 范围在 0 到 50 之间(汽车停止时为 0)。
所以我的问题是:
有什么方法可以让我投资这个 属性 以便它可以帮助增强检测,从而使检测忽略 T 恤?,因为当汽车不再可见并且无关物体停留会计算无关物体的距离差,这个距离会变小,直到小于50!
提前致谢
根据OP提供的信息,这里有一个解决这个问题的方法。
示例图片
我创建了一些示例图像,大致代表了随时间移动的物体。中心对象代表我们正在寻找的汽车,其他对象已被分类器错误地检测到。
前四张图片表示一辆汽车(中心物体)从左向右移动,以及其他两个检测不正确的物体。在第五张图片中,汽车已经移出画面,但仍然存在两个错误检测。第六帧由一辆新车进入帧和其他错误检测组成。
解决方案-代码
评论包含有关算法的信息。我们正在计算每个 blob 的质心,并将其与之前 detected/extracted blob 的质心进行比较。
import os
import cv2
import numpy as np
# Reading files and sorting them in the right order
all_files = os.listdir(".")
all_images = [file_name for file_name in all_files if file_name.endswith(".png")]
all_images.sort(key=lambda k: k.split(".")[0][-1])
print(all_images) #
# Initially, no centroid information is available.
previous_centroid_x = -1
previous_centroid_y = -1
DIST_THRESHOLD = 30
for i, image_name in enumerate(all_images):
rgb_image = cv2.imread(image_name)
height, width = rgb_image.shape[:2]
gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray_image, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
blankImage = np.zeros_like(rgb_image)
for cnt in contours:
# Refer to https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#moments
M = cv2.moments(cnt)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# Refer to https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/
# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_properties/py_contour_properties.html#contour-properties
extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
extTop = tuple(cnt[cnt[:, :, 1].argmin()][0])
extBot = tuple(cnt[cnt[:, :, 1].argmax()][0])
color = (0, 0, 255)
if i == 0: # First frame - Assuming that you can find the correct blob accurately in the first frame
# Here, I am using a simple logic of checking if the blob is close to the centre of the image.
if abs(cY - (height / 2)) < DIST_THRESHOLD: # Check if the blob centre is close to the half the image's height
previous_centroid_x = cX # Update variables for finding the next blob correctly
previous_centroid_y = cY
DIST_THRESHOLD = (extBot[1] - extTop[1]) / 2 # Update centre distance error with half the height of the blob
color = (0, 255, 0)
else:
if abs(cY - previous_centroid_y) < DIST_THRESHOLD: # Compare with previous centroid y and see if it lies within Distance threshold
previous_centroid_x = cX
previous_centroid_y = cY
color = (0, 255, 0)
cv2.drawContours(blankImage, [cnt], 0, color, -1)
cv2.circle(blankImage, (cX, cY), 3, (255, 0, 0), -1)
cv2.imwrite("result_" + image_name, blankImage)
更新阈值使算法能够跨帧跟踪对象的质心。由于对象可以上下移动一点,我们希望将当前帧中找到的对象的质心与上一帧中找到的汽车的质心相匹配。
解决方案 - 结果
绿色 - 选定的 blob 红色 - 被拒绝的 blob 对象中心也已标记以供参考。
注意 - 这不是一个完美的解决方案。它有几个限制,但它可以帮助您为您的问题设计一个近似的解决方案。