Opencv学习笔记——基础知识

Posted zyw2002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv学习笔记——基础知识相关的知识,希望对你有一定的参考价值。

1. Opencv 环境配置

为了避免依赖的冲突和python版本的不匹配,建议重新建立一个虚拟环境。

要确保python版本和opencv版本匹配。在这里,我采用的是opencv 3.8.8 和 opencv 4.5.3,并且已经配置好Anaconda。

1.1 创建opencv虚拟环境

  1. 创建虚拟环境(其中opencvEnv是自己起的名字,也可以用其他的名字)

    Anaconda Prompt 中键入conda create -n opencvEnv python=3.8.8

  2. 进入虚拟环境

    activate opencvEnv

  3. 安装opencv

    pip install opencv-python

    pip install opencv-contrib-python

  4. 安装matplotlib库(后续画图需要)

    pip install opencv-python

1.2 让notebook 进入虚拟环境

  1. 在当前虚拟环境下安装conda install ipykernel
  2. 将当前环境写入notebook中python -m ipykernel install --user --name opencvEnv --display-name opencvEnv
  3. 如果没有安装notebook ,则键入pip install notebook
  4. 打开notebookipython notebook
  5. 切换当前环境为新建立的虚拟环境opencvEnv(在导航栏中点击“kernel","change kernel ",“opencvEnv”)

1.3 虚拟环境导入pycharm

  1. 点击"File" ,“setting”, “project”,“python interpreter”

  2. 点击

  3. 点击"add"

  4. 点击"Conda Environment",“Existing environment”

  5. 选择“opencvEnv”,“OK”

2. 图像的基本操作

图片数据大小 h e i g h t ∗ w i d t h ∗ 3 height*width*3 heightwidth3

h e i g h t ∗ w i d t h height*width heightwidth: 像素点的个数

3 3 3:R,G,B三个颜色通道

因此图片可以有三个大小为height*width的矩阵构成,矩阵中的元素值表示当前颜色通道的亮度大小,取值范围是[0,255], 数值越大,表明该区域越亮。

2.1 读取图片

2.1.1 基本操作

  1. 导入库
import cv2 
import matplotlib.pyplot as plt
import numpy as np 
%matplotlib inline 
  1. 读取图片

    opencv的读取格式是BGR, 读取格式是cv2.imread(), 参数是图片位置

    img=cv2.imread('cat.jpg') # 图片与源程序处于同一个目录下
    img # 打印img的矩阵格式
    
  2. 显示图片

    cv2.imshow( )

    第一个参数是图片名字,第二个参数是已经读取完的图片

    cv2.imshow('image',img) 
    
    cv2.waitKey(0) # 等待时间,毫秒级,0表示任意键终止
    cv2.destroyAllWindows() 
    

定义显示图片的函数

def cv_show(name,img):
    cv2.imshow(name,img) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
  1. 图片的大小

    img.shape

    img.shape # (414,500,3)
    
  2. 灰度图片

    cv2.imread(' ',cv2.IMREAD_GRAYSCALE)

    • cv2.IMREAD_COLOR:彩色图像
    • cv2.IMREAD_GRAYSCALE:灰度图像
    img=cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE)
    img.shape #(414,500) 灰度图片只有单通道,表示亮度
    

    显示图片

    cv2.imshow('image',img) 
    
    cv2.waitKey(10000) #等待10000毫秒后自动关闭
    cv2.destroyAllWindows()
    

  1. 保存图片

    cv2.imwrite(' ', ) 参数一:保存的文件名;参数二:保存的图片

    cv2.imwrite('mycat.png',img)
    
  2. 图片的类别

    图片在计算机中一ndarray的数据结构保存

    type(img) # numpy.ndarray
    
  3. 图片大小

    img.size #207000
    
  4. 保存图片的数据类型

    img.dtype #dtype('uint8')
    
  5. 截取部分图像数据

    img=cv2.imread('cat.jpg')
    cat=img[0:50,0:200] 
    cv_show('cat',cat)
    

2.1.2 颜色通道提取

  1. 颜色通道提取

    cv2.split(), 参数是图片,返回值分别为b,g,r

    1. b,g,r=cv2.split(img)
       r.shape #(414,500)
    
  2. 颜色通道合成

    cv2.merge(), 参数是颜色通道组成的元组,返回值是图片

    img=cv2.merge((b,g,r))
    img.shape # (414, 500, 3)
    
  3. 保留单通道

    只保留R

    cur_img = img.copy()
    cur_img[:,:,0] = 0 #b通道置为0
    cur_img[:,:,1] = 0 #g通道置为0
    cv_show('R',cur_img)
    

只保留G

# 只保留G
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,2] = 0
cv_show('G',cur_img)

只保留B
cur_img = img.copy()
cur_img[:,:,1] = 0
cur_img[:,:,2] = 0
cv_show('B',cur_img)

2.2 读取视频

  • cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
  • 如果是视频文件,直接指定好路径即可。
  1. 读视频

    cv2.VideoCapture( ) 参数是视屏路径

    vc = cv2.VideoCapture('test.mp4')
    

    检查打开的是否正确,其中open 是bool类型的数据,为True表示可以正确打开,反之则不能; frame表示读取视频中的一帧数据。

    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)  #将每一帧图片转化为灰度图片
            cv2.imshow('result', gray) # 显示每一帧的灰度图片
            if cv2.waitKey(100) & 0xFF == 27: #相邻两个帧展示间隔时间为100ms, 0xFF 是退出键
                break
    vc.release()
    cv2.destroyAllWindows()
    

2.3 边界填充

cv2.copyMakeBorder() 参数是待处理的图片,上下左右边框大小,填充方式

  • BORDER_REPLICATE:复制法,也就是复制最边缘像素。
  • BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
  • BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
  • BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
  • BORDER_CONSTANT:常量法,常数值填充。
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)

画图展示处理效果

import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

plt.show()

2.4 图像融合

2.4.1 数值计算

img_cat=cv2.imread('cat.jpg')
img_dog=cv2.imread('dog.jpg')

img_cat2= img_cat +10  # 相当于在每一个像素点位置加10
img_cat[:5,:,0]
'''
array([[142, 146, 151, ..., 156, 155, 154],
       [108, 112, 118, ..., 155, 154, 153],
       [108, 110, 118, ..., 156, 155, 154],
       [139, 141, 148, ..., 156, 155, 154],
       [153, 156, 163, ..., 160, 159, 158]], dtype=uint8)
'''
img_cat2[:5,:,0]
'''
array([[152, 156, 161, ..., 166, 165, 164],
       [118, 122, 128, ..., 165, 164, 163],
       [118, 120, 128, ..., 166, 165, 164],
       [149, 151, 158, ..., 166, 165, 164],
       [163, 166, 173, ..., 170, 169, 168]], dtype=uint8)
'''
(img_cat + img_cat2)[:5,:,0]  #相当于% 256
'''
array([[ 38,  46,  56, ...,  66,  64,  62],
       [226, 234, 246, ...,  64,  62,  60],
       [226, 230, 246, ...,  66,  64,  62],
       [ 32,  36,  50, ...,  66,  64,  62],
       [ 60,  66,  80, ...,  74,  72,  70]], dtype=uint8)
'''

cv2.add将两张图片相加时,当和超多255时,用255代替。

cv2.add(img_cat,img_cat2)[:5,:,0]
'''
array([[255, 255, 255, ..., 255, 255, 255],
       [226, 234, 246, ..., 255, 255, 255],
       [226, 230, 246, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)
'''

2.4.2 图像融合

当大小不同的两张图片相加会报错。

img_cat.shape # (414, 500, 3)
  1. 调整图片大小

    cv2.resize() 参数是待处理的图片,和期望的宽高。

    img_dog = cv2.resize(img_dog, (500, 414))
    img_dog.shape # (414, 500, 3)
    

    还可以按照比例缩放

    res = cv2.resize(img, (0, 0), fx=1, fy=3)
    plt.imshow(res)
    

  1. 按照权重融合

    cv2.addWeighted()参数是待处理的两张图片和各自的权重

    res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)
    plt.imshow(res)
    

2.5 灰度图

cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 

img=cv2.imread('cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img_gray.shape #(414, 500)

展示图片

cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)    
cv2.destroyAllWindows() 

2.6 HSV

  • H - 色调(主波长)。
  • S - 饱和度(纯度/颜色的阴影)。
  • V值(强度)

cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

cv2.imshow("hsv", hsv)
cv2.waitKey(0)    
cv2.destroyAllWindows()

3. 阈值和平滑处理

3.1 图像阈值

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的反转
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

3.2 图像平滑

图像平滑的目的是降低噪声点的影响

img = cv2.imread('lenaNoise.png')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

滤波实际上时进行卷积

均值滤波:简单的平均卷积操作

blur = cv2.blur(img, (3, 3))

方框滤波: 基本和均值一样,可以选择归一化

box = cv2.boxFilter(img,-1,(3,3), normalize=True) 

高斯滤波:高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间

aussian = cv2.GaussianBlur(img, (5, 5), 1) 

中值滤波:相当于用中值代替

median = cv2.medianBlur(img, 5)

展示所有的处理效果图

res = np.hstack((blur,aussian,median))
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 图像形态学操作

4.1 腐蚀操作

读入原始图片

img = cv2.imread('dige.png')

cv2.imshow('img', i
mg)
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()

读入原始图片

pie = cv2.imread('pie.png')

cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()

观察迭代次数对于腐蚀的影响

kernel = np.ones((30,30),np.uint8) 
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2 膨胀操作

展示原始图片

img = cv2.imread('dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

先进行腐蚀操作

kernel = np.ones((3,3),np.uint8) 
dige_erosion = cv2.erode(img,kernel,iterations = 1)

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在进行膨胀操作

cv2.dilate()膨胀操作, 参数是图片,卷积核,迭代次数

kernel = np.ones((3,3以上是关于Opencv学习笔记——基础知识的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV学习笔记总结

Opencv学习笔记——基础知识

基础学习笔记之opencv:实现将图片生成视频

DOM探索之基础详解——学习笔记

C++下opencv学习笔记(图像的简单读取丶显示与存储)

OpenCV学习笔记2基础:读取播放保存视频