通过一些实践项目的练习,总结下图像处理的一般过程方法:
原始图–>灰度图–>高斯滤波,消除噪声–>二值图–>中值滤波,消除噪声–>膨胀处理–>数据处理(如:求得坐标,划线)–>图像融合
(1) 原图
w, h =image.shape[:2] 获取每帧图片的宽和高
image.shape[0], 图片垂直尺寸
image.shape[1], 图片水平尺寸
image.shape[2], 图片通道数
(2) 灰度图:cv2.cvtColor() 颜色空间转换
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 彩色图转灰度图
(3) cv2.GaussianBlur() 高斯滤波,线性平滑滤波,适用于消除高斯噪声
语法:cv2.GaussianBlur(src, ksize, sigmaX, sigmaY, borderType)-> dst
src 输入图像。
ksize 高斯内核大小。 ksize.width和ksize.height可以不同,但它们都必须为正数和奇数,也可以为零,然后根据sigmaX和sigmaY计算得出。
sigmaX X方向上的高斯核标准偏差。
sigmaY Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,则分别从ksize.width和ksize.height计算得出:
sigmaX=0.3×[(ksize.width-1)×0.5-1] +0.8
sigmaY=0.3×[(ksize.height-1)×0.5-1]+0.8
borderType是边界样式,该值决定了以何种方式处理边界。一般情况下,不需要考虑该值,直接采用默认值即可。在该函数中,sigmaY和borderType是可选参数。sigmaX是必选参数
dst 输出图像的大小和类型与src相同。
函数cv2.GaussianBlur() 的常用形式为:dst=cv2.GaussianBlur(src,ksize,0,0)
(4) cv2.adaptiveThreshold() 用于图像自适应阈值二值化
语法:dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)
dst: 输出图
src: 输入图,只能输入单通道图像,通常来说为灰度图
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
thresh_type: 阈值的计算方法,包含以下2种类型:
cv2.ADAPTIVE_THRESH_MEAN_C: 区域内均值
cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 区域内像素点加权和,权重为一个高斯窗口
type:二值化操作的类型,与固定阈值函数相同,用于控制参数2 maxval,包含以下5种类型:
cv2.THRESH_BINARY: 黑白二值
cv2.THRESH_BINARY_INV:黑白二值反转
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
Block Size: 图片中区域的大小,取奇数
C:阈值计算方法中的常数项
注:通过规定一个区域大小,比较处理像素点与区域大小里面像素点的平均值。阈值(或者其他特征)的大小关系确定这个像素点是属于黑或者白(如果是二值情况)。(经验之谈:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在寻找轮廓时会找到图片最外面的一个框。其中红色和白色更容易检测到)
(5) cv2.medianBlur() 图像滤波:中值滤波,可对灰色图像和彩色图像使用,中值滤波对噪声的消除效果比线性滤波好,但是随着滤波核的增大,图像也会变模糊
语法:dst=cv2.medianBlur(src,ksize)
dst是返回值,表示进行中值滤波后得到的处理结果。
src 是需要处理的图像,即源图像
ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中其邻域图像的高度和宽度。需要注意,核大小必须是比1大的奇数,比如3、5、7等
(6) cv2.dilate()函数对图片进行膨胀处处理
语法:cv2.dilate(img, kernel, iteration)
img – 目标图片
kernel – 进行操作的内核,默认为3×3的矩阵
iterations – 膨胀次数,默认为1
应用:
kernel = np.ones((4, 4), np.uint8)
img_dilate = cv2.dilate(img, kernel, iterations = 1)
(7) cv2.getRotationMatrix2D() 旋转矩阵,对图片使用该旋转矩阵,只是让图片绕着左上角进行旋转
语法: cv2.getRotationMatrix2D(center, angle, scale)
center:旋转中心坐标,是一个元组参数(col, row)
angle:旋转角度,旋转方向,负号为逆时针,正号为顺时针
scale:旋转后图像相比原来的缩放比例,1为等比例缩放
(8) cv2.warpAffine 计算变换后的平移图像
dist = cv2.warpAffine(src, M, dsize)
src – 输入图像。
M – 变换矩阵。
dsize – 输出图像的大小。
通过像素点数量检测车位上是否有停车, 代码实现步骤如下:
# 处理视频图像
def detect():
# 为了使裁剪后的单个车位里面没有绘制的边框,需要在画车位框之前,把原图像复制一份
imgCopy = img.copy()
# 获得整每帧图片的宽和高
img_w, img_h = img.shape[:2] #shape是(w,h,c)
# ==1== 转换灰度图,通过形态学处理来检测车位内有没有车
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# ==2== 高斯滤波,卷积核3*3,沿x和y方向的卷积核的标准差为1
imgGray = cv2.GaussianBlur(imgGray, (3,3), 1)
# ==3== 二值图,自适应阈值方法
imgThresh = cv2.adaptiveThreshold(imgGray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 101, 20)
# ==4== 删除零散的白点,
# 如果车位上有车,那么车位上的像素数量(白点)很多,如果没有车,车位框内基本没什么白点
imgMedian = cv2.medianBlur(imgThresh, 5)
# ==5== 扩张白色部分,膨胀
kernel = np.ones((3,3), np.uint8) # 设置卷积核
imgDilate = cv2.dilate(imgMedian, kernel, iterations=1) # 迭代次数为1
#(4)绘制车位线矩形框
w, h = 175,300 # 矩形框的宽和高
# 遍历所有的矩形框坐标
for pos in posList:
# 得到旋转后的矩形的四个角坐标,传入原图,旋转参考点坐标,矩形框左上角坐标,框的宽w和高h,逆时针转4°(#根据实际情况修改)
angle = recRota(imgDilate, pos[0], pos[1], pos[0], pos[1], w, h, -5, draw=False) # 裁剪的车位不绘制车位图
#(5)裁剪所有的车位框,由于我们的矩形是倾斜的,先要把矩形转正之后再裁剪
# 变换矩阵,以每个矩形框的左上坐标为参考点,顺时针寻转4°,旋转后的图像大小不变
rota_params = cv2.getRotationMatrix2D(angle[0], angle=-5, scale=1) ##根据实际情况修改
# 旋转整张帧图片,输入img图像,变换矩阵,指定输出图像大小
rota_img = cv2.warpAffine(imgDilate, rota_params, (img_w, img_h))
# 裁剪摆正了的矩形框,先指定高h,再指定宽w
imgCrop = rota_img[pos[1]:pos[1]+h, pos[0]:pos[0]+w]
# 显示裁剪出的图像
# cv2.imshow('imgCrop', imgCrop)
#(6)计算每个裁剪出的单个车位有多少个像素点
count = cv2.countNonZero(imgCrop)
# 将计数显示在矩形框上
cv2.putText(imgCopy, str(count), (pos[0]+5, pos[1]+20), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0,255,255), 2)
#(7)确定车位上是否有车
if count < 3000: # 像素数量小于2500辆就是没有车
color = (0,255,0) # 没有车的话车位线就是绿色
spacePark ="Empty" # 每检测到一个空车位,数量就加一
else:
color = (0,0,255) # 有车时车位线就是红色
spacePark ="No empty"
#(8)绘制所有车位的矩形框
# 在复制后的图像上绘制车位框
imgCopy = drawLine(imgCopy, angle, color, 3)
# 绘制车位空闲标识
# cv2.rectangle(imgCopy, (0,150), (200,210), (255,255,0), cv2.FILLED)
cv2.rectangle(imgCopy, (0,0), (195,65), (255,255,255), 3) #白色
cv2.putText(imgCopy, spacePark, (15,40), cv2.FONT_HERSHEY_COMPLEX, 1, (255,0,255), 3)
# cv2.imshow('img', imgCopy)
# cv2.imshow('imgGray', imgGray) # 高斯滤波后
# cv2.imshow('imgThresh', imgThresh) # 二值化后
# cv2.imshow('imgMedian', imgMedian) # 模糊后
# cv2.imshow('imgDilate', imgDilate) # 膨胀
return imgCopy
参考链接:停车场空余车位检测