如何使用Python计算OpenCV中的汽车数量?
我正在尝试使用OpenCV和Python自动计算图像中的汽车数量 起初我认为我可以通过一些细分来实现这一点,但我没有取得多大成功。然后,我认为Hough变换可能有助于计算汽车周围的边界,但它只能真正找出停车位线。我能想到的唯一一件事就是开始训练一些关于汽车和非汽车模板的比赛,但我希望有更简单的方法可以在这里做得更好。我还尝试了边缘检测,它看起来是积极的,但不确定如何继续:如何使用Python计算OpenCV中的汽车数量?,python,opencv,image-processing,Python,Opencv,Image Processing,我正在尝试使用OpenCV和Python自动计算图像中的汽车数量 起初我认为我可以通过一些细分来实现这一点,但我没有取得多大成功。然后,我认为Hough变换可能有助于计算汽车周围的边界,但它只能真正找出停车位线。我能想到的唯一一件事就是开始训练一些关于汽车和非汽车模板的比赛,但我希望有更简单的方法可以在这里做得更好。我还尝试了边缘检测,它看起来是积极的,但不确定如何继续: 快速matlab代码,可轻松转换为python,让您开始学习 b = rgb2hsv(I); se = strel('re
快速matlab代码,可轻松转换为python,让您开始学习
b = rgb2hsv(I);
se = strel('rectangle', [2,4]); %# structuring element
BW = b(:,:,3)>0.5;
BW2 = bwareaopen(BW,30);
BW3 = imerode(BW2, se);
BW4 = imdilate(BW3, se);
CC = bwconncomp(BW4);
从这里您知道,您需要查看CC的put结果并计算宽高比,因为您大概知道汽车有多大。这是我对BW4的输出结果
这看起来像是一种可能需要利用图像颜色成分的情况。显然,在平均亮度值上设置一个直线阈值将消除深色油漆的汽车。一种可能是探索颜色关系(红到绿、蓝到绿、红到蓝)以及饱和度。由于大多数汽车都是深灰色的,所以色调可能不会给你带来太多好处 我认为如果你能限制你感兴趣的区域,你的边缘检测方法可以工作。为了获得更好的边缘并消除停车线,在运行边缘检测之前,在彩色图像上使用2x2腐蚀过滤器。然后我建议使用更强的边缘检测方法(如sobel或prewitt)。你应该得到这样的结果(我的是在所有3个颜色通道上运行的): 然后,您可以转换为二进制,如果您想(不应该是必要的)或只是计算相关ROI中的像素
如果你正试图为移动的摄像机、多个批次、多个角度创建一些东西,那么你将需要一个更复杂的系统。但是对于一个固定的摄像头来说,类似这样的功能应该可以使用。汽车是具有高密度角的对象,因此,这为您提供了一些附加信息,以确定图像区域是否可能是汽车。我只是用
goodFeaturesToTrack
当maxCorners=10000,qualityLevel=0.01,MindDistance=1时,得到了这个结果
分别
这本身就是非常嘈杂的,但也许你可以将它与其他分割方法相结合。例如,您可以根据颜色分割计算“预期的汽车尺寸矩形”,并搜索具有高拐角密度的矩形。当你有一个非常结构化的情况,比如在示例图像中,你“知道”汽车应该在哪里,所以你只能检查这些区域。好的,所以。。。。我可能在这方面做了太多的工作,但似乎很简单 对于我的实现,我决定最好找到空的停车位,并假设所有其他停车位都被占用。为了确定一个停车位是否是空的,我只是将它与道路上停车位大小的部分进行比较。这意味着无论是亮还是暗,同样的算法都应该有效,因为模板是直接从图像中提取的 此时,我只做模板匹配(我尝试了各种方法,但
cv2.TM\u CCORR\u NORMED
效果最好)。这会产生一个不错的结果,现在我们需要处理它
我在停车场行周围创建ROI(感兴趣区域)。然后,通过对每列进行统计,将它们折叠为一个向量。我看的是平均数。
这是一个很好的指示器,你已经可以清楚地看到空的空间在哪里了。但是深色汽车仍然存在一些问题,所以现在我们决定看看另一个统计数据,方差如何?整个地区的停车场都很稳定。另一方面,一辆汽车有一些变化,车窗、车顶后视镜会产生一些变化。所以我画出了“反向”方差。因此,它的方差不是0,而是1。看起来像这样
这看起来很有希望!但你知道什么更好吗?把两者结合起来!让我们把它们相乘,我把这个结果叫做“概率”,因为它应该在0到1之间
现在你真的可以看到空白和黑色汽车之间的区别了。让我们做一些简单的阈值。这很好,但它没有给出车辆/空位的数量。在这一点上,我们逐列查看“概率”,并查找阈值上的特定数量的连续像素。有多少像素?大约和汽车宽度一样多的像素。这种“滞后”型模型应能抑制任何峰值或虚假数据点
现在所有这些加在一起,我们假设空间的数量是恒定的(我认为是合理的假设),我们只说汽车数量=空间数量-空空间数量
,然后标记图像
并打印一些结果
found 24 cars and 1 empty space(s) in row 1
found 23 cars and 0 empty space(s) in row 2
found 20 cars and 3 empty space(s) in row 3
found 22 cars and 0 empty space(s) in row 4
found 13 cars and 9 empty space(s) in row 5
当然,还有代码。这可能不是最有效的,但我是一个典型的matlab人员,这是我的第一个openCV/Python项目
import cv2
import numpy as np
from matplotlib import pyplot as plt
# this just keeps things neat
class ParkingLotRow(object):
top_left=None
bot_right=None
roi=None
col_mean=None
inverted_variance=None
empty_col_probability=None
empty_spaces=0
total_spaces=None
def __init__(self,top_left,bot_right,num_spaces):
self.top_left = top_left
self.bot_right = bot_right
self.total_spaces = num_spaces
############################ BEGIN: TWEAKING PARAMETERS ###########################################
car_width = 8 #in pixels
thresh = 0.975 #used to determine if a spot is empty
############################### END: TWEAKING PARAMETERS ###########################################
parking_rows = []
# defines regions of interest, row 1 is on top, row 5 is on bottom, values determined empirically
parking_rows.append(ParkingLotRow(( 1, 20),(496, 41),25)) #row 1
parking_rows.append(ParkingLotRow(( 1, 87),(462,105),23)) #row 2
parking_rows.append(ParkingLotRow(( 1,140),(462,158),23)) #row 3
parking_rows.append(ParkingLotRow(( 1,222),(462,240),22)) #row 4
parking_rows.append(ParkingLotRow(( 1,286),(462,304),22)) #row 5
#read image
img = cv2.imread('parking_lot.jpg')
img2 = img.copy()
#creates a template, its jsut a car sized patch of pavement
template = img[138:165,484:495]
m, n, chan = img.shape
#blurs the template a bit
template = cv2.GaussianBlur(template,(3,3),2)
h, w, chan = template.shape
# Apply template Matching
res = cv2.matchTemplate(img,template,cv2.TM_CCORR_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
#adds bounding box around template
cv2.rectangle(img,top_left, bottom_right, 255, 5)
#adds bounding box on ROIs
for curr_parking_lot_row in parking_rows:
tl = curr_parking_lot_row.top_left
br = curr_parking_lot_row.bot_right
cv2.rectangle(res,tl, br, 1, 5)
#displays some intermediate results
plt.subplot(121),plt.imshow(res,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title('Original, template in blue'), plt.xticks([]), plt.yticks([])
plt.show()
curr_idx = int(0)
#overlay on original picture
f0 = plt.figure(4)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)),plt.title('Original')
for curr_parking_lot_row in parking_rows:
#creates the region of interest
tl = curr_parking_lot_row.top_left
br = curr_parking_lot_row.bot_right
my_roi = res[tl[1]:br[1],tl[0]:br[0]]
#extracts statistics by column
curr_parking_lot_row.col_mean = np.mean(my_roi, 0)
curr_parking_lot_row.inverted_variance = 1 - np.var(my_roi,0)
curr_parking_lot_row.empty_col_probability = curr_parking_lot_row.col_mean * curr_parking_lot_row.inverted_variance
#creates some plots
f1 = plt.figure(1)
plt.subplot('51%d' % (curr_idx + 1)),plt.plot(curr_parking_lot_row.col_mean),plt.title('Row %d correlation' %(curr_idx + 1))
f2 = plt.figure(2)
plt.subplot('51%d' % (curr_idx + 1)),plt.plot(curr_parking_lot_row.inverted_variance),plt.title('Row %d variance' %(curr_idx + 1))
f3 = plt.figure(3)
plt.subplot('51%d' % (curr_idx + 1))
plt.plot(curr_parking_lot_row.empty_col_probability),plt.title('Row %d empty probability ' %(curr_idx + 1))
plt.plot((1,n),(thresh,thresh),c='r')
#counts empty spaces
num_consec_pixels_over_thresh = 0
curr_col = 0
for prob_val in curr_parking_lot_row.empty_col_probability:
curr_col += 1
if(prob_val > thresh):
num_consec_pixels_over_thresh += 1
else:
num_consec_pixels_over_thresh = 0
if (num_consec_pixels_over_thresh >= car_width):
curr_parking_lot_row.empty_spaces += 1
#adds mark to plt
plt.figure(3) # the probability graph
plt.scatter(curr_col,1,c='g')
plt.figure(4) #parking lot image
plt.scatter(curr_col,curr_parking_lot_row.top_left[1] + 7, c='g')
#to prevent doubel counting cars, just reset the counter
num_consec_pixels_over_thresh = 0
#sets axis range, apparantlly they mess up when adding the scatters
plt.figure(3)
plt.xlim([0,n])
#print out some stats
print('found {0} cars and {1} empty space(s) in row {2}'.format(
curr_parking_lot_row.total_spaces - curr_parking_lot_row.empty_spaces,
curr_parking_lot_row.empty_spaces,
curr_idx +1))
curr_idx += 1
#plot some figures
plt.show()
嗯,如果它拾取停车位线,你可以做一些分割,只要停车位大小可以是“给定的”。这就是说,提取停车场线,验证它是具有给定比例/大小的停车场,然后通过检查停车场内的区域来检查停车场内是否有车-可能使用一致性分析或其他方法。我不能假设停车位线总是存在。在这种情况下,从HSV颜色空间中选择V并进行一些形态学处理。我将发布一些快速的基本代码让你开始。你只是在这个特定的停车场解决这个问题吗?相机动过吗?如果摄影机和场景相当恒定,则可以大大简化问题。您可以创建一个小的感兴趣区域,每个点都应该位于该区域。然后比较这些区域中的值