OpeenCV(python)|openCV专栏(一)(基础操作)

OPENCV基础操作教程

提示:本专栏所用版本仅供参考,其他版本也可
版本
python Python 3.9.3
opencv 4.5.5
matplotlib 3.4.3
numpy 1.19.5
学习基础 python及其简单的矩阵计算

学习目录
  • (一)读取一张图像
  • (二)图像的存储形式
  • (三)图像数据的处理
    • 1、依次显示B,G,R三个通道的图像
    • 2、制作一张随机图像
    • 3、像素处理:加减乘除
    • 3、像素处理(按位逻辑操作)
  • (四)摄像头基础操作
  • (五)结束语

(一)读取一张图像 首先,运行如下代码,我们发现桌面上创建了一个名为"img"的窗口并显示了当前文件夹下名为111的图片。(注意,运行前情复制一张图片到写有python代码的文件夹下,并重命名为111)
import cv2#导入cv库img = cv2.imread(".\\111.bmp")#读取图片111 """ ./代表表示文件夹: "./111.bmp"表示当前文件夹下的111图片,格式为bmp """ cv2.imshow("img",img)#显示图片111到窗口 print(img)#打印图像数据 cv2.waitKey(0)#等待键盘任意按键按下 cv2.destroyWindow("img")#关闭img窗口

函数介绍:
函数原型 返回值 参数
cv2.imread(filename[,flags]) 读取的图像 filename:完整文件名
flags:读取类型[如灰度]
cv2.imshow(winname,mat) None
winname:窗口名称
mat:要显示的图像
cv2.waitKey([delay]) 按键的ASCII码 等待键盘触发的时间(ms)
cv2.destroyWindow(winname) None 要销毁窗口的名称
cv2.imwrite(filename,img[,params]) True/False filename:路径名
img:保存的图像
params保存的类型
(二)图像的存储形式 运行(一)的代码后,除了启动一个窗口,还在终端打印了如下数据
OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

可以看到,一个彩色图像在计算机中以三维数组(x,y,3)的形式存储(准确的说,这是RGB彩色图像存储方式,在openCV中,还有其他的图像形式,第二章中将详细讲解),为了感受三维图像,我绘制了如下三维坐标图:
OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

【OpeenCV(python)|openCV专栏(一)(基础操作)】在openCV中,对图像数据的处理分为行,列和通道,对应三维矩阵的形式。行列及其通道决定了像素大小,通道分为R,G,B三通道,表示了不同的三原色,R代表红色,G表示绿色,B表示蓝色。
有了这些数据,我们便可以对图像进行肆无忌惮的处理,修改矩阵中的数据就相当于读图像进行修改。
(三)图像数据的处理 在(二)中,我们有了图像在三维矩阵中存储形式个概念,接下来,我们将对一幅图像的数据进行修改。 在此之前,我们已经通过函数cv2.imread()拿到了图像111的三维数组。
函数 作用
x,y,n = img.shape 获取彩色图像的行,列,通道
value = https://www.it610.com/article/img.size 获取图像的像素大小(size=x* y*N)
1、依次显示B,G,R三个通道的图像
import cv2 img = cv2.imread("./111.jpg")#读取图片111B = img[:,:,0]# 0(B通道) G = img[:,:,1]# 1(R通道) R = img[:,:,2] cv2.imshow("B",B)#显示图片111到窗口 cv2.imshow("G",G)#显示图片111到窗口 cv2.imshow("R",R)#显示图片111到窗口 cv2.imshow("img",img)#显示原图 cv2.waitKey() cv2.destroyAllWindows()#销毁所有窗口

运行结果:
OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

可以看到我们通过获取三维数组的每一个通道表示的二维数组分离了B G R三个通道,且三个通道对不同的颜色表现出了不同的敏感度。
关于通道的分离,我们还可以使用opencv提供的split函数
B,G,R = cv2.split( img ) #分离B,G,R三通道
2、制作一张随机图像 根据(二),我们已经知道了一张图像是以矩阵的形式存储数据。那么理论上,我们也可以手动生成一个数组,并让它显示出来。
矩阵计算相关函数:
名称 作用
numpy 一个提供了大量的矩阵运算的模块
np.zeros() 生成一张全是 0 的矩阵表
np.ones() 生成一张全时 1 的矩阵表
np.random.randint() 生成一张全是随机数的矩阵表
np.hstack() 将多个二维数组水平拼接在一起
import numpy as np#导入np库#np.uint8表示一个无符号字节,大小(0~255) data1 = np.zeros((200,200),np.uint8)#生成一张200*200全为0的矩阵 data2 = np.ones((200,200),np.uint8)#生成一张200*200全为1的矩阵 data2 = data2*255#将data2矩阵的每个数据都乘上255data3 = np.random.randint(0,255,(200,200),np.uint8)#生成一张200*200的随机矩阵 data4 = np.hstack((data1,data2,data3))#j将三个二维数组水平拼接在一起#img = np.random.randint(0,255,(200,200,3),np.uint8)#生成一张200*200*3的随机矩阵 cv2.imshow("combition",data4) cv2.waitKey() cv2.destroyAllWindows()#销毁所有窗口

结果:
OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

3、像素处理:加减乘除 数学逻辑:a+b<=255 (sum = a+b)
数学逻辑:a+b>255 (sum = (a+b)%255)
img = cv2.imread("./111.jpg")#读取图片111# 1 B = img.copy()#复制img的数据 B[:,:,0] = 255#让图像的0通道全部为255 # 2 R = img.copy() x,y,n = R.shape#获取R的行列和通道数 mask = np.zeros((x,y,n),np.uint8)#生成一个大小等于R的矩阵 mask[200:400,200:500,0] = 100#修改B 通道某个区域为255 R = mask+R #两个矩阵相加 #R = R-mask #R = R*2cv2.imshow("combition",R) cv2.waitKey() cv2.destroyAllWindows()#销毁所有窗口

运行:
OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

3、像素处理(按位逻辑操作)
cv提供的函数 实质 作用
cv2.bitwise_and(s1,s2[,mask]) & 按位与操作
cv2.bitwise_or(s1,s2[,mask]) | 按位或操作
cv2.bitwise_not(s1[,mask]) ~ 按位取反操作
cv2.bitwise_xot(s1,s2[,mask]) ^ 按位异或操作
如图是一个(3*3),unit8类型的矩阵的二进制表,在计算中,按位逻辑操作可以可以操作每一个比特位的值。这些操作包含:&、|、~、^
—— 0 1 2
0 00100101 11111111 01010100
1 11111111 11011100 11110000
2 11101111 00000000 11111110
import cv2 import numpy as npimg = cv2.imread("./111.jpg")#读取图片111# 1 B,G,R = cv2.split(img)#通道分离C = B[200:500,200:500] imgmask = np.ones((C.shape),np.uint8)#生成一个大小等于B的二维矩阵imgmask[:,:] = 0x15; #每个像素点 = 0001 0101 #进行按位逻辑运算 A = cv2.bitwise_and(C,imgmask) O = cv2.bitwise_or(C,imgmask) N = cv2.bitwise_not(C) X = cv2.bitwise_xor(C,imgmask)AONX1 = np.hstack((C,A,O))#水平拼接 AONX2 = np.hstack((C,N,X)) showimg = np.vstack((AONX1,AONX2))#垂直拼接cv2.imshow("showimg",showimg) cv2.waitKey() cv2.destroyAllWindows()#销毁所有窗口

OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

甚至,我们还可以逐位(1111 1111)单独提取组成八张新矩阵,既位平面分解
## 4、图像访问 numpy库向用户提供了一种矩阵的快速访问接口
import cv2 import numpy as npimg = cv2.imread('./111.jpg') number = img.item((200,200,1))#访问200行,200列,1通道的数据 img.itemset((200,200,1),50)#修改200行,200列,1通道的数据 number1 = img.item((200,200,1))#访问200行,200列,1通道的数据 print(number,"",number1)#打印修改前后的数据

(四)摄像头基础操作
import cv2video = cv2.VideoCapture(0)#0表示打开笔记本自带的摄像头open = video.isOpened()#判断摄像头是否被打开,发开返回True while(open): """由于摄像头不是静态的照片 所以需要以循环的方式一直读取 """ ret,frame = video.read()#读取摄像头当前帧的数据,每帧为一张图片 if frame is None:#判断是否有数据被读取 break cv2.imshow("video",frame)#显示读取到的数据 if cv2.waitKey(30) & 0xff == 27:#判断是否按下了ESC键 break cv2.destroyAllWindows()#销毁所有窗口

运行以上函数,我们成功打开了笔记本电脑的摄像头。对于读取到的frame数据而言,依然是一张BGT彩色图像的数据形式,我们依然可以使用前面写过的算法操作进行计算它的数据,唯一不同的是frame数据会随着时间的变化而自行变化。
【点击学习】:openCV专栏(二):基础计算实战+色彩空间转换
(五)结束语 以上就是今天所要分享的内容了
学习路漫漫,我们仍需负重前行……
为此博主新创建了一个群,期待你们的加入:
QQ群:928357277

OpeenCV(python)|openCV专栏(一)(基础操作)
文章图片

欢迎加入我们的大家庭:928357277

    推荐阅读