OpenCV入门9——目标识别(车辆统计)

文章目录

  • 图像轮廓
  • 查找轮廓
  • 绘制轮廓
  • 轮廓的面积与周长
  • 多边形逼近与凸包
  • 外接矩形
  • 项目总览【车辆统计】
  • 视频加载【车辆统计】
  • 去背景【车辆统计】
  • 形态学处理【车辆统计】
  • 逻辑处理【车辆统计】
  • 显示信息【车辆统计】

图像轮廓

OpenCV入门9——目标识别(车辆统计)_第1张图片
OpenCV入门9——目标识别(车辆统计)_第2张图片
OpenCV入门9——目标识别(车辆统计)_第3张图片
OpenCV入门9——目标识别(车辆统计)_第4张图片
OpenCV入门9——目标识别(车辆统计)_第5张图片
OpenCV入门9——目标识别(车辆统计)_第6张图片
OpenCV入门9——目标识别(车辆统计)_第7张图片
OpenCV入门9——目标识别(车辆统计)_第8张图片
OpenCV入门9——目标识别(车辆统计)_第9张图片
OpenCV入门9——目标识别(车辆统计)_第10张图片
OpenCV入门9——目标识别(车辆统计)_第11张图片

查找轮廓

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('./contours1.jpeg')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

cv2.imshow('img', img)
cv2.imshow('binary', binary)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

print(contours)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第12张图片
OpenCV入门9——目标识别(车辆统计)_第13张图片

绘制轮廓

OpenCV入门9——目标识别(车辆统计)_第14张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('./contours1.jpeg')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

print(contours)

# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)

cv2.imshow('img', img)
cv2.imshow('binary', binary)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第15张图片
详细可参考官方资料

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('./contours1.jpeg')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print(contours)

# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)

cv2.imshow('img', img)
cv2.imshow('binary', binary)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第16张图片
OpenCV入门9——目标识别(车辆统计)_第17张图片
OpenCV入门9——目标识别(车辆统计)_第18张图片

轮廓的面积与周长

OpenCV入门9——目标识别(车辆统计)_第19张图片
OpenCV入门9——目标识别(车辆统计)_第20张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('./contours1.jpeg')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print(contours)

# 绘制轮廓
cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
area = cv2.contourArea(contours[0])
print("area=%d"%(area))

# 计算周长
len = cv2.arcLength(contours[0], True)
print("len=%d"%(len))

# cv2.imshow('img', img)
# cv2.imshow('binary', binary)

# key = cv2.waitKey(0) & 0xff
# if key == ord('q'):
#     cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第21张图片

多边形逼近与凸包

OpenCV入门9——目标识别(车辆统计)_第22张图片
OpenCV入门9——目标识别(车辆统计)_第23张图片
OpenCV入门9——目标识别(车辆统计)_第24张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

img = cv2.imread('./hand.png')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

print(len(contours))

# 绘制轮廓
cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))

# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))

cv2.imshow('img', img)
# cv2.imshow('binary', binary)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第25张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

def drawShape(src, points):
    i = 0
    while i < len(points):
        if(i == len(points) - 1):
            x, y = points[i][0]
            x1, y1 = points[0][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        else:
            x, y = points[i][0]
            x1, y1 = points[i + 1][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        i = i + 1

img = cv2.imread('./hand.png')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# print(len(contours))

# 绘制轮廓
# cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))

# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))

e = 5
approx = cv2.approxPolyDP(contours[0], e, True)
drawShape(img, approx)

hull = cv2.convexHull(contours[0])
drawShape(img, hull)

cv2.imshow('img', img)
# cv2.imshow('binary', binary)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第26张图片

外接矩形

OpenCV入门9——目标识别(车辆统计)_第27张图片
红框就是最小外接矩形,绿框就是最大外接矩形。

最小外接矩形可以看图形有没有旋转
OpenCV入门9——目标识别(车辆统计)_第28张图片
OpenCV入门9——目标识别(车辆统计)_第29张图片
OpenCV入门9——目标识别(车辆统计)_第30张图片
OpenCV入门9——目标识别(车辆统计)_第31张图片
详情见参考文档
OpenCV入门9——目标识别(车辆统计)_第32张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

def drawShape(src, points):
    i = 0
    while i < len(points):
        if(i == len(points) - 1):
            x, y = points[i][0]
            x1, y1 = points[0][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        else:
            x, y = points[i][0]
            x1, y1 = points[i + 1][0]
            cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)
        i = i + 1

img = cv2.imread('./hello.jpeg')
# print(img.shape)

# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)

# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# print(len(contours))

# 绘制轮廓
# cv2.drawContours(img, contours, 1, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))

# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))

# e = 5
# 多边形逼近
# approx = cv2.approxPolyDP(contours[0], e, True)
# drawShape(img, approx)

# 凸包
# hull = cv2.convexHull(contours[0])
# drawShape(img, hull)

r = cv2.minAreaRect(contours[1])
box = cv2.boxPoints(r)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)

x, y, w, h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)

cv2.imshow('img', img)
# cv2.imshow('binary', binary)

key = cv2.waitKey(0) & 0xff
if key == ord('q'):
    cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第33张图片

项目总览【车辆统计】


OpenCV入门9——目标识别(车辆统计)_第34张图片
OpenCV入门9——目标识别(车辆统计)_第35张图片

视频加载【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

while True:
    ret, frame = cap.read()

    if(ret == True):
        cv2.imshow('video', frame)

    key = cv2.waitKey(1)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()

去背景【车辆统计】

如果视频是25fps,即每秒25帧,即1000ms过25帧,那么200ms就走5帧(25/1000*200=5)
OpenCV入门9——目标识别(车辆统计)_第36张图片
OpenCV入门9——目标识别(车辆统计)_第37张图片
运动的物体为前景,静止的物体就是背景

详细可以参考官方文档

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

bgsubmog = cv2.createBackgroundSubtractorMOG2()
while True:
    ret, frame = cap.read()

    if(ret == True):
        mask = bgsubmog.apply(frame)
        cv2.imshow('video', mask)

    key = cv2.waitKey(1)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第38张图片

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

bgsubmog = cv2.createBackgroundSubtractorMOG2()
tst = cv2.createBackgroundSubtractorMOG2()

while True:
    ret, frame = cap.read()

    if(ret == True):
        # 灰度图
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪(高斯)
        blur = cv2.GaussianBlur(frame, (3, 3), 5)
        # 去背景
        mask = bgsubmog.apply(blur)
        t = tst.apply(frame)

        cv2.imshow('video', mask)
        cv2.imshow('t', t)

    key = cv2.waitKey(40)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()

OpenCV入门9——目标识别(车辆统计)_第39张图片

形态学处理【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as np

cap = cv2.VideoCapture('./video.mp4')

bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()

# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

while True:
    ret, frame = cap.read()

    if(ret == True):
        # 灰度图
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪(高斯)
        blur = cv2.GaussianBlur(frame, (3, 3), 1)
        # 去背景
        mask = bgsubmog.apply(blur)
        # t = tst.apply(frame)

        # 腐蚀,去掉图中小斑块
        erode = cv2.erode(mask, kernel, iterations=1)

        # 膨胀,还原放大
        dilate = cv2.dilate(erode, kernel2, iterations=5)

        # 闭操作,去掉物体内部噪声
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
        close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)

        contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        for i, c in enumerate(contours):
            x, y, w, h = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

        cv2.imshow('video', frame)
        # cv2.imshow('erode', close)

    key = cv2.waitKey(40)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()


逻辑处理【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as np

min_w = 50
min_h = 50
max_w = 800
max_h = 800

# 检测线的高度
line_high = 480

# 存放有效车辆数组
cars = []

# 统计车的数量
carnums = 0

# 线的偏移
offset = 10

# 求中心点
def center(x, y, w, h):
    x1 = int(w / 2)
    y1 = int(h / 2)
    cx = x + x1
    cy = y + y1
    return cx, cy

cap = cv2.VideoCapture('./video.mp4')

bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()

# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

while True:
    ret, frame = cap.read()

    if(ret == True):
        # print(frame.shape)
        # (584, 1280, 3)
        # 灰度图
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪(高斯)
        blur = cv2.GaussianBlur(frame, (3, 3), 1)
        # 去背景
        mask = bgsubmog.apply(blur)
        # t = tst.apply(frame)

        # 腐蚀,去掉图中小斑块
        erode = cv2.erode(mask, kernel, iterations=1)

        # 膨胀,还原放大
        dilate = cv2.dilate(erode, kernel2, iterations=3)

        # 闭操作,去掉物体内部噪声
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
        close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)

        contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        cv2.line(frame, (100, line_high), (1100, line_high), (255, 255, 0), 2)

        for i, c in enumerate(contours):
            x, y, w, h = cv2.boundingRect(c)

            # 对车辆的宽高进行判断,以验证是否是有效车辆
            isValid = (x >= min_w) and (h >= min_h) and (x <= max_w) and (h <= max_h)
            if(not isValid):
                continue

            # 有效的车
            cpoint = center(x, y, w, h)
            cars.append(cpoint)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

            for xc, yc in cars:
                if(yc > line_high - offset and yc < line_high + offset):
                    carnums += 1
                    cars.remove((xc, yc))
                    print(carnums)

        cv2.imshow('video', frame)
        # cv2.imshow('erode', close)

    key = cv2.waitKey(40)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()

显示信息【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as np

min_w = 50
min_h = 50
max_w = 800
max_h = 800

# 检测线的高度
line_high = 480

# 存放有效车辆数组
cars = []

# 统计车的数量
carnums = 0

# 线的偏移
offset = 10

# 求中心点
def center(x, y, w, h):
    x1 = int(w / 2)
    y1 = int(h / 2)
    cx = x + x1
    cy = y + y1
    return cx, cy

cap = cv2.VideoCapture('./video.mp4')

bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()

# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

while True:
    ret, frame = cap.read()

    if(ret == True):
        # print(frame.shape)
        # (584, 1280, 3)
        # 灰度图
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 去噪(高斯)
        blur = cv2.GaussianBlur(frame, (3, 3), 1)
        # 去背景
        mask = bgsubmog.apply(blur)
        # t = tst.apply(frame)

        # 腐蚀,去掉图中小斑块
        erode = cv2.erode(mask, kernel, iterations=1)

        # 膨胀,还原放大
        dilate = cv2.dilate(erode, kernel2, iterations=3)

        # 闭操作,去掉物体内部噪声
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
        close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)

        contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # 画一条检测线
        cv2.line(frame, (100, line_high), (1100, line_high), (255, 255, 0), 2)

        for i, c in enumerate(contours):
            x, y, w, h = cv2.boundingRect(c)

            # 对车辆的宽高进行判断,以验证是否是有效车辆
            isValid = (x >= min_w) and (h >= min_h) and (x <= max_w) and (h <= max_h)
            if(not isValid):
                continue

            # 有效的车
            cpoint = center(x, y, w, h)
            cars.append(cpoint)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            cv2.circle(frame, (cpoint), 5, (0, 0, 255), -1)

            for xc, yc in cars:
                if(yc > line_high - offset and yc < line_high + offset):
                    carnums += 1
                    cars.remove((xc, yc))
                    print(carnums)
        cv2.putText(frame, "Cars Count:" + str(carnums), (500, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 3)
        cv2.imshow('video', frame)
        # cv2.imshow('erode', close)

    key = cv2.waitKey(40)
    if(key == 27):
        break

cap.release()
cv2.destroyAllWindows()


通过实践可以发现传统的目标检测缺点很多,比方说可能重复计数…所以之后我们需要结合深度学习来提高目标检测的精度

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

你可能感兴趣的:(OpenCV,opencv,人工智能,计算机视觉,经验分享)