OpenCV(9)-图像轮廓

图像轮廓

图像轮廓概述

  • 图像轮廓是具有相同颜色强度连续点的曲线

  • 作用:

    • 可以用于图形分析
    • 物体的识别与检测
  • 注意:

    • 为了检测的准确性,需要先对图像进行二值化或Canny操作
    • 画轮廓时会修改输入的图像
  • 轮廓查找API:

  • findContours(img,mode,ApproximationMode,…)

    • mode:模式,对查找到的轮廓如何处置
      • RETR_EXTERNAL = 0, 表示只检测外轮廓
      • RETR_LIST = 1,检测的轮廓不建立等级关系
      • RETR_CCOMP = 2,每层最多两级
      • RETR_TREE = 3,按树形存储轮廓
    • ApproximationMode:近似模式
      • CHAIN_APPROX_NODE,保存所有轮廓上的点
      • CHAIN_APPROX_SIMPLE,只保存角点
  • 有两个返回值:contours(所有轮廓)和hierarchy(层级关系)

查找轮廓

#转变成单通道
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret,binary = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
#轮廓查找
contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

绘制轮廓

  • drawContours(img,contours,contourIdx,color,thichness…)
    • contourIdx轮廓顺序号,-1表示绘制所有轮廓
    • color轮廓颜色
    • thichness线宽,-1是全部填充
#绘制轮廓
cv2.drawContours(img,contours,-1,(0,0,255),1)

轮廓的面积和周长

  • 轮廓的面积contourArea(contour)
  • 轮廓的周长arcLength(curve,closed)
    • curve轮廓曲线
    • closed是否是闭合的轮廓
#计算面积
area = cv2.contourArea(contours[0])
print("area = %d"%(area))
#计算周长
len = cv2.arcLength(contours[0],true)

多边形逼近与凸包

  • 多边形逼近,可凸可凹,更接近真实物体
  • 多边形逼近作用:减少了存储的数据量,同时将特征点描述出来
    • 特征点可多可少,精度调高,逼近更真实;反之则数据量更少
  • approxPolyDP(curve,epsilon,closed)
    • curve 曲线、轮廓
    • epsilon 精度
    • closed 是否是闭合曲线
e = 20 #设置精度
approx = cv2.approxPolyDP(contours[0],e,True)
#画线函数
def drawShape(src,points):
    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,0,255),3)
        else:
            x,y = points[i][0]
        	x1,y1 = points[i+1][0]
        	cv2.line(src,(x,y),(x1,y1),(0,0,255),3)
        i = i + 1
#绘制
drawShape(img,approx)
  • 凸包:只能凸出,不会下凹,只画出大致轮廓
  • convexHull(points,clockwise,…)
    • points 轮廓
    • clockwise 顺时针绘制
hull = cv2.convexHull(contours[0])
drawShape(img,hull)

外接矩阵

  • 最小外接矩阵 红框 知道物体有没有旋转,以及旋转角度
  • minAreaRect(points)
    • points 轮廓
    • 返回值:RotatedRect
      • x,y 起始点
      • width,height
      • angle 旋转角度
  • 最大外接矩阵 绿框
  • boundingRect(array)
    • array 轮廓
    • 返回值:Rect
      • x,y 起始点
      • width,height
        OpenCV(9)-图像轮廓_第1张图片
r = minAreaRect(contours[1])
box = cv2.boxPoints(r) #拿到起始点和宽高
box = np.int0(box) #将浮点型box转换为int型
cv2.drawContours(img,[box],0,(0,0,255),2)
x,y,w,h = cv2.boundingRect(contours[1])
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)

[实战]车辆统计

项目总览

涉及到的内容

  • 窗口的展示
  • 图像/视频的加载
  • 基本图像的绘制
  • 车辆识别
    • 基本图像的运算与处理
    • 形态学
    • 轮廓查找

涉及到的知识点

  • 加载视频
  • 通过形态学识别车辆
  • 对车辆进行统计
  • 显示车辆的统计信息

加载视频

import cv2
import numpy as np

#加载视频
cap = cv2.VideoCapture('video.mp4')

#视频由很多帧组成 循环读取
while True:
    ret, frame = cap.read() #ret读取视频帧是否成功,frame读取视频帧
    if(ret == True):
        cv2.imshow('video',frame)
        
    key = cv2.waitKey(1)
    if(key == 27): #27为ESC键
        break
#释放资源
cap.release()
cv2.destroyAllWindows()

去除背景

  • createBackgroundSubtractorMOG(…)
    • history = 200
bgsubmog = cv2.createBackgroundSubtractorMOG()

形态学处理

#腐蚀,去除图中小斑块
erode = cv2.eroed(mask,kernel)
#膨胀,还原放大
dilate = cv2.dilate(erode,kernel,iterations = 3)
#闭操作,去除物体内部的小块
close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)
close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,kernel)
#绘制轮廓
cnts, h = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for(i,c) in enumerate(cnts):
    (x,y,w,h) = cv2.boundingRect(c)
    cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)

逻辑处理 车辆统计

#对车辆的宽高进行判断
#以验证是否是有效的车辆
isValid = (w>=min_w) and (h>=min_h)
if(not isValid):
    continue
#到这里都是有效的车
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
#取出车的中心点
cpoint = center(x,y,w,h)
cars.append(cpoint)
            
#中心点落在线内,统计
for (x,y) in cars:
#要有一条线,有范围,从数组中减去
	if((y > line_high - offset) and (y < line_high + offset)):
		carno += 1
		cars.remove((x,y))
		print(carno)

显示车辆统计信息

cv2.putText(frame,"Cars Count:" + str(carno),(500,60),cv2.FONT_HERSHEY_SIMPLEX,2,(255,0,0),5)
  • 同时进行线高、偏移等参数,使其检测尽可能准确
  • 后期完善:进行深度学习的数据训练

完整代码

import cv2
import numpy as np

min_w = 90
min_h = 90

#检测线的高度
line_high = 550

#线的偏移
offset = 7

#统计车的数量
carno = 0

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

#获取中心点
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.createBackgroundSubtractorMOG()

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

#视频由很多帧组成 循环读取
while True:
    ret, frame = cap.read() #ret读取视频帧是否成功,frame读取视频帧
    if(ret == True):
        #灰度化
        cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        #高斯去噪点
        blur = cv2.GuassianBlur(frame,(3,3),5)
        #去背景
        mask = bgsubmog.apply(blur)
        
        #腐蚀,去除图中小斑块
        erode = cv2.eroed(mask,kernel)
        #膨胀,还原放大
        dilate = cv2.dilate(erode,kernel,iterations = 3)
        #闭操作,去除物体内部的小块
        close = cv2.morphologyEx(dilate,cv2.MORPH_CLOSE,kernel)
        close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,kernel)
        #绘制轮廓
        cnts, h = cv2.findContours(close,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
        
        cv2.line(frame,(10,line_high),(1200,line_hjgh),(255,255,0),3)
        
        for(i,c) in enumerate(cnts):
            (x,y,w,h) = cv2.boundingRect(c)
            
            #对车辆的宽高进行判断
            #以验证是否是有效的车辆
            isValid = (w>=min_w) and (h>=min_h)
            if(not isValid):
                continue
            #到这里都是有效的车
            cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
            #取出车的中心点
            cpoint = center(x,y,w,h)
            cars.append(cpoint)
            
            #中心点落在线内,统计
            for (x,y) in cars:
                #要有一条线,有范围,从数组中减去
                if((y > line_high - offset) and (y < line_high + offset)):
                    carno += 1
                    cars.remove((x,y))
                    print(carno)
        cv2.putText(frame,"Cars Count:" + str(carno),(500,60),cv2.FONT_HERSHEY_SIMPLEX,2,(255,0,0),5)
        cv2.imshow('video',framw)
        
    key = cv2.waitKey(1)
    if(key == 27): #27为ESC键
        break
#释放资源
cap.release()
cv2.destroyAllWindows()

你可能感兴趣的:(opencv,python,计算机视觉)