我试图使用OpenCV和Python自动计算图像中的汽车数量。
最初我认为我可以通过一些细分来做到这一点,但我没有取得多大成功。然后我认为霍夫变换可能有助于计算汽车周围的边界,但它只是真正选择了停车位线。我唯一能想到的就是开始训练一些关于汽车和非汽车模板的比赛,但我希望有更简单的东西可以在这里做得很好。我也试过边缘检测,看起来很积极,但不确定如何继续:
答案 0 :(得分:5)
好的,所以....我可能在这方面做了太多工作,但看起来很简单。
对于我的实施,我决定最好找到空的停车位,并假设所有其他空间都被占用。为了确定一个地点是否为空,我只是将它与道路的停车位大小部分进行比较。这意味着相同的算法无论是亮还是暗等都应该起作用,因为模板是直接从图像中提取的。
此时我只是进行模板匹配(我尝试了各种方法,但cv2.TM_CCORR_NORMED
效果最好)。这给出了一个不错的结果,现在我们需要处理它。
我在停车场行周围创建了ROI(感兴趣的区域)。然后我通过每列统计数据将它们折叠为单个向量。我看一下这个意思。
它是一个非常好的指标,你已经可以清楚地看到空白的位置。但深色车仍然存在一些问题,所以现在我们决定看另一个统计数据,方差怎么样?停车场在整个地区都非常稳定。另一方面,汽车有一些变化,窗户,屋顶镜子有一些变化。所以我用"倒置"方差。因此,方差为0时,不是没有变化,而是方差为1.它看起来像这样
这看起来非常有前途!但你知道什么更好吗?结合这两个!所以让我们将它们相乘,我将这个结果称为"概率"因为它应该介于0和1之间
现在你可以真正看到空白区域和黑暗车厢之间的区别。所以我们做一些简单的门槛。这很好,但它没有给你车辆/空位数。在这一点上,我们经历了"概率"逐列,我们在阈值上查找一定数量的连续像素。多少像素?与汽车一样多的像素很宽。这"滞后"类型模型应该抑制任何峰值或虚假数据点。
现在一切都在一起,我们假设空格的数量是不变的(我认为是合理的假设),我们只是说number of cars = number of spaces - number of empty spaces
并标记图像
并打印一些结果
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()
答案 1 :(得分:2)
这看起来像是您可能想要利用图像的颜色分量的情况。显然,平均亮度值的直线阈值将消除黑漆的汽车。一种可能性是探索颜色关系(红色到绿色,蓝色到绿色,红色到蓝色)以及饱和度。 Hue可能不会让你感觉太多,因为大多数车都是灰色的。
如果您可以限制您感兴趣的区域,我认为您的边缘检测方法可以正常工作。为了获得更好的优势并消除停车线,在运行边缘检测之前,请在彩色图像上使用2x2的侵蚀过滤器。然后我建议使用更强大的边缘检测方法(如sobel或prewitt)。你应该得到这样的东西(我的是在所有3个颜色通道上运行):
然后,您可以根据需要转换为二进制(不应该是必需的)或只计算相关ROI中的像素。
如果您正在尝试创建移动相机,多个批次,多个角度的东西,那么您将需要一个更复杂的系统。但是对于一个固定的相机,这样的东西应该可以工作。
答案 2 :(得分:1)
快速的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的放置结果并计算宽高比,因为你大致了解汽车的大小。这是BW4的结果。
答案 3 :(得分:0)