树莓派CSI摄像头使用python调用opencv库函数进行运动检测识别

目录

一、完成摄像头的调用

二、利用python调用opencv库函数对图像进行处理

2.1 图像处理大体流程

2.2 opencv调用函数的参数以及含义

2.2.1 ret, img = cap.read() 读取帧图像

2.2.2 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 灰度图像

2.2.3 gray_diff_img = cv2.absdiff(gray_img, previous_img) 帧差法

2.2.4 cv2.threshold (src, thresh, maxval, type) 二值化处理

2.2.5 cv2.medianBlur(src, ksize) 中值滤波

2.2.6 np.ones(shape, dtype=None, order='C')

2.2.7 cv2.morphologyEx(src, op, kernel) 

2.2.8 cv2.findContours(image,mode,method)

2.2.9 cv2.contourArea()  求轮廓面积

2.2.10 cv2.boundingRect() 返回轮廓框框坐标

2.2.11 cv2.rectangle() 坐标连线,框出轮廓

2.2.12 cv2.imshow()  窗口显示图像

三、处理代码


一、完成摄像头的调用

如果不会具体操作的请看

树莓派调用CSI摄像头进行实时监控

二、利用python调用opencv库函数对图像进行处理

2.1 图像处理大体流程

(1) 打开摄像头设备

(2) 图像进行帧处理(一帧一帧处理),while循环中,先读取摄像头一帧图像

(3) 灰度图像处理,判断上一帧图像是否为空。若为空,赋予一帧图像并进行图像灰度处理;若不为空,则也进行图像灰度处理。

(4) 帧差法,利用上一帧图像和这一帧图像作差值处理。

(5) 二值化图像处理,对进行帧差法后的图像作二值化处理。

(6) 中值滤波处理

(7) 闭运算,腐蚀,膨胀处理。

(8) 对运动图像进行轮廓检测,返回坐标集

(9) 利用坐标框选目标。

(10) 显示图像,将处理完的图像变为上一帧图像。

2.2 opencv调用函数的参数以及含义

2.2.1 ret, img = cap.read() 读取帧图像

cap 是你摄像头设备0捕获的摄像头图像数据( 例: cap = cv2.VideoCapture(0) );

read()是opencv库函数读取摄像头一帧图像,cap.read() 就是获取摄像头设备0读取的一帧图像;

img 就是摄像头设备0读取的一帧图像,图像格式为BGR;

ret 就是bool类型,读取成功返回True,失败则是Flase.

2.2.2 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 灰度图像

img:传入转换的图片。

cv2.COLOR_BGR2GRAY:将格式为BGR的图片转换为灰度图片。

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  gray就是转换成功的灰度图片

2.2.3 gray_diff_img = cv2.absdiff(gray_img, previous_img) 帧差法

cv2.absdiff(a,b) : a,b均为一帧图像。

比较二帧图像不同之处(例如:运动检测时,只有运动的物体会运动,而背景则不动,cv2.absdiff(a,b)得到的是去除背景的运动物体的图片)。gray_diff_img则是二帧处理后的一帧图像。

2.2.4 cv2.threshold (src, thresh, maxval, type) 二值化处理

src:传入的一帧图像。

thresh:阈值(数值范围0-255,根据光照强度选择)

maxval:填充色(数值范围0-255,二值化图像一般都选255)

type:如下图

 thresh_img = cv2.threshold(gray_diff_img, 40, 255, cv2.THRESH_BINARY)

得到的二值化图像thresh_img

2.2.5 cv2.medianBlur(src, ksize) 中值滤波

src 是需要处理的图像。

ksize 是滤波核的大小。滤波核大小是指在滤波处理过程中其邻域图像的高度和宽度。需要注意,核大小必须是比1大的奇数,比如3、5、7等。 
例:mask_img = cv2.medianBlur(thresh_img, 3) 

2.2.6 np.ones(shape, dtype=None, order='C')

shape:是一个int或一个int元组,用于定义数组的大小。

dtype:是一个可选参数,默认值为float。 它用于指定数组的数据类型,例如int。

order:该顺序定义是在内存中以行优先(C风格)还是列优先(Fortran风格)顺序存储多维数组。我们不用写,默认即可。

例:k = np.ones((3, 3), np.uint8) 

大小为1的(1,1)的小矩阵为一个单位,构成3行3列大矩阵,类型为uint8。(具体干嘛用的,我也不是很清除,猜测大概就是表示图像大小)

2.2.7 cv2.morphologyEx(src, op, kernel) 

src:是需要处理的图像。

op:

cv2.MORPH_OPEN:开运算,对图像先进行腐蚀再膨胀,等同于dilate(erode(src,kernal)),开运算对图像的边界进行平滑、去掉凸起等
cv2.MORPH_CLOSE:闭运算,对图像先进行膨胀在腐蚀,等同于erode(dilate(src,kernal)),闭运算用于填充图像内部的小空洞、填充图像的凹陷等

kernel:输入一个数组作为核,表示图像大小。(我也不是很懂)

例 close = cv2.morphologyEx(mask_img, cv2.MORPH_CLOSE, k)

2.2.8 cv2.findContours(image,mode,method)

image :代表输入的图片。注意输入的图片必须为二值图片。若输入的图片为彩色图片,必须先进行灰度化和二值化。

mode : 表示轮廓的检索模式,有4种:

cv2.RETR_EXTERNAL  表示只检测外轮廓。

cv2.RETR_LIST  检测的轮廓不建立等级关系。

 cv2.RETR_CCOMP  建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。

cv2.RETR_TREE  建立一个等级树结构的轮廓。

method: 为轮廓的近似办法,有4种:
cv2.CHAIN_APPROX_NONE  存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))<=1。
cv2.CHAIN_APPROX_SIMPLE  压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
 cv2.CHAIN_APPROX_TC89_L1 和 cv2.CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法。

函数返回值contours:返回几个轮廓(返回几个运动物体框框),每个轮廓的单位是点集(即轮廓大小)

例:cnts = cv2.findContours(close_img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

2.2.9 cv2.contourArea()  求轮廓面积

2.2.10 cv2.boundingRect() 返回轮廓框框坐标

x, y, w, h = cv2.boundingRect(c) ,x,y,w,h为轮廓的坐标长度,c为contours的子集

2.2.11 cv2.rectangle() 坐标连线,框出轮廓

cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) 

图片,长方形框左上角坐标, 长方形框右下角坐标, 字体颜色,字体粗细

2.2.12 cv2.imshow()  窗口显示图像

 cv2.imshow("name", img)  "name" 为窗口名字,img为窗口显示图像。

三、处理代码

import cv2
import time
import numpy as np

def videos():
    cap = cv2.VideoCapture(0)
    cap.set(3, 640)
    cap.set(4, 480)
    cap.set(5,40)
    
    img_num = 0
    k = np.ones((3, 3), np.uint8)  

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

        if not img_num:
            previous = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        gray_diff = cv2.absdiff(gray, previous)  
        thresh = cv2.threshold(gray_diff, 40, 255, cv2.THRESH_BINARY)[1] 
        mask = cv2.medianBlur(thresh, 3) 
        close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, k) 

        cnts = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0] 
        for c in cnts:   
            area = cv2.contourArea(c)
            if area > 200:
                x, y, w, h = cv2.boundingRect(c)
                cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

        cv2.imshow("thresh_img", close)
        cv2.imshow("Result", img)
        img_num += 1

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

videos()

左上角因为阳光问题所以出现一点白。

猜你喜欢

转载自blog.csdn.net/qq_51679917/article/details/130440779