opencv官方文件

一:Mac下命令方式搭建opencv开发环境

1.安装homebrew 在终端输入homebrew下的命令

2.根据提示配置环境

3.通过以下两个命令安装配置环境

brew install python@3.9

pip3 install numpy matplotlib opencv_python

配置完成后可顺利导入相应包即可

opencv开发工具:pyсharm vscode

利用开发工具尝试的第一个小例子:通过CV2打开一张图片,现实时长用waitKey

如果小写会出现以下错误提示:AttributeError: module 'cv2' has no attribute 'waitkey'

Mac系统下可以直接 mkdir&&cd&&code.

然后进入代码编写即可

二:车辆检测

1.窗口的展示

1.1:创建和显示窗口

namedWindow()

imshow()

destoryAllWindows()

resizeWindows 具体参数可以下载master opencv 进行查看

import cv2cv2.namedWindow('new',cv2.WINDOW_NORMAL) #创建窗口
cv2.resizeWindow('new',1920,1080)#resize窗口的大小cv2.imshow('new',0) #展示窗口key=cv2.waitKey(0)#设置展示窗口的时长 单位毫秒
if (key == 'q'):#接受键盘信息 如果输入q 结束窗口展示exit()cv2.destroyAllWindows() #释放掉所有窗口资源

设置鼠标回调函数

setMouseCallback(winname,callback,userdate) 窗口名字 回调函数 参数

callback (event,x, y, flags, userdate) 事件(左键 右键) 坐标位置

opencv控制鼠标:

import cv2
import numpy as np
from cv2 import resizeWindow#设置函数
def mouse_callback(event,x,y,flags,userdata):print(event,x,y,flags,userdata)#mouse_callback(1,100,100,16,"666")#创建窗口
cv2.namedWindow('mouse',cv2.WINDOW_NORMAL)
cv2,resizeWindow('mouse',640,360)#设置鼠标回调
cv2.setMouseCallback('mouse',mouse_callback,"123")#显示窗口和背景
img =np.zeros((360,640,3),np.uint8) #与窗口的长宽比是相反的360 640
while True:cv2.imshow('mouse',img)key = cv2.waitKey(1)if key & 0xFF == ord('q'):breakcv2.destroyAllWindows()

2.图像视频的加载(imread)

2.1:imread

im == image

imread(path,flag)

加入图片可能存在的问题:

import cv2
from cv2 import WINDOW_NORMALcv2.namedWindow('img',cv2.WINDOW_NORMAL)
img=cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')#读入图片cv2.imshow('img',img)
key=cv2.waitKey(0)print(key)
print('q')
print(ord('q'))if(key & 0xFF ==ord('q')): #最好更改成这样 这样才能真正进入退出的代码段执行print(1111)cv2.destroyAllWindows()#直接替换exit()

保存图片:

imwrite(name,img).    name:要保存的文件名。img:是mat类型

import cv2
from cv2 import WINDOW_NORMALcv2.namedWindow('img',cv2.WINDOW_NORMAL)
img=cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')#读入图片while True:#加了while循环 cv2.imshow('img',img)key=cv2.waitKey(0)if(key &0xFF ==ord('q')):breakelif(key &0xFF ==ord('s')):cv2.imwrite('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.jpeg',img)
cv2.destroyAllWindows()

2.2:视频采集:

VideoCapure()

cap.read()  返回两个值,第一个为状态值,读到帧为true,第二个值为视频帧

cap.release()

import cv2#创建窗口
cv2.namedWindow('video',cv2.WINDOW_NORMAL)
cv2.resizeWindow('video',640,480)#获取视频设备
cap = cv2.VideoCapture(0)while True:ret,frame=cap.read() #从设备中(摄像头)读取数据 视频帧 #一帧一帧的读 循环所以形成了视频cv2.imshow('video',frame)  #将获得的视频帧在窗口中显示key = cv2.waitKey(10)#等待键盘事件,如果为q退出if(key & 0xFF == ord('q')):break#释放videoCapture
cap.release()
cv2.destroyAllWindows()

如何视频文件中读取视频帧:只需在cv2.VideoCapture中写入视频地址即可

#获取视频设备/从视频文件中读取视频帧
cap = cv2.VideoCapture('/Users/wangcc/Desktop/opencv/IMG_5091.MOV')

2.3:如何将视频数据录制成多媒体文件

VideoWriter 参数一位输出文件 参数二为多媒体文件格式(VideoWriter_fourcc)帧率➕分辨率

write

release

#创建VideoWriter为写多媒体文件
fourcc=cv2.VideoWriter_fourcc(*'MJPG')#创建fourcc
vw=cv2.VideoWriter('./out.mp4',fourcc,25,(1280,720))
#某一路径下 fourcc 帧率 分辨率要与自己摄像头的分辨率一样#写数据到多媒体文件vw.writer(frame)#释放VideoWriter资源
vw.release()
import cv2#创建VideoWriter为写多媒体文件
fourcc=cv2.VideoWriter_fourcc('M','J','P','G')#创建fourcc
vw=cv2.VideoWriter('/Users/wangcc/Desktop/opencv',fourcc,25,(1296,694)) #某一路径下 fourcc 帧率 分辨率#创建窗口
cv2.namedWindow('video',cv2.WINDOW_NORMAL)
cv2.resizeWindow('video',640,360)#获取视频设备/从视频文件中读取视频帧
#cap = cv2.VideoCapture('/Users/wangcc/Desktop/opencv/IMG_5091.MOV')
cap = cv2.VideoCapture(0)while cap.isOpened(): #判断摄像头是否为打开状态ret,frame=cap.read() #从设备中(摄像头)读取数据 视频帧if ret == True:cv2.imshow('video',frame)  #将获得的视频帧在窗口中显示cv2.resizeWindow('video',640,360) #重新将窗口设置为指定大小#写数据到多媒体文件vw.writer(frame)key = cv2.waitKey(1)#等待键盘事件,如果为q退出if(key & 0xFF == ord('q')):breakelse:break#释放videoCapture
cap.release()#释放VideoWriter资源
vw.release()
cv2.destroyAllWindows()

TrackBar控件:

createTrackBar 参数trackbarname(控件名), winname(窗口名),value:trackbar当前值

count:最小值为0,最大值为count。callback,userdate

getTrackbarPos 参数:输入值trackbarname,winname.   输出:当前值

import cv2
import numpy as npdef callback():pass#创建窗口
cv2.namedWindow('trackbar',cv2.WINDOW_NORMAL)#创建trackbar
cv2.createTrackbar('R','trackbar',250, 255, callback)
cv2.createTrackbar('G','trackbar',100, 255, callback)
cv2.createTrackbar('B','trackbar',100, 255, callback)#设置一个纯黑色的背景
img = np.zeros((480,640,3),np.uint8)
while True:#获取当前trackbar的值r = cv2.getTrackbarPos('R','trackbar')g = cv2.getTrackbarPos('G','trackbar')b = cv2.getTrackbarPos('B','trackbar')#改变背景图片颜色img[:] = [b, g, r]cv2.imshow('trackbar',img)key = cv2.waitKey(10)if key & 0xFF == ord('q'):breakcv2.destroyAllWindows()

3.基本图形的绘制

3.1:openCV的色彩空间

openCV默认使用BGR

YUV:用在视频中  4:2:0  4:2:2  4:4:4

HSV 与 HSL:

Hue:色相,即色彩,如红色,蓝色

Saturation:饱和度,颜色的纯度

Value:明度         Lightness:

openCV色彩空间的转换

 #颜色空间转换cvt_img = cv2.cvtColor(img,colorspaces[index])
import cv2def callback():passcv2.namedWindow('color',cv2.WINDOW_NORMAL)img = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')colorspaces=[cv2.COLOR_BGR2RGBA,cv2.COLOR_BGR2BGRA,cv2.COLOR_BGR2GRAY,cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor','color',0,len(colorspaces),callback)while True:index = cv2.getTrackbarPos('curcolor','color')#颜色空间转换cvt_img = cv2.cvtColor(img,colorspaces[index])cv2.imshow('color',img)key = cv2.waitKey(10)if key & 0xFF == ord('q'):break cv2.destroyAllWindows()

Numpy创建矩阵:

创建数组array()

创建全0数组 zeros()/ones

创建全值数组full()

创建单元数组identity()/eye()

import numpy as npa = np.array([2,3,4])
b = np.array([[1,2,3],[4,5,6]])#(480,640,3)(行的个数,列的个数,通道数/ 层数) np.uint8矩阵中的数据类型
c = np.zeros((480,640,3),np.uint8)#ones矩阵
d = np.ones((8,8,3),np.uint8)#full矩阵 255 是矩阵中的数值
e = np.full((8,8),255,np.uint8)#单位矩阵identity
f = np.identity(4)#eye 矩阵
g = np.eye(3,5,k=1)
print(g)

numpy的检索与赋值

import cv2img = np.zeros((480,640,3),np.uint8)print(img[100,100])
count =0
while count < 400:img[count,400,2] = 255#img[count,400] = [0,0,255] 多通道赋值的两种方法count = count + 1cv2.imshow('img',img)key = cv2.waitKey(0)
if key & 0xFF == ord('q'):cv2.destroyAllWindows()

Region of image(RIO) 图形的绘制

获取子矩阵

[y1:y2,x1:x2] 取某一部分       [:,:] 全部矩阵

import cv2img = np.zeros((480,640,3),np.uint8)# print(img[100,100])
# count =0
# while count < 400:
#     img[count,400,2] = 255
#     #img[count,400] = [0,0,255]
#     count = count + 1roi = img[200:400,200:400]
roi[:,:]=[0,255,0]
roi[50:100,50:100]=[0,0,255]
cv2.imshow('img',roi)key = cv2.waitKey(0)
if key & 0xFF == ord('q'):cv2.destroyAllWindows()

Mat 属性

mat的深浅拷贝

浅拷贝:

Mat A

A = imread(file, IMREAD_COLOR)

Mat B(A);  B与A的Header不同,但指向的数据相同

深拷贝:

C++中实现方式有两种

cv ::Mat::clone()

cv::Mat::copyTo()

将DATA也重新赋值一份,A与B完全切断

python中实现:

copy(),使用该方法就是深拷贝

进行深拷贝后,进行图片的处理时不影响原图片,cv2.add也是深拷贝操作

import cv2
from cv2 import resizeWindow
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')
resizeWindowimg1 = img# 浅拷贝
img2 = img.copy() #深拷贝 即使图片做了改变,但拷贝的是原图片img[100:400,100:400] = [255,0,0]cv2.imshow('img',img)
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)cv2.waitKey(0)

访问图像的属性:

import cv2
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')print(img.shape)
print(img.size)
print(img.dtype)

通道的分离与合并:

split(mat)

merge((ch1,ch2,...)

import cv2
import numpy as npimg = np.ones((640,480,3),np.uint8)b,g,r=cv2.split(img)b[100:400,100:400] = 255
g[100:400,100:400] = 255img1=cv2.merge((b,g,r))cv2.imshow('img',img)
cv2.imshow('b',b)
cv2.imshow('g',g)
cv2.imshow('img1',img1)cv2.waitKey(0)

图形的绘制:

画线:

cv2.line(img,(10,20),(300,400),(0,0,255),5,4).    背景,x坐标,y坐标,颜色,线宽,线型。

画圆:

cv2.circle(img,中心点,半径,颜色,线型(-1填充)......)

画椭圆:

cv2.ellipse(img,中心点,长宽的一半,角度,从哪个角度开始(按顺时针),到那个角度结束.....)

画多边形:

pts=np.array([(),(),()],np.int32).  必须是int32 位

cv2.polylines(img,点集[pts],是否闭合(true false),颜色)

填充多边型:cv2.fillpoly(img,[pts],(0,0,255))

画文本:

cv2.putText(img,字符串,起始点,字体(cv2.FONT_HERSHEY_PLAIN),字号,颜色.....)

import cv2
import numpy as npimg = np.zeros((480,640,3),np.uint8)
#画线,画圆,画椭圆
cv2.line(img,(10,10),(400,400),(0,0,255),4,8)
cv2.circle(img,(300,300),100,(255,0,0),-1)
cv2.ellipse(img,(200,200),(150,50),45,0,300,(0,255,0),-1)#绘制多边形
pots = np.array([(10,10),(10,110),(110,110),(110,10)],np.int32)
cv2.polylines(img,[pots],True,(0,0,255))
#cv2.fillpoly(img,[pots],(255,0,0))#绘制文本
cv2.putText(img,'openCV',(1,300),cv2.FONT_HERSHEY_SIMPLEX,5,(0,0,255))cv2.imshow('img',img)
cv2.waitKey(0)

鼠标回调函数画图:

import cv2
import numpy as npcurshape = 0
startpos =(0,0)
#鼠标回调函数
def mouse_callback(event,x,y,flags,userdate):global curshape,startposif(event & cv2.EVENT_LBUTTONDOWN == cv2.EVENT_LBUTTONDOWN):startpos = (x,y)elif(event & cv2.EVENT_LBUTTONUP == cv2.EVENT_LBUTTONUP):if curshape == 0:cv2.line(img,startpos,(x,y),(0,0,255))elif curshape == 1:cv2.rectangle(img,startpos,(x,y),(0,0,255))elif curshape == 2:a = (x-startpos[0])b = (y-startpos[1])r=int((a**2+b**2)**0.5)cv2.circle(img,startpos,r,(0,0,255))else:print('error')#创建窗口
cv2.namedWindow('drawshape',cv2.WINDOW_NORMAL)#设置鼠标回调
cv2.setMouseCallback('drawshap',mouse_callback)#显示窗口和背景
img =np.zeros((480,640,3),np.uint8) #与窗口的长宽比是相反的360 640
while True:cv2.imshow('drawshap',img)key = cv2.waitKey(1) & 0xFFif key  == ord('q'):breakelif key == ord('l'): #linecurshape = 0elif key == ord('r'): #rectcurshape = 1elif key == ord('c'): #circlecurshape = 2cv2.destroyAllWindows()

4.车辆识别

第一章:基本图像运算与处理

1.图像的加法运算(图更亮)

cv2.add(dog,img).    dog+img

2.图像的减法运算(图更暗)

subtract(A,B)     A-B

3.图像的乘与除

multiply(A,B)

divide(A,B)

4.图像位运算(与,或,非,异或)

非:bitwise_not(img)

与:bitwise_and(img1,img2). 找出图片的交叉点

或:bitwise_or(img1,img2)

异或:bitwise_xor(img1,img2)

import cv2
from cv2 import waitKey
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')
print(img.shape)back = np.ones((694,1296,3),np.uint8)*20add = cv2.add(img,back)
sub = cv2.subtract(img,back)
mul = cv2.multiply(img,back)
div = cv2.divide(img,back)
no  =  cv2.bitwise_not(img)cv2.imshow('no',no)# cv2.imshow('add',add)
# cv2.imshow('sub',sub)
# cv2.imshow('mul',mul)
# cv2.imshow('div',div)# cv2.imshow('img',img)
# cv2.imshow('back',back)cv2.waitKey(0)

给图片添加水印

import cv2
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')
print(img.shape)logo = np.zeros((200,200,3),np.uint8)
mask = np.zeros((200,200),np.uint8)logo[20:100,20:100] = (0,0,255)
logo[80:160,80:160] = (255,0,0)mask[20:100,20:100] = 255
mask[80:160,80:160] = 255#对mask按位求反
m =  cv2.bitwise_not(mask)
#选择logo粘贴的位置
roi =  img[0:200,0:200]
#con = cv2.add(logo,mask)#对m进行与操作
tmp = cv2.bitwise_and(roi,roi,mask=m)dst = cv2.add(tmp,logo) #保留不是黑的部分#将dst赋值给img
img[0:200,0:200] = dstcv2.imshow('img',img)cv2.imshow('dst',dst)
cv2.imshow('tmp',tmp)
cv2.imshow('mask',mask)
cv2.imshow('roi',roi)
cv2.imshow('logo',logo)
cv2.waitKey(0)

图像的基本变换:

图像的缩放:resize(src,dst,dsize,fx,fy,interpolation)

src:源图片,dst;目的 [dsize:目标的大小 fx:fy: x y 轴的缩放因子],

interpolation:缩放算法

INTER_NEAREST 领近插值,  INTER_LINEAR 双线性插值,INTER_CUBIR:三次插值

INTER_AREA:双线性插值,原图中的四个点

INTER_CUBIC:三次插值,原图中的16个点

INTER_AREA:效果最好

import cv2
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')new = cv2.resize(img,(300,200))
new1 =  cv2.resize(img,None,fx=0.3,fy=0.3,interpolation=cv2.INTER_AREA)cv2.imshow('new',new)
cv2.imshow('new1',new1)cv2.waitKey(0)

图像的翻转:

flip(img,flipcode).    flipcode==0,上下翻转,flipcode>0左右 flipcode<0,上下+左右

图像的旋转:

  rotate(img,rotateCode)

ROTATE_90_CLOCKWISE ROTATE_180        ROTATE_90_COUNTERCLOCKWISE

顺时针方向90度。             顺时针180度                         逆时针90度

        图像的仿射变换:(图像旋转 缩放 平移的总称)

        warpAffine(src,M,dsize,flags,mode,value)

        M:变换矩阵        dsize:输出图片尺寸大小           flags:与resize中的插值算法一样

mode:边界外推法标志        Value:填充边界的值

 变换矩阵M:

getRotationMatrix2D(center,angle,scale)

center:旋转的中心点          angle:旋转的角度        scale;放大缩小

M = cv2.getRotationMatrix2D((500,500),90,0.5)

如果想改变图片的尺寸,需要改变dsize的数值。

  getAffineTransform(src[],dts[])

src[]: 原图片中的三个点 与新图片中的三个点一一对应

h,w,ch =img.shape
#M = cv2.getRotationMatrix2D((w/2,h/2),90,0.5)
#M =  np.float32([[1,0,100],[0,1,100]])src = np.float32([[200,400],[200,800],[400,400]])
dts = np.float32([[100,300],[100,700],[300,200]])
M = cv2.getAffineTransform(src,dts)
new = cv2.warpAffine(img,M,(w,h))

透视变换

warpPerspective(img,M,dsize....)

变换矩阵:getPerspectiveTransform(src,dst) 四个点:图形的四个点

src = np.float32([[100,400],[100,800],[400,400],[400,800]])
dst = np.float32([[100,300],[100,700],[300,200],[300,300]])
M = cv2.getPerspectiveTransform(src,dst)new1 = cv2.warpPerspective(img,M,(200,200))

图像卷积

fliter2D(src, ddepth, kernel, anchor, delta, borderType)

src:源图像, ddepth:位深多少位(-1 与源图像一致)kernel:卷积核

anchor:锚点 图中心点(可以不设)delta:默认0   borderType:默认 不设

import cv2
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/截屏2022-07-22 下午2.56.35.png')kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel) #效果让图像更平滑了cv2.imshow('dst',dst)
cv2.imshow('img',img)
cv2.waitKey(0)

低通滤波:作用降噪

方盒滤波与均值滤波

normalize = true, a=1/W*H  [方盒滤波等于均值滤波】

noramlize = false, a = 1,

boxFliter(src,ddepth,ksize,anchor,normalize,boderType) 方盒滤波

src, 源图

ddepth, 位深

ksize, 卷积核大小

anchor,锚点:默认-1

normalize, :True. Flase

boderType:

blur(src,ksize,anchor,boderType) 均值滤波 大多数情况下直接使用均值滤波代替方盒滤波

dst = cv2.blur(img,(5,5)) #均值滤波

卷积核为:a=1/W*H。  a*[5乘5的矩阵]

高斯滤波:

作用:解决高斯噪音

GaussianBlur(img,kernel,sigmaX,sigmaY,.....)

源图,卷积核,到中心点的误差,

代码:

中值滤波:

可以很好的处理图片中的胡椒噪点

API:  medianBlur(img,ksize)  ksize:卷积核的大小  单值

代码:

双边滤波:

作用:美颜

API:bilateralFilter(img,d,sigmaColor,sigmaSpace,....)

img:图像, d:直径,sigmaColor:颜色的sigma,空域核 sigmaSpace:空间核sigma

代码:

高通滤波:作用:检测边缘

Sobel(索贝尔)高斯:可改变卷积核大小,3*3的卷积核无沙尔效果好,只能求一个方向的边缘。

1: 先向X方向求导,然后在Y方向求导,最终结果:|G| = |Gx|+|Gy| CV2.add(d1,d2)

2:API:Sobel(src,ddepth,dx,dy,ksize=3,scale=1,delta=0,borderType =BORDER_DEFAULT)

当scale=-1,则为Scharr, 对X求导检测出Y方向边缘, 对Y求导显示X边缘

代码:

Scharr(沙尔):不可改变卷积核大小,与Sobel类似,只不过是Kernel值不同

1:API:Scharr(src,ddepth,dx,dy,scale=1,delta=0,borderType =Border_DEFAULT)

2: 可识别很细的边界

代码:

Laplacian(拉普拉斯),可同时求X,Y方向的边缘,但自身没有降噪功能,在使用之前需要先手工降噪

1:API:Laplacian(img,ddepth,kszie = 1, scale = 1,borderType = BORDER_DEFAULT)

代码:

边缘检测Canny:终极边缘检测大法

        1:使用5*5高斯滤波消除噪声

        2:计算图像梯度的方向(0°/45°/90°/135°)

        3:取局部最大值

        4:canny阈值计算  轮廓

        API:Canny(img, minVal.maxVal,....)最小阈值,最大阈值

第二章:形态学

知乎关于形态学的介绍 包含代码

什么是形态学处理:

1:基于图像形态进行处理的一些基本方法;比如识别杯子的位置

2:这些处理方法基本是对二进制图像进行处理:也就是黑白图片

二值化:将图像的每个像素变成两种值,如0,255

全局二值化:API:threshold(img,thresh,maxVal,type)

img:图像,最好是灰度图,thresh:阈值 ,maxVal:超过阈值,替换成maxVal

type:THRESH_BINARYTHRESH_BINAPY_INV 

二进制 低于阈值变最小值,反之最大值

THRESH_TRUNC  THRESH_TOZEROTHRESH_TOZERO_INV

        

                        代码:

                        

自适应阈值:

API:adaptiveThreshold(img,maxVal,adaptiveMethod,type,blockSize,C)            adaptiveMethod:计算阈值的方法。

ADAPTIVE_THRESH_MEAN_C:计算邻近区域的平均值作为阈值

ADAPTIVE_THREAH_GASSIAN_C:高斯窗口加权平均值

Type: THRESH_BINARY  THRESH_BINARY_INV

blockSize:邻近区域的大小

C:常量,应从计算出的平均值和加权平均值中减去

        代码:

3:卷积核决定这图像处理后的效果

处理方法:

1:腐蚀(缩小)与膨胀(变大)

腐蚀:只有在卷积核所覆盖区域全大于1时,卷积核中心位置覆盖的点保留原色

  API:erode(img,kernel,iterations=1)  原图像 卷积核 腐蚀次数

                        获得卷积核:getStructuringElemrnt(type,size)

                          type:MORPH_RECT(矩形   MORPH_ELLIPSE(椭圆形)                                    MORPH_CROSS(交叉     矩形kernel腐蚀最严重 

膨胀:只要卷积核中心覆盖的值不为0,其周边值都改变成非0,卷积核越大,膨胀越快

  API:dilate(img,kernel,iterations=1)

2:开运算:先腐蚀再膨胀

效果:去除噪点 API:(img,MORPH_OPEN,kernel)  噪点越大 核设置越大

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, 1)

3:闭运算:先膨胀在腐蚀

分析: 字体不改变的前提下,我们把字体缺陷信息补全。

4:形态学梯度:

梯度计算主要显示的是边缘信息。计算的方法:

膨胀的图像 - 腐蚀的图像

我们明显的看出,用大一圈的图像减去小一圈的图像正好就是边缘的信息。

gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv_show(gradient)

5:顶帽:TOPHAT

高帽计算:原始图像 - 开运算结果

我们知道开运算的结果就是去除毛刺,

我们原始图像减去开运算结果就是我们要消除的毛刺信息。

top_hat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
ss = np.hstack((img, top_hat))
cv_show(ss)

结果:得到噪点

6:黑帽: MORPH_BLACKHAT

黑帽计算:闭运算结果 - 原始图像

显示缺陷

black_hat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
ss = np.hstack((img, black_hat))
cv_show(ss)
import cv2
from cv2 import ADAPTIVE_THRESH_GAUSSIAN_C
from cv2 import getStructuringElement
from cv2 import MORPH_CROSS
from cv2 import MORPH_OPEN
import numpy as npimg = cv2.imread('/Users/wangcc/Desktop/opencv/bc036515-ed41-dd06-dd78-203de60d2a22.jpeg')
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #二值化处理dst=cv2.adaptiveThreshold(img1,255,ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,7,0)kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))#获得卷积核
dst1 = cv2.erode(dst,kernel,iterations=1) #腐蚀操作dst2 = cv2.dilate(dst1,kernel,iterations=1) #膨胀操作kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(2,2))#得卷积核
opening = cv2.morphologyEx(dst2,cv2.MORPH_OPEN,kernel1,2)#开运算close = cv2.morphologyEx(opening,cv2.MORPH_CLOSE,kernel1,1)#闭运算cv2.imshow('dst1',dst1)
cv2.imshow('dst2',dst2)
cv2.imshow('opening',opening)
cv2.imshow('close',close)new=cv2.morphologyEx(dst,cv2.MORPH_OPEN,(7,7),1)
# cv2.imshow('gray',img1) #二值化
# cv2.imshow('img',img)
# cv2.imshow('bin',dst) #显示处理后的二值图
# cv2.imshow('new',new)cv2.waitKey(0)

第三章:轮廓查找

轮廓查找的API:

contours,hierarchy=findContours(img,mode,ApproximationMode)  两个返回值

轮廓    层级

mode:RETR_EXTERNAL=0 表示只检测外轮廓

RETR_LIST=1  检测的轮廓都表示出来 没有等级关系

RETR_CCOMP=2,每层最多两级

RETR_TREE=3 按树形存储轮廓

ApproximationMode

CHAIN_APPROX_NONE 保存所有轮廓上的点

CHIAN_APPROX_SIMPLE 只保存角点

绘制轮廓的API:

  drawContours(img,contours,contourIdx,color,thickness....)

contourIdx:-1表示绘制所有轮廓  轮廓的顺序号具体展示轮廓 第一个0 第二个1

color:轮廓的颜色(0,0,255)

thickness:线宽,1比较细 -1全部填充

轮廓的面积和周长:

应用:通过面积小于多少,过滤出查找的轮廓

已知其中一个面积的真实值,通过比列计算出其他未知的轮廓面积周长

,面积API:contourArea(contour)

                            周长API:  arcLength(curve,closed)  curve:轮廓  closed:是否闭合 true闭合

   代码:

import cv2
from cv2 import waitKey
from cv2 import RETR_LIST
from cv2 import CHAIN_APPROX_NONE
from cv2 import ADAPTIVE_THRESH_GAUSSIAN_C
from cv2 import ADAPTIVE_THRESH_MEAN_C
import numpy as npsrc = cv2.imread('/Users/wangcc/Desktop/opencv/contours.png')
gray=cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #转变成单通道
binary = cv2.adaptiveThreshold(gray,255,ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,7,0) #自适应阀值contours,hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) #查找轮廓 获得轮廓点cv2.drawContours(src,contours,-1,(0,0,255),-1) #绘制轮廓 src在三通道中才能显示彩色#轮廓的周长和面积
area0 = cv2.contourArea(contours[0])
area1 = cv2.contourArea(contours[1])length0 = cv2.arcLength(contours[0],True)
length1 = cv2.arcLength(contours[1],True)print("area0=%d,area1=%d"%(area0,area1)) #输出面积
print("length0=%d,length1 = %d"%(length0,length1))#输出周长
cv2.imshow('binary',binary)
cv2.imshow('src',src)
cv2.imshow('gray',gray)waitKey(0)

多边形逼近与凸包:

多边形逼近可减少存储的数据量。凸包只描述轮廓

  多边形API:approxPolyDP(curve,epsilon,clsed)

曲线轮廓,精度,是否闭合

 凸包: API:convexHull(points,clockwise)

轮廓,顺时针true,逆时针false

代码:

import cv2
from cv2 import THRESH_BINARY
from cv2 import RETR_EXTERNAL
from cv2 import CHAIN_APPROX_SIMPLE
from cv2 import approxPolyDP
from cv2 import ADAPTIVE_THRESH_GAUSSIAN_C
import numpy as npdef drawShape(src,points):i = 0while 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),1)else:x,y = points[i][0]x1,y1 = points[i+1][0]cv2.line(src,(x,y),(x1,y1),(0,0,255),1)i = i+1#灰度化 二值化
img = cv2.imread('/Users/wangcc/Desktop/opencv/contours.png')
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)#绘制轮廓
# cv2.drawContours(img,contours,-1,(0,0,255),1)#查找图形轮廓上的点
e = 1 #值越小精度越好
approx = cv2.approxPolyDP(contours[0],e,True)#画图函数
drawShape(img,approx)#凸包
hull = cv2.convexHull(contours[1])
drawShape(img,hull)cv2.imshow('gray',gray)
cv2.imshow('img',img)cv2.waitKey(0)

外接矩形:

最小外接矩形:API:minAreaRect(points) pomints轮廓

返回值:RotatedRect  包含x,y 起始点,width,height 宽和高  angle 角度

最大外接矩形:API:boundingRect(array)  array:轮廓

返回值Rect 包含x,y 起始点,width,height 宽和高

  代码:

#最小外接矩形
r = 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),(255,0,0),1)

车辆统计项目

窗口的展示

图像/视频的加载

基本图形的绘制

车辆识别:(基本图像运算与处理,形态学,轮廓查找)

1:加载视频  2:通过形态学识别车辆 3:对车辆进行统计 4:显示车辆统计信息

import cv2
from cv2 import ADAPTIVE_THRESH_GAUSSIAN_C
from cv2 import ADAPTIVE_THRESH_MEAN_C
from cv2 import BackgroundSubtractor
from cv2 import dilate
import numpy as np#创建显示窗口
cv2.namedWindow('video',cv2.WINDOW_NORMAL)
cv2.resizeWindow('video',640,480)#导入视频文件/获取摄像头视频帧
cap = cv2.VideoCapture('/Users/wangcc/Desktop/opencv/IMG_6577.MOV')min_w = 100
min_h = 100#检测线的高度
line_high = 900#存放车辆的数组
cars = []#线的偏移量
offset = 6carno = 0def center(x,y,w,h):x1 = int(w/2)y1 = int(h/2)cx = x + x1cy = y + y1return cx, cybgsubmog  = cv2.createBackgroundSubtractorMOG2()
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)) #获得卷积核
while True:ret, frame = cap.read()if (ret == True):# 灰度化cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)# #二值化# blur = cv2.adaptiveThreshold(gray,255,ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,7,0)#去噪(高斯) 去噪以后比二值化更清楚了blur = cv2.GaussianBlur(frame,(3,3),5) #去背影mask = bgsubmog.apply(blur)#腐蚀erode = cv2.erode(mask,kernel)#膨胀dilate = cv2.dilate(erode,kernel,iterations=3)#闭操作# opening= cv2.morphologyEx(dilate,cv2.MORPH_OPEN,kernel,1)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,(750,line_high),(1600,line_high),(0,255,0),6)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),6)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 +=1cars.remove((x,y))print(carno)cv2.putText(frame,"cars count:"+str(carno),(700,60),cv2.FONT_HERSHEY_COMPLEX,2,(0,255,0),2)# cv2.imshow('video',blur)cv2.imshow('video1',frame)cv2.imshow('video2',close)cv2.imshow('video3',mask)# cv2.imshow('video2',opening)key = cv2.waitKey(1)if(key == 27): #27是esc退出键breakcap.release()
cv2.destoryAllWindows()

Harris角点检测API:

cornerHarris(img,dst,blovkSize,ksize,k)

dst,输出结果

blockSize:检测窗口大小 ksize:Sobel卷积核 k:权重系数,经验值 一般0.02-0.04之间

Shi-Tomasi角点检测:

对Harris角点检测的改进

API:goodFraturesToTrack(img,maxCorners,...)

maxCorners:角点的最大数,值为0表示无限制

qualityLevel:小于1的正数,一般在0.01-0.1之间

minDistance:角之间最小欧式距离,忽略小于此距离的点

mask:感兴趣的区域

blockSize:检测窗口

useHarrisDetector:是否使用Harris算法

k:默认是0.04

SIFT(Scale-Invariant Feature Transform)        

Harris 角点具有旋转不变的特性 经过缩放后,原来的角点有可能就不是角点了

使用步骤:

1:创建SIFT对象

2:进行检测,kp=sift.detect(img,...)获得关键点

3:绘制关键点,drawKeypoints(gray,kp, img)

SIFT计算描述子:

关键点:位置,大小和方向

关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换,光照变换的影响。

kp,des = sift.compute(img,kp) 其作用是进行特征匹配

kp,des = sift.detectAndCompute(img,....) mask:指明对img中哪个区域进行计算

SURF(Speeded-Up Robust Feature)特征检测

SIFT的缺点:速度慢,因此使用SURF速度加快

1:创建对象surf = cv2.xfeatures2d.SURF_creature()

2:kp,des = surf.detectAndCompute(img,mask)

ORB(oriented FAST and Rotated BRIEF):

ORB的优势可以做到实时检测  但准确率不如前者 适用于大批量图片检测

ORB= oriented FAST (可以做特征点的实时检测)+ Rotated BRIEF(是对已检测到的特征点进行描述,加快了特征描述建立的速度 极大降低了匹配的时间)

使用步骤:

1:创建对象:orb = cv2.ORB_create()

2: kp,des= orb.detectAndCompute(img,mask)

暴力特征匹配:BF(Brute-Force)

原理:使用第一组中的每个特征的描述子 与第二组中的所有特征描述子进行匹配

计算他们之间的差距,然后将最接近一个匹配返回

openCV 自学笔记相关推荐

  1. matlab 平均梯度,OpenCV 自学笔记33. 计算图像的均值、标准差和平均梯度

    OpenCV 自学笔记33. 计算图像的均值.标准差和平均梯度 均值.标准差和平均梯度是验证图像质量的常用指标.其中: 均值反映了图像的亮度,均值越大说明图像亮度越大,反之越小: 标准差反映了图像像素 ...

  2. 【OpenCV自学笔记】DYA3 测试旧版本OpenCV函数的使用和图像简单缩放

    版权声明:本文为 @iCurious 的原创文章,可以转载,但请务必注明作者和出处!!! 原文链接:|blog.csdn.net/icurious|www.blankspace.cn|www.cnbl ...

  3. 基于python的openCV自学笔记(四)——遗漏知识点补充

    本篇补充暑假学opencv遗漏的相关知识点 参考链接:https://www.bilibili.com/video/BV1Fo4y1d7JL?from=search&seid=17628666 ...

  4. OpenCV 学习笔记03 boundingRect、minAreaRect、minEnclosingCircle、boxPoints、int0、circle、rectangle函数的用法...

    函数中的代码是部分代码,详细代码在最后 1 cv2.boundingRect 作用:矩形边框(boundingRect),用于计算图像一系列点的外部矩形边界. cv2.boundingRect(arr ...

  5. 字节跳动大佬的Python自学笔记.pdf

    1. 字节跳动大佬的Python自学笔记 这是我的一个朋友自学资料包,通过这个资料包自学拿到了字节跳动的Offer, 下面是他之前入门学习Python时候的学习资料,非常全面,从Python基础.到w ...

  6. JAVA自学笔记07

    JAVA自学笔记07 1.构造方法 1) 例如:Student s = new Student();//构造方法 System.out.println(s);// Student@e5bbd6 2)功 ...

  7. MySQL自学笔记2--select的5个子句

    MySQL自学笔记 使用的MySQL自带命令客户端,其中具体的操作是在自建的数据库下room303表中进行的,表中的列有:id.name.age.email.tel.salary.riqi.class ...

  8. opencv学习笔记(二):基于肤色的人手检测

    opencv学习笔记(二):基于肤色的人手检测 原文:http://blog.csdn.net/wzmsltw/article/details/50849810 先写了人手的检测程序,下一步基于检测程 ...

  9. python做直方图-python OpenCV学习笔记实现二维直方图

    本文介绍了python OpenCV学习笔记实现二维直方图,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/dd/d0d/tutorial_py_2d ...

最新文章

  1. 开平方的 7 种算法
  2. 大神的xml解析之路
  3. 使用PHPExcel判别和格式化Excel中的日期格式
  4. spring boot报错:Unable to start embedded Tomcat server 权限不够
  5. 第3章:Kubernetes监控与日志管理
  6. 前端学习(1262):fetch请求参数
  7. php验证密码后跳转_php-laravel框架用户验证(Auth)模块解析(四)忘记密码
  8. 【面向对象设计的5个原则】
  9. 运动控制卡中伺服电机的规划位置与编码器位置的区别
  10. Bash递归函数计算斐波纳吉(fibonacci)数列
  11. ubuntu截图工具KSnapshot(静态图),peek(动态图)
  12. rk3568 LTE(EC20)
  13. OPPO R7s线刷和恢复出厂设置的比较
  14. 谷歌浏览器的本地收藏夹在什么位置?
  15. 手机备份到底备份什么
  16. 线程状态是五种对?还是六种对?
  17. excel切片器_听说你还不会用切片器?比筛选好用100倍,小白也能学会
  18. 芋道 Spring Boot 对象转换 MapStruct 入门
  19. Jmeter基础篇(12):用户自定义变量
  20. 链表基本操作的函数实现。(1)

热门文章

  1. python作排产计划_轻松打造11周精通python计划(完结) | 软件库
  2. Esx host补丁更新
  3. wps底纹去不掉_WPS广告太多,关又关不掉,其实它有无广告的版本
  4. FINN(二)CNN,BNN及其硬件实现的背景知识
  5. 降低屏幕亮度,减缓眼疲劳 (linux/windows/firefox/android)
  6. php小程序中的页面如何换行,解决微信小程序scroll-view换行问题
  7. 永磁同步电机力矩控制(二):FOC与DTC
  8. 架构师之spring------@Autowire注入多泛型实例 can not cast to的问题解决
  9. Android录像时添加时间水印
  10. 电子学会图形化scratch编程等级考试二级真题答案解析(选择题)2020-9A卷