opencv学习笔记

一、计算机眼中的图像

在计算机眼中,每一个图像都是由若干个像素点组成的,而每个像素点就是一个值,这个值是在0~255之间进行浮动的,代表这个像素点的亮度。这个值越接近0,则代表这个像素点亮度比较低,也就是越接近黑色,而这个值越接近255,则代表这个像素点亮度越高,也就是越接近白色。

1.颜色通道

颜色通道可以简单理解为图像的色彩,彩色图像就是一个多通道的图像,而最常见的单通道图像就比如灰度图,也就是黑白图等。

在不同的颜色通道上,同一个像素点哪怕位置相同,但其所代表的值也不一定相同,比较常见的多颜色通道有RGB三通道,分别是Red(红色),Green(绿色),Blue(蓝色)。一个像素点在不同的颜色通道上有不同的取值,代表这个像素点在该颜色通道上对应位置的亮度。

2.呈现形式

既然图像在计算机眼中是由一个个值组成的,那么自然而然的,在计算机眼中,图像就是以矩阵的形式呈现的。我们在处理的过程中,则是用numpy中的ndarray这一数据类型来对其进行表示。

单通道的图像和多通道的图像在表示时当然也有所不同,我们就用灰度图和彩色图来进行对比。    灰度图在计算机眼中由于是单通道的图像,那么就是由一个二维的矩阵来进行呈现。                      彩色图则是一个三维的矩阵来程序,就以RGB三通道来举例,则是Red通道一个二维矩阵,Green通道一个二维矩阵,Blue通道一个二维矩阵,而只有这三个矩阵一起组合成一个三维矩阵,才是这张彩色图在计算机眼中完整的呈现。

二、数据读取

数据读取也分为对图像数据的读取和对视频数据的读取。

1.对图像数据的读取与展示

import cv2     #cv2是opencv库中的一个模块
import matplotlib.pyplot as plt   # 引入这个plt主要用于对处理后的图像进行展示、
import numpy as np    

img = cv2.imread('cat.jpg')

利用cv2.imread()函数就可以对图像数据进行读取了,用img这个变量来进行接收,于是img就是cat.jpg这个图像的像素矩阵了。

当然,导入的时候也可以指定导入的图像的颜色通道,就是cv2.imread()函数的第二个参数,          cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道 cv2.IMREAD_GRAYSCALE:读入灰度图片                                                  cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道                                         也可以写成如下:                                                                                                                            取值0,将图像转化为灰图;                                                                                                                取值2,原深度图像;                                                                                                                            取值4,原颜色图像;                                                                                                                            取值1为彩图 

注意:这里导入了matplotlib模块是用于对处理后的图像的展示,但matplotlib是以RGB的格式展示,而在cv2.read函数中是以BGR的格式读取的,因此若要用matplotlib展示,需要先对颜色通道进行一个转换。所以一般我们用cv2中的展示函数来进行展示。

接下来就是对图像的展示。

cv2.imshow('image',img)  #图片的展示
cv2.waitKey(0)   #展示的时间
cv2.destryAllWindows()   #关闭窗口

cv2.imshow()函数中第一个参数是一个字符串,为用于展示图片的窗口命名,第二个参数就是要展示的像素矩阵。

cv2.waitKey()函数是一个窗口展示时间长短的函数,参数填写要展示窗口的时间,单位是毫秒,但填写0作为参数时,则代表展示窗口直到按下键盘的任意键。

cv2.destryAllWindows()函数是一个用于关闭窗口的函数,在前面的操作中也许会打开许多窗口,使用这个函数可以直接把前面打开的许多窗口在这个函数执行的时候全部销毁。

2.对视频数据的读取与展示

视频其实可以理解为多张图像的连续展示而形成的。

这里我们要先引入一个帧数的概念,所谓帧数就是一秒内所出现的图像数。举个例子,100帧就是一秒内出现了一百张图像的意思,帧数越高,所形成的视频在我们人眼看来则越自然,越连贯。人眼所看到30帧以上的视频就可以认为这个是个连贯内容了。

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

以上这个代码就是用cv2.VideoCapture()函数来对视频转化成一个视频流的东西,用一个变量去接收。

if vc.isOpened():  #判断提取的视频流是否能打开
    open,frame = vc.read()     #检查能否读到第一帧
else:
    open = Flase
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(10) & OxFF == 27 :     #展示的时间和设定按什么键退出展示
            break
vc.release()    #释放该线程
cv2.destroyAllWindows()     #销毁所有出现的窗口

以上便是对这个视频流进行打开和展示,

isOpened()函数是用于检测这个视频流能否进行打开,会返回一个布尔类型。

read()函数是一个打开视频流的函数,会返回两个值,第一个值是代表是否读取到了一个有图像的一帧画面,是布尔类型值,第二个值是所读取到的那一帧画面的像素矩阵。如果在一个循环中多次对一个对象多次执行read()函数,read()函数则会依次读取这个视频流的每一帧。

cv2.Color()函数是一个转化颜色通道的函数,第一个参数是需要转化的对象,第二个参数是要执行的转化操作,例如上述例子中的cv2.COLOR_BGR2GRAY,就是把BRG三通道的图转化成单通道的灰度图,这样的参数还有很多,以此类推。

release()函数是一个释放函数,当前可以简单理解为释放这个线程的操作,一般用于多线程操作时的程序中。

三、ROI区域截取

1.区域截取

ROI是Region of interest的缩写,就是感兴趣的区域的意思,但其实你可以理解为就是对部分区域的截取的意思。

img = cv2.imread('cat.jpg')    #读入图像
cat = img[0:200,0:200]    #ROI区域截取
cv_show('cat',cat)     #展示图像,第一个参数是展示窗口的名字,第二个参数是所要展示的像素矩阵

实际上就是运用了numpy矩阵中的知识,对这个矩阵进行一个区域的截取,使得截取后的矩阵是我们感兴趣的区域。                                                                                                                              所使用的方法就是在大矩阵中用索引的方法取一个小矩阵。

2.颜色通道的分离,合并和提取

颜色通道的分离,合并和提取都是对颜色通道的操作,下面用BGR三颜色通道进行示范。

B,G,R = cv2.split(img)     #将img这个像素矩阵的颜色通道进行分离
img = cv2.merge((B,G,R))   #将三个颜色通道重新合并为一个像素矩阵

cv2.split()函数就是用于将颜色通道分离,多少个颜色通道就用多少个变量去依次接收那些颜色通道。                                                                                                                                                     cv2.merge()函数就是用于将颜色通道合并,将要合并的颜色通道以集合的形式作为参数输入到该函数中,再用一个变量来接收合并后的像素矩阵。

#提取R通道
cur_img = img.copy()
cur_img[:,:,0] = 0    #将B通道赋值为0
cur_img[:,:,1] = 0    #将G通道赋值为0 
cv_show('R',cur_img)

提取其中的颜色通道原理也很简单,将不需要的颜色通道通过矩阵赋值的形式将其赋值为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,
                            borderType=cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,
                               borderType=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)

边界填充要用到cv2.copyMakeBorder()函数来进行边界填充的操作,第一个参数是你要进行填充的图片,接下来的参数依次是上、下、左、右所要填充的数值(可以理解为改方向上要加宽多少),而第三部分的参数就是指定填充的方式。

1)复制法,就是复制最边缘像素
BORDER_REPLICATE

2)反射法1,对感兴趣的图像中的像素在两边进行复制
BORDER_REFLECT
例如: dcba | (图像像素) abcd | dcba

3)反射法2,就是以最边缘像素为轴,对称
BORDER_REFLECT_101
例如: dcb | (图像像素) abcd | cba

4)外包装法
BORDER_WRAP
例如: abcd | (图像像素) abcd | abcd

5)常量法,常数值填充                                                                                                    BORDER_CONSTANT

五、数值计算

两个像素矩阵是可以进行数值计算的,计算的规则就是numpy的矩阵运算。

但有个要注意的是,在像素矩阵的计算中,由于像素点的亮度取值区间是0~255,因此倘若计算后的值超过了255,则要减去256(0~255一共有256个数)。

六、图像融合

图像融合一般分为两步,因为在融合有个前提条件,就是参与融合的像素矩阵一定是要相同大小的,才能进行融合。

1.变换目标行列大小

变换目标的行列大小。

img_dog = cv2.resize(img_dog,(500,414))

cv2.resize()函数可以达到修改目标行列大小的目的,第一个参数是所要修改的对象,第二个参数是列行的集合。

注意:第二个参数是 "宽" "高" 的集合,而一般我们在查看像素矩阵的shape属性是,给的是"高" "宽",因此这里需要特别注意。

cv2.resize()函数还可以改变图片的宽高的比例

img_dog = cv2.resize(img_dog,(0,0),fx = 3,fy = 1)

cv2.resize()函数改变图像比例的方法就是在原来指定修改的宽高的集合中,将宽高都改成0,然后在后面用fx,fy分别指定一个数,fx和fy的比例,就是图片中宽和高的比例。像上述例子中,宽高的比例就是3:1。 

2.图像融合

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

用cv2.addWeighted()函数可以完成图像融合的操作,第一部分的参数有两个,第一个是所要融合的像素矩阵,和在融合的图片中的显示比例;第二部分的参数则是第二个所要融合的像素矩阵和所要融合的比例,而第三部分的参数是偏置参数,一般来说填0就行。

七、图像阈值

我们也可以有方法对一个像素矩阵中的每个像素点进行一个统一处理。

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)

这里用到的是cv2.threshold()函数,下面我们详细讲讲该函数的参数。

ret,dst = cv2.threshold(src,thresh,maxval,type)                                                                 注意:这里的ret返回值在实际中使用的并不多,ret返回的是你函数中设置的阈值。

src:输入图,只能输入单通道图像,通常来说是灰度图                                                                    dst:输出图                                                                                                                                        thresh:阈值                                                                                                                                      maxval:当像素值超过了阈值(或者小于阈值,由后面的type决定),所赋予的值                        type:二值化的操作类型,包括以下五种类型:

      1)cv2.THRESH_BINARY---------------超过阈值部分取maxval(最大值),否则取0                        2)cv2.THRESH_BINARY_INV---------------cv.2THRESH_BINARY的反转式                                    3)cv2.THRESH_TRUNC---------------大于阈值部分设为,否则不变                                                4)cv2.THRESH_TOZERO---------------大于阈值部分不改变,否则为0                                            5)cv2.THRESH_TOZERO_INV---------------TOZERO的反转

                               

 八、图像的平滑处理

首先我们要引入一个图像中的噪音的概念。

1.图像中的噪音

图像中的噪声通常表现为孤立像素或像素块的更强的视觉效果。一般来说,噪声信号与所要研究的对象无关,它采取无用信息的形式,扰乱了可观测信息的图像。流行的说法是图像不清晰的噪声是图像数据中存在的对不必要的干扰或冗余信息。图像对人们接受各种信息的障碍可称为图像噪声。

图像中的黑色的孤立像素点或像素块叫做椒点,而白色的叫盐点,如果一个图像中这两种形式的噪音都有,那么就叫椒盐噪音。

而我们要进行的图像平滑处理,就是为了把这些噪音所带来的影响尽可能的消除。

2.图像的平滑处理

通过不同的滤波依次对每个像素点进行处理,来将噪音点处理掉,但会对图像清晰度等造成一定的副作用。

1)均值滤波

均值滤波是指以当前像素点为中心,使用当前像素点周围N * N个像素值的均值来代替当前像素值。使用该方法遍历处理图像内每一个像素点,既可以完成整幅图像的均值滤波。

​ 针对图像边缘像素点,可以只取图像内存在的周围邻域点的像素值的均值。也可以将图像边缘扩展后,可以在新增的行和列内填充不同的像素值,在此基础上,再针对原始图像进行N · N邻域像素点的均值计算。OpenCV提供了多种边界处理方式,我们可以根据实际需要选用不同的边界处理模式。
 

函数语法:

在OpenCV中,实现均值的函数是cv2.blur(),其语法格式:

dst = cv2.blur(src, ksize, anchor, borderType)

dst:返回值,均值滤波处理后得到的处理结果。

src:需要处理的图像,即原始图像。可以有任意数量的通道,并能对各个通道独立处理。图像的深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

ksize:是滤波核的大小。滤波核大小指在均值处理过程中,其邻域图像的高度和宽度。例如,其值可以是(5, 5),表示以5×5大小的邻域均值作为图像均值滤波处理的结果。

M和N分别对应高度和宽度。一般情况下,M和N是相等的,例如比较常用的3×3、5×5、7×7等。如果M和N的值越大,参与运算的像素点数量就越多,图像失真越严重。

anchor:锚点,其默认值是(-1,-1), 表示当前计算均值的点位于核的中心点位置,该值使用默认值即可,在特殊情况下可以指定不同的点作为锚点。

borderType:边界样式,该值决定了以何种方式来处理边界,一般情况下不需要考虑该值的取值,采用默认情况即可。
 

import cv2

img = cv2.imread('../lena512color_noise.tiff')
dst1 = cv2.blur(img, (7, 7))
dst2 = cv2.blur(img, (15, 15))
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

 2)方框滤波

方框滤波与均值滤波不同,方框滤波不会计算像素均值。在均值滤波中,滤波结果是任意一点的邻域平均值。方框滤波可以自由选择对均值滤波的结果是否进行归一化,既可以自由选择滤波结构是邻域之和,还是邻域之和的平均值。

注意:可以理解为方框滤波基本与均值滤波相同,但方框滤波可以选择是否归一化(归一化就是求均值,不归一化就是求和)

函数语法:

在OpenCV中,实现方框滤波的函数是cv2.boxFilter(),其语法格式是:

dst = cv2.boxFilter(src, ddepth, ksize, anchor, normalize, borderType)

dst:返回值,均值滤波处理后得到的处理结果。

src:需要处理的图像,即原始图像。可以有任意数量的通道,并能对各个通道独立处理。图像的深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

ddepth:结果图像的图像深度,一般使用-1表示与原始图像使用相同的图像深度。

ksize:是滤波核的大小。滤波核大小指在均值处理过程中,其邻域图像的高度和宽度。例如,其值可以是(5, 5),表示以5×5大小的邻域均值作为图像均值滤波处理的结果。
在这里插入图片描述

anchor:锚点,其默认值是(-1,-1), 表示当前计算均值的点位于核的中心点位置,改制使用默认值即可,在特殊情况下可以指定不同的点作为锚点。

normalize:表示在滤波时是否进行归一化处理(归一化:这里指的是将计算结果规范到合理的范围内,即将计算结果规范到当前像素值范围内的值)处理。该参数是一个逻辑值。

当参数normalize=1时,表示进行归一化处理,要用邻域像素值得和处理面积。
当参数normalize=0时,表示不需要进行归一化处理,直接使用邻域像素值的和。(当和超出255时为255)
通常情况下,针对方框滤波,卷积核可以表示为:
在这里插入图片描述

borderType:边界样式,该值决定了以何种方式来处理边界。

通常情况下,在使用方框滤波函数时,对于参数anchor、normalize、borderType,直接采用默认值即可。 

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.boxFilter(img, -1, (7, 7))
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

3)高斯滤波

 在均值滤波和方框滤波中,其邻域内每个像素的权重是相等的。在高斯滤波中,会将离中心点近的权重加大,离中心点远的权重减小,在此基础上计算邻域内各个像素值不同权重的和。

简单理解:可以理解为高斯滤波更重视中间的值。

函数语法

在OpenCV中,实现高斯滤波的函数cv2.GaussianBlur(),该函数的语法格式是:

dst = cv2.GauusianBlur(src, ksize, sigmaX, sigmaY, borderType)

dst:返回值,均值滤波处理后得到的处理结果。

src:需要处理的图像,即原始图像。可以有任意数量的通道,并能对各个通道独立处理。图像的深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

ksize:是滤波核的大小。滤波核大小指在均值处理过程中,其邻域图像的高度和宽度。但需要注意,滤波核的值必须是奇数。

sigmaX:卷积核在水平方向上(X轴方向)的标准差,其控制的是权重比例。

sigmaY:卷积核在垂直方向上(Y轴方向)的标准差,如果将该值设置为0,则只采用sigmaX的值;如果sigmaX、sigmaY都是0,则通过ksize.width和ksize.height计算得到:

sigmaX = 0.3 × [(ksize.width-1) × 0.5-1] + 0.8
sigmaY = 0.3 × [(ksize.height-1) × 0.5-1] + 0.8
borderType:边界样式,该值决定了以何种方式来处理边界。一般情况下,不需要考虑该值,直接采用默认值。

注意:在该函数中sigmaY、borderType是可选参数。sigmaX是必选参数,但是可以将其设置为0,让函数自己去计算sigmaX的具体值。

​ 官方文档建议显示的指定ksize、sigmaX、sigmaY三个参数的值,以避免将来参数修改后可能造成的语法错误。当然,实际处理中,可以显示的指定sigmaX、sigmaY为默认值0。因此,函数cv2.GaussianBlur()的常用形式为:

dst = cv2.GaussianBlur(src, ksize, 0, 0)

import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.GaussianBlur(o,(5,5),0,0)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

4)中值滤波

中值滤波不同于前面的滤波方式,不再采用滤值的方式计算滤波的结果。它采用的是邻域内所有像素值的中间值来替代当前像素点的像素值。

函数语法:

在OpenCV中,实现中值滤波的函数是cv2.medianBlur(),其语法格式是:

dst = cv2.medianBlur(src, ksize)

dst:返回值,均值滤波处理后得到的处理结果。

src:需要处理的图像,即原始图像。可以有任意数量的通道,并能对各个通道独立处理。图像的深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

ksize:是滤波核的大小。滤波核大小指在均值处理过程中,其邻域图像的高度和宽度。但需要注意,滤波核的值必须是比1大的奇数, 比如3、5、7等。
 

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.medianBlur(img, 5)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,OpenCV是一个开源计算机视觉和机器学习软件库,用于开发图像和视频处理应用程序。通过使用OpenCV,您可以读取摄像头并显示实时图像,打开视频文件或摄像头文件,并获取视频的相关信息,例如帧宽度、帧高度、帧率和总帧数。 对于学习OpenCV,你可以按照以下步骤进行: 1. 安装OpenCV库:在开始学习OpenCV之前,您需要从OpenCV官方网站下载和安装OpenCV库。根据您的操作系统和编程语言选择合适的版本。 2. 学习基本概念:熟悉OpenCV的基本概念和术语,例如图像和视频的加载、显示、保存以及常用的图像处理操作,如滤波、边缘检测和特征提取等。 3. 掌握OpenCV函数和类:深入了解OpenCV提供的函数和类,例如cv::Mat用于图像和矩阵操作,cv::VideoCapture用于读取和处理视频,以及cv::imshow和cv::waitKey等用于显示图像的函数。 4. 实践项目:通过完成一些实践项目来应用您所学到的知识。例如,利用OpenCV实现人脸检测、目标追踪、图像识别等。 5. 学习资料和资源:查找和阅读OpenCV的官方文档、教程和示例代码,参与开源社区讨论和交流,加入相关的论坛和邮件列表等。 总结起来,学习OpenCV包括安装OpenCV库、学习基本概念、掌握OpenCV函数和类、实践项目以及查找和阅读相关资料和资源。通过不断实践和学习,您将能够更好地理解和应用OpenCV库来开发图像和视频处理应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值