这是看视频的笔记,大部分内容抄自老师的笔记,稍微微加了自己百度的一些解析,侵删。
Anaconda要装3.5.2,对应python3.6版本,无外网推荐用清华源镜像
链接 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
OpenCV装3.4.1.15
指令:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python == 3.4.1.15
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.1.15
https://repo.anaconda.com/archive/ 从这里选择对应anaconda版本,另外,python版本和下载的opencv版本有关,刚开始我用的版本不对,会有报错
总之,环境配置是一大步。
im = cv2.imread(‘cat.jpg’) 读取图片 返回的是一个列表 储存每一个像素点的数据
还有一个可选参数:cv2.IMREAD_GRAYSCALE 灰度图
cv2.IMREAD_COLOR 彩色图 默认为彩色
图像的显示
#图像的显示,也可以创建多个窗口
cv2.imshow(‘mao’,img)
#等待时间,毫秒级,0表示任意键终止
cv2.waitKey(10000)
cv2.destroyAllWindows()
cv2.waitKey(10000) 表示出现窗口等待的时间,若参数为 -1,则表示不设置窗口出现时间,一般该参数设置为 -1
cv2.destroyAllWindows()表示按下任意键销毁窗口
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以定义该函数来显示图像
**cv2.imwrite(‘223.png’,img)**保存图片 第一个参数为保存图片的名字
type(img) img的类型为numpy.ndarray
img.size img大小
img.dtype dtype(‘uint8’)
cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
参数是0,表示打开笔记本内置摄像头
如果是视频文件,直接指定好路径即可。
**ret, frame =vc.read()**vc.read()按帧读取视频,ret,frame是获cap.read()方法的两个返回值。其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵。
vc = cv2.VideoCapture('test.mp4')
# 检查是否打开正确
if vc.isOpened():
oepn, frame = vc.read()
else:
open = False
while open:
ret, frame = vc.read()
if frame is None:
break
if ret == True:
# 就是个处理一帧的例子,这里转为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 不断显示一帧,就成视频了
# 这里没有提前创建窗口,所以默认创建的窗口不可调整大小
# 可提前使用cv.WINDOW_NORMAL标签创建个窗口
cv2.imshow('result', gray)
if cv2.waitKey(3) & 0xFF == 27: # 每3ms播放一帧 按下Esc键退出 或者cv.waitKey(1) & 0xFF == ord('q')按下 q 退出
break
vc.release()
#调用release()释放摄像头,调用destroyAllWindows()关闭所有图像窗口
cv2.destroyAllWindows()
img=cv2.imread('cat.jpg')
cat=img[0:50,0:200]
cv_show('cat',cat)
b,g,r=cv2.split(img)
合并通道
img=cv2.merge((b,g,r))
img.shape
**# 只保留R
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show(‘R’,cur_img)
**
把索引0,和1 置0
top_size,bottom_size,left_size,right_size = (50,50,50,50)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)
** BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充**
img_cat2= img_cat +10
图像上每个像素点都加10
(不知道有啥用,反正知道有可以相加这个操作就可以了 加10前后的图像
)
两个图片也可以直接相加,cv2中大于255部分的对255取余处理 img_cat + img_cat2
用函数相加的话,大于255部分直接取255 cv2.add(img_cat,img_cat2)
融合的图像shap必须一样,否则会 ValueError: operands could not be broadcast together with shapes (414,500,3) (429,499,3)
更改图片大小函数 img_dog = cv2.resize(img_dog, (500, 414))
还可以 res = cv2.resize(img, (0, 0), fx=4, fy=4) 前两个参数为(0,0),后面两个参数为倍数
融合图片:res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)
0.4 0.6 分别为图片的权重 最后一项为偏移项 相当于w=ax+by+c 中的c
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0 常作为二值化操作
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转
#简单的平均卷积操作
blur = cv2.blur(img, (3, 3)) #周围3x3方框的均值
#基本和均值一样,可以选择归一化
box = cv2.boxFilter(img,-1,(3,3), normalize=True) #-1 表示颜色通道数一致,通常为-1,不需要去改,normalize=True做归一化处理,譬如3x3加起来,最后除以9就是归一化,选择归一化就和均值滤波操作一模一样,该参数置为False时,不除以9,越界的像素点直接置为255,最后图像会亮很多
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。
cv2.GussianBlur()函数
语法:GaussianBlur(src,ksize,sigmaX [,dst [,sigmaY [,borderType]]])-> dst
——src输入图像;图像可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
——dst输出图像的大小和类型与src相同。
——ksize高斯内核大小。 ksize.width和ksize.height可以不同,但它们都必须为正数和奇数,也可以为零,然后根据sigma计算得出。
——sigmaX X方向上的高斯核标准偏差。
——sigmaY Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,则分别从ksize.width和ksize.height计算得出;为了完全控制结果,而不管将来可能对所有这些语义进行的修改,建议指定所有ksize,sigmaX和sigmaY。
卷积核里的数值是满足高斯分布,相当于更重视中间的
#(5, 5)表示高斯矩阵的长与宽都是5,标准差取1
aussian = cv2.GaussianBlur(img, (5, 5), 1)
cv2.imshow(‘aussian’, aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
离的越近,重要程度越高,权重越大
#相当于用中值代替
median = cv2.medianBlur(img, 5) # 中值滤波 方框中数据从小到大排列,取中间的数
cv2.imshow(‘median’, median)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 展示所有的
res = np.hstack((blur,aussian,median)) #行排列 np.vstack列排列
#print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.erode()函数
kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8) 是画一个3x3的矩阵,类型为uint8
ones()返回一个全1的n维数组,同样也有三个参数:shape(用来指定返回数组的大小)、dtype(数组元素的类型)、order(是否以内存中的C或Fortran连续(行或列)顺序存储多维数据)。后两个参数都是可选的,一般只需设定第一个参数。
erosion = cv2.erode(img,kernel,iterations = 1) 传入图片、“方框”、迭代次数
腐蚀程度和 “方框” 还有迭代次数有关
膨胀·则与腐蚀相反 cv2.dilate()函数
kernel = np.ones((3,3),np.uint8)
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)
cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.morphologyEx() 函数
#开:先腐蚀,再膨胀
img = cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
#闭:先膨胀,再腐蚀
img = cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 梯度=膨胀-腐蚀
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
#黑帽
img = cv2.imread('dige.png')
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')
cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
src:输入图像
ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,当组合为dx=0,dy=1时求y方向的一阶导数(如果同时为1,通常得不到想要的结果)
ksize:(可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。求X方向和Y方向一阶导数时,卷积核分别为 上图
scale:(可选参数)将梯度计算得到的数值放大的比例系数,效果通常使梯度图更亮,默认为1
delta:(可选参数)在将目标图像存储进多维数组前,可以将每个像素值增加delta,默认为0
borderType:(可选参数)决定图像在进行滤波操作(卷积)时边沿像素的处理方式,默认为BORDER_DEFAULT
返回值是 梯度图
图像深度是指存储每个像素值所用的位数,例如cv2.CV_8U,指的是8位无符号数,取值范围为0~255,超出范围则会被截断(截断指的是,当数值大于255保留为255,当数值小于0保留为0,其余不变)。
具体还有:CV_16S(16位无符号数),CV_16U(16位有符号数),CV_32F(32位浮点数),CV_64F(64位浮点数)
函数cv2.convertScaleAbs(src[,alpha[,beta]])
先计算数组绝对值,后转化为8位无符号数
src:输入图像(多维数组)
alpha:比例因子
beta:保存新图像(数组)前可以增加的值
白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
各有特点
使用高斯滤波器,以平滑图像,滤除噪声。
计算图像中每个像素点的梯度强度和方向。
应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
通过抑制孤立的弱边缘最终完成边缘检测。
v2=cv2.Canny(img,50,100)
这两个值为阈值,最小和最大
up=cv2.pyrUp(img)
cv_show(up,'up')
print (up.shape)
down=cv2.pyrDown(img)
cv_show(down,'down')
print (down.shape)
down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')
cv2.findContours(img,mode,method)
mode:轮廓检索模式
method:轮廓逼近方法
#为了提高准确率,对图像进行二值化
img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show(thresh,'thresh')
#检测轮廓操作
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
返回值:binary 是传进去的原图 不过新版opencv把该返回值取消了
contours:保存的是一些轮廓的信息
hierarchy:层级,暂时不懂不用
函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图
#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
cv_show(res,'res')
参数: 1、在哪个图像上画
2、轮廓的像素点
3、-1表示画出所有轮廓,0则表示画第一个,1第二个…
4、画轮廓的线条的颜色 B G R格式
5、线条宽度
#面积
cv2.contourArea(cnt)
#周长,True表示闭合的
cv2.arcLength(cnt,True)
epsilon = 0.15*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)
cv_show(res,'res')
cv2.approxPolyDP()
参数:1、做哪个轮廓
2、指定一个值进行比较的,这个值也可以自己填,一般是按照周长的百分比
还有;轮廓的外接矩形、外接圆等
模板匹配和卷积原理很像,模板在原图像上从原点开始滑动,计算模板与(图像被模板覆盖的地方)的差别程度,这个差别程度的计算方法在opencv里有6种,然后将每次计算的结果放入一个矩阵里,作为结果输出。假如原图形是AxB大小,而模板是axb大小,则输出结果的矩阵是(A-a+1)x(B-b+1)
# 模板匹配
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
res.shape
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
匹配多个对象
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于%80的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # *号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)
没听太懂…