初识图像处理:从入门到改行(3)

世上无难事,只要肯放弃!

这次本来打算做一个停车场视频,把空车位框起来的,但是由于我的pytorch始终没有办法构建好自己的数据集,虽然有大佬给的keras训练好的模型,而恰好我使用的是python3.8,安装keras有点麻烦。并且我很懒,所以这次试手只完成了一半。
好了,话不多说,开始。
先从视频里截一张图停车场
经典开局两件套

import cv2
import numpy as np
import torch


def imshow(img):
    cv2.imshow(str(img),img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

由于截图左上角部分是不需要的,所以先获取我们想要的部分

'''
获取停车场想要的部分
'''
img = img_gray.copy()
(y,x) = img.shape[:2]
# 用jupyter 手动调整的参数
mask = [(0.05*x,0.7*y),(0.34*x,0.5*y),(0.58*x,0.12*y),(0.91*x,0.12*y),(0.91*x,0.88*y),(0.05*x,0.88*y)]

I = np.zeros_like(img)

mask = np.array([mask],dtype = np.int)
# cv2.fillPoly 可以用任意点围成多边形并且指定围成图形的值
# mask 是一个三维矩阵 相当于只有一个元素 该元素有n个点 每个点有2个坐标x,y 可以用jupyter type一下看看类型
# 所以mask = np.array 时 list mask要多加一个[]
cv2.fillPoly(I,mask,255)

# cv2.bitwise_and() 对二者进行与操作
# 要求二者同类型 同数据类型 所以用zeros_like 生成I
img = cv2.bitwise_and(img, I)
imshow(img)

在这里插入图片描述

  • 接下来是直线检测
'''
直线检测
'''

# 先要进行边缘检测
img = cv2.Canny(img,160,220)

# 直线检测

#输入的图像需要是边缘检测后的结果
#minLineLengh(线的最短长度,比这个短的都被忽略)和MaxLineCap(两条直线之间的最大间隔,小于此值,认为是一条直线)
#rho距离精度,theta角度精度,threshod超过设定阈值才被检测出线段
# 返回值是个三维数组 (n,1,4) n条直线,1,4个值x1,y1,x2,y2
lines = cv2.HoughLinesP(img, rho=0.1, theta=np.pi/10, threshold=15, minLineLength=9, maxLineGap=4)

在这里插入图片描述

简单讲一下 hough直线检测,
hough直线检测是把y=kx+b 通过x=rcos()转换成极坐标,
这样得到r和theta的一点,对应y=kx+b一条直线。
当极坐标的点重合的越多,说明共y=kx+b这条线上的线段越多。
当重合的数量达到一定阈值,就认为存在一条直线。

什么,你说你不知道canny边缘检测?
canny我的理解简单来说就是选择局部最大梯度的点
然后比较大小,小于第一个参数的直接判断非边缘
大于第二个参数的判断为边缘
大于第一个,小于第二个则看它旁边的点是否为边缘

  • 筛选直线
# 筛选直线
img_1 = img_rgb.copy()
line_n =[]
for line in lines:
    x1,y1,x2,y2 = line[0]
    if abs(x2-x1) <55 and abs(x2-x1)>25:
        if abs(y2-y1)<1:
            line_n.append((x1,y1,x2,y2))
            # cv2.line(图像,起点,终点,颜色,粗)
            cv2.line(img_1,(x1,y1),(x2,y2),(0,255,0),2)

imshow(img_1)

import operator

# operator.itemgetter是一个函数,获取对应维的数
# 按起点对列表排序
line = sorted(line_n, key=operator.itemgetter(0, 1))

  • 分块
'''
分块
'''
park = {}
# 用range是为了方便访问下一个线 len-1 是避免i+1越界
num = 0
for i in range(len(line) - 1):
    # distance 是两天直线起点的距离
    distance = abs(line[i][0] - line[i + 1][0])
    if num not in park.keys():
        park[num] = []
    if distance < 20:
        park[num].append(line[i])
    else:
        park[num].append(line[i])
        num += 1


''''
for j in range(len(park)):
    img_2 = img_1.copy()
    for i in park[j]:
        cv2.line(img_2,(i[0],i[1]),(i[2],i[3]),(0,0,255),2)
    imshow(img_2)
'''

在这里插入图片描述
用了循环,红色的是同一个块更加直观

  • 把每一个块框出来
'''
把块框出来
'''
# 因为每块停车位底部是同一条直线 所以选max_y为底
max_y=0
rec = []
# 字典的遍历默认是访问键
for key in park:
    min_y = img_gray.shape[0]
    long = 0
    sum = 0
    # 找出最上方的的直线到max_y作为高,最长线的长度为宽,x均值为起点
    # 因为找到的线都偏短,x的均值会偏右 所以给x设置一个偏移量
    shift = 10
    # 最长的线一般偏短,所以加一点补充
    long_sup = 3
    for line in park[key]:
        distance = abs(line[2]-line[0])
        if distance > long:
            long = distance
        if line[1]>max_y:
            max_y = line[1]
        if line[1]<min_y:
            min_y = line[1]
        sum += line[0]
    avg = int(sum/len(park[key]))-shift
    long += long_sup
    # 其实左上和右下两个点就能表示矩形了
    rec.append([[avg,max_y],[avg,min_y],[avg+long,min_y],[avg+long,max_y]])
for i in rec:
    i[0][1]=max_y
    i[3][1]=max_y

在这里插入图片描述
同样每块单独框出来

  • 微调
# 对每组车位左上角的y进行细调

adjust =np.array( [-6,1,0,-4,3,-4,4,-3,0,0,-3,-5])
j=0
for i in rec:
    i[1][1]+=adjust[j]
    i[2][1]+=adjust[j]
    j+=1
'''
for i in rec:
    img_3 = img_rgb.copy()
    # rectangle 里 坐标是元组
    cv2.rectangle(img_3,tuple(i[1]),tuple(i[3]),(255,0,0),2)
    imshow(img_3)

'''

框选车位

'''
# 将每一个单独的车位画出来
'''
# 每一个车位的高度差gap
gap = 15.5
car_park = []
item = 0
for i in rec:

    height = abs(i[1][1] - i[0][1])
    width = i[3][0] - i[0][0]
    num = int(height / gap)
    # num+ 1个空位 有一个空位不完整
    for j in range(num + 1):
        # 记录车位的左上和右下坐标
        if item < 1 or item > 10:
            car_park.append([[i[1][0], i[1][1] + int(j * gap)], [i[2][0], i[2][1] + int(j * gap + gap)]])

        else:
            car_park.append([[i[1][0], i[1][1] + int(j * gap)], [i[1][0] + int(width / 2), i[2][1] + int(j * gap + gap)]])
            car_park.append([[i[1][0] + int(width / 2), i[1][1] + int(j * gap)], [i[2][0], i[2][1] + int(j * gap + gap)]])
    item += 1


img_4 = img_rgb.copy()
for i in car_park:
    cv2.rectangle(img_4, tuple(i[0]), tuple(i[1]), (255, 0, 0), 2)
imshow(img_4)

在这里插入图片描述
到此位置都很简单,难点在后面?
(其实我觉得也不难,但是就是报一些搜不到原因的错)

后面就是深度学习训练模型,把框的车位放入模型进行预测。然后从视频里读取帧进行框选。目前还没能成功,以后有机会再弄吧。下一期再见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值