概念
图像二值化
- 二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或
255,也就是将整个图像呈现出明显的黑白效果的过程。 - 在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
形态学操作
-
腐蚀与膨胀属于形态学操作,所谓的形态学,就是改变物体的形状,形象理解一些:腐蚀=变瘦 膨胀=变胖 ,主要是采用 变瘦cv2.erode() 和 变胖cv2.dilate()
-
腐蚀和膨胀主要针对二值化图像的白色部分
-
膨胀与腐蚀能够实现以下作用:
1.消除噪声
2.分割出独立的图像元素,在图像中连接相邻的元素
3.寻找图像中的明显的极大值区域或者极小值区域
4.求出图像的梯度
相关运算
开运算,闭运算,顶帽,顶帽
- 开运算:先进行腐蚀操作,后进行膨胀操作,主要用来去除一些较亮的部分,即先腐蚀掉不要的部分,再进行膨胀。
- 闭运算:先进行膨胀操作,后进行腐蚀操作,主要用来去除一些较暗的部分。
- 形态学梯度:膨胀运算结果减去腐蚀运算结果,可以拿到轮廓信息。
- 顶帽运算:原图像减去开运算结果。
- 底帽运算:原图像减去闭运算结果。
进行开运算,闭运算,顶帽运算,底帽运算,形态学梯度,opencv提供了一个统一的函数cv2.morphologyEx(),其对应参数如下:
dst = cv2.morphologyEx(src,op,kernel,anchor,iterations,borderType,borderValue)
src: 输入图像对象矩阵,为二值化图像
op: 形态学操作类型
cv2.MORPH_OPEN 开运算
cv2.MORPH_CLOSE 闭运算
cv2.MORPH_GRADIENT 形态梯度
cv2.MORPH_TOPHAT 顶帽运算
cv2.MORPH_BLACKHAT 底帽运算
kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
anchor:锚点,默认为(-1,-1)
iterations:腐蚀操作的次数,默认为1
borderType: 边界种类
borderValue:边界值
原理
- 开启摄像头读取图片
- 通过KNN背景分割器剔除背景,获得移动物体遮罩
- 将遮罩二值化处理
- 将遮罩开运算
- 得到面积大于3000的遮罩轮廓(四个点)
- 在原图上画矩形
代码解释
import cv2
import numpy as np
//背景分割器
bs=cv2.createBackgroundSubtractorKNN(detectShadows=True)
camera=cv2.VideoCapture(0)
camera.set(3,320)
camera.set(4,160)
while True:
//frame的类型为numpy
ret,frame=camera.read()
//背景分割器,该函数计算了前景掩码
//apply()返回的是高X宽的一个numpy矩阵,这里是160x320,如果没有移动物体那么这个矩阵全部为0
fgmask=bs.apply(frame)
/**
threshold作用
二值化阈值处理,前景掩码含有前景的白色值以及阴影的灰色值,在阈值化图像
中,将非纯白色(244~255)的所有像素都设为0,而不是255
图像二值化
src:表示的是图片源
thresh:表示的是阈值(起始值)
maxval:表示的是最大值
type:表示的是这里划分的时候使用的是什么类型的算法
1.cv2.THRESH_BINARY 表示阈值的二值化操作,大于阈值使用maxval表示,小于阈值使用0表示
2. cv2.THRESH_BINARY_INV 表示阈值的二值化翻转操作,大于阈值的使用0表示,小于阈值的使用最大值表示
3. cv2.THRESH_TRUNC 表示进行截断操作,大于阈值的使用阈值表示,小于阈值的不变
4. cv2.THRESH_TOZERO 表示进行化零操作,大于阈值的不变,小于阈值的使用0表示
5. cv2.THRESH_TOZERO_INV 表示进行化零操作的翻转,大于阈值的使用0表示,小于阈值的不变
返回值:
ret:True或False,代表有没有读到图片;
dst: 目标图像;
*/
th=cv2.threshold(fgmask.copy(),244,255,cv2.THRESH_BINARY)[1]
/**
src: 输入图像对象矩阵,为二值化图像
kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
anchor:锚点,默认为(-1,-1)
iterations:腐蚀操作的次数,默认为1
borderType: 边界种类,有默认值
borderValue:边界值,有默认值
cv2.getStructuringElement()
shape:核的形状
cv2.MORPH_RECT: 矩形
cv2.MORPH_CROSS: 十字形(以矩形的锚点为中心的十字架)
cv2.MORPH_ELLIPSE:椭圆(矩形的内切椭圆)
ksize: 核的大小,矩形的宽,高格式为(width,height)
anchor: 核的锚点,默认值为(-1,-1),即核的中心点
*/
th=cv2.erode(th,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),iterations=2)
//开运算
dilated=cv2.dilate(th,cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)),iterations=2)
//获取轮廓 (第三讲研究过了) cv2.RETR_EXTERNAL只检测外轮廓
//cv2.CHAIN_APPROX_SIMPLE压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需要4个点来保存轮廓信息;
image,contours,hier=cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
//轮廓面积>3000
if cv2.contourArea(c)>3000:
/**
cv2.boundingRect(img)这个函数
这个函数很简单,img是一个二值图,也就是它的参数;返回四个值,分别是
x,y,w,h;x,y是矩阵左上点的坐标,w,h是矩阵的宽和高。
然后利用cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)画出
矩行
参数解释
第一个参数:img是原图
第二个参数:(x,y)是矩阵的左上点坐标
第三个参数:(x+w,y+h)是矩阵的右下点坐标
第四个参数:(0,255,0)是画线对应的rgb颜色
第五个参数:2是所画的线的宽度
*/
(x,y,w,h)=cv2.boundingRect(c)
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,255,0),2)
if x!=0 and y!=0:
print('x',x,'y',y)
cv2.imshow("mog",fgmask)
cv2.imshow("detection",frame)
if (cv2.waitKey(30)&0xFF)==27:
break
if (cv2.waitKey(30)&0xFF)==ord('q'):
break
camera.release()
cv2.destroyAllWindows()