opencv-python学习笔记

这是看视频的笔记,大部分内容抄自老师的笔记,稍微微加了自己百度的一些解析,侵删。

安装

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

图像阈值

ret, dst = cv2.threshold(src, thresh, maxval, type)
  • 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()

图像梯度-Sobel算子

在这里插入图片描述

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,所以要取绝对值

图像梯度-Scharr算子
在这里插入图片描述

在这里插入图片描述

各有特点

Canny边缘检测

    1.    使用高斯滤波器,以平滑图像,滤除噪声。
      
    1.    计算图像中每个像素点的梯度强度和方向。
      
    1.    应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
      
    1.    应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
      
    1.    通过抑制孤立的弱边缘最终完成边缘检测。
      
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:轮廓检索模式

  • RETR_EXTERNAL :只检索最外面的轮廓;
  • RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
  • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
  • RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次; 建议用这个

method:轮廓逼近方法

  • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
  • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。
#为了提高准确率,对图像进行二值化
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
  • TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
  • TM_CCORR:计算相关性,计算出来的值越大,越相关
  • TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
  • TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
  • TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
  • TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关
    建议用带归一化的方法

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)

直方图与模板匹配

cv2.calcHist(images,channels,mask,histSize,ranges)
  • images: 原图像图像格式为 uint8 或 float32。当传入函数时应 用中括号 [] 括来例如[img]
  • channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
  • mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如 果你想统图像某一分的直方图的你就制作一个掩模图像并 使用它。
  • histSize:BIN 的数目。也应用中括号括来
  • ranges: 像素值范围常为 [0,256]

没听太懂…

傅里叶变换

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值