Opencv笔记
1—计算机眼中的图像
图像由像素(pixel)点构成,像素点是一个值,在0-255之间浮动,表示亮度
0黑的,255白的
RGB图像的颜色通道R:Red;G:Green;B:Blue
注意:opencv中使用的颜色通道顺序为BGR而不是RGB
黑白图又叫灰度图GRAYSCALE只有一个通道表示亮度
有下面三种类型的图像(彩色图像、灰度图像、黑白图像)
矩阵大小代表图像大小500*500 【500,500,3】3:表示在每个颜色通道上都有500*500
应当注意,图像中有多少像素并不表示其物理尺寸(一个像素不等于一毫米)。相反,像素的大小取决于为该图像设置的每英寸像素数 (Pixels Per Inch, PPI)。图像的 PPI 一般设置在 [200-400] 范围内。
计算PPI的基本公式如下:
PPI=宽度(像素) / 图像宽度(英寸)
PPI=高度(像素) / 图像高度(英寸)
如何访问各个像素
像素索引起始值为0,左上角为(0,0)而不是(1,1)
1-数据读取-图片
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('dabai.jpg')#相对路径
cv2.imshow('1',img)#打开图像一定要创建一个窗口
cv2.waitKey(0)#0表示任意键终止
或cv2.waitKey(1000)#毫秒级
cv2.destroyAllWindows( )
#显示图像的大小信息
h,w,c=img.shape#高,宽,通道数(注意:highth在前,width在后)
image_size=img.size#(高*宽*通道数)
image_dtype=img.dtype#图像的数据类型
print(h,w,c)#注意显示灰度图时会报错,应为因为通道数1个,不会显示
用opencv将图像转化为RGB格式(matplotlib格式)
opencv默认读取的是BGR格式而不是RGB格式
b,g,r=cv2.split(img) #分割颜色通道
b,g,r=cv2.split(img)
print(b)
print(b.shape)
img_matplotlib=cv2.merge([r,g,b])#转换颜色通道
·用matplotlib展示图像plt.subplot(m,n,p) m*n网格图中,m行数,n列数,p位置
plt.subplot(1,2,1)
plt.imshow(img)
plt.subplot(1,2,2)
plt.imshow(img_matplotlib)
plt.show()
·用opencv展示图像
cv2.imshow(‘bgr image’,img)
cv2.imshow(‘rgb image’,img_matplotlib)
cv2.waitKey(0)
cv2.destroyAllWindows()
·用numpy的concatenate()来拼接opencv中两个窗口的图像
img_concats=np.concatenate((img,img_matplotlib),axis=1)
cv2.imshow(‘brg image and rgb image’,img_contats)
cv2.waitKey(0)
cv2.destroyAllWindows()
用cv2.split()分割颜色通道比较耗时;所以建议用numpy索引来获取颜色通道
B=img[:,:,0]
G=img[:,:,1]
R=img[:,:,2]#0,1,2分别是b,g,r的索引
另一个需要注意的是,可以使用 NumPy 在一条语句中将图像从 BGR 转换为 RGB:
img_matplotlib = img_OpenCV[:, :, ::-1]
简化过程
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()#函数要放在函数调用的前面
彩色图转化为灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_img =cv2.imread(‘路径’,cv2.IMREAD_GRAYSCALE)
两种应该都可以
保存图像
cv2.imwrite(‘路径名’,img)
彩色图像访问操作Opencv中的像素
·访问像素
(b,g,r)=img[6,40]#访问(x=40,y=6)处的像素,存储信息
·opencv一次只能访问一个通道
b = img[6, 40, 0]
·更改像素值
img[6, 40] = (0, 0, 255)
·图像切片
top_left_corner = img[0:50, 0:50]#获取图像左上角
针对灰度图:
gray_img[6, 40] = 0
更改为黑色,强度为0
2-数据读取-视频
import cv2
vc=cv2.VideoCapture('1.mp4')
if vc.isOpened():#检查是否打开正确
open,frame=vc.read()#open是一个bool类型的值
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(10) & 0xFE ==27:#1会太快了
break
vc.release()
cv2.destroyAllWindows()
ROI区域你感兴趣的区域
import cv2
import matplotlib.pyplot as plt
import numpy as np
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread('dabai.jpg')
dabai=img[0:200,0:200]
cv_show('dabai',dabai)
·图像变成红色/绿色/蓝色
#只保留R
cur_img=img.copy()
cur_img[:,:,0]=0#B通道0
cur_img[:,:,1]=0#G通道设为0
cv_show('R',cur_img)
3-边界填充
格式:cv.copyMakeBorder(img,top, bottom, left, right ,borderType)
参数:
img: 需要填充的图像
top: 上边界填充像素
bottom: 下边界填充像素
left: 左边界填充像素
right: 右边界填充像素
borderType: 图像填充的方法
复制法:复制最边缘像素
# 读取图片
img = cv2.imread("picture2.jpg")
# 填充像素
top_size = 50
bottom_size = 50
left_size = 50
right_size = 50
# Replicate (复制法)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
cv2.imshow("replicate", replicate)
cv2.waitKey(0)
cv2.destroyAllWindows()
输出结果:
反射法:对图像边缘像素进行反射
reflect=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT)
输出结果:
反射法101:以边界为中心点,对图像边缘像素进行反射
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)
输出结果:
常量法:用常数值填充. 需要设置一个 value 值,代表填充的颜色.
constant=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_CONSTANT, value=0)#这边设置的黑色
输出结果:
用matplotlib展示图像
plt.imshow(data, cmap='viridis', interpolation='nearest')
plt.colorbar() # 显示颜色条
plt.title('Example Image') # 设置标题
plt.xlabel('X Axis') # 设置X轴标签
plt.ylabel('Y Axis') # 设置Y轴标签
plt.show()
这边可以用plt.subplot(2,3,x)来进行6张图的多图展示
4-数值计算
img=cv2.imread('2.png')
print(img)
img2=img+10
print(img2)#每个数值都加10
print((img+img2)[:5,:,0])
#numpy中的处理:如果越界255,如294,就进行294%256余38
cv2.add(img,img2)[:1,:,0]
#opencv中如果超出255,即以255显示
图像融合
img1=cv2.imread('2.png')
img2=cv2.imread('dabai.jpg')
print(img1.shape)
print(img2.shape)
img3=cv2.resize(img1,(526,673))#图像融合前一定要修改至尺寸相同cv2.resize(width,height)
res=cv2.addWeighted(img2,0.4,img3,0.6,0)#按比例融合cv2.Addweight(img1,权重,img2,权重,亮度)
plt.imshow(res)
plt.show()#用matplotlib来展示图像
print(img3.shape)
img4=cv2.resize(img1,(0,0),fx=3,fy=1)#x*3,y*1表示按比例放大缩小
风景图加大白(哈哈哈好玩)
5-腐蚀操作图像的前景对象(白色区域)的缩小和去除边缘
(是不是很好笑)
图二是腐蚀后的图像
import cv2
import numpy as np
img=cv2.imread('des2.jpg')
kernel=np.ones((5,5),np.uint8)#卷积核
erosion=cv2.erode(img,kernel,iterations=1)#iterations迭代次数
cv2.imshow('erosion',erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蚀操作中的卷积核是一个用于图像处理的矩阵,通常只包含0和1的值1。
在进行腐蚀操作时,卷积核会在原始图像上滑动,每次锚点位置的像素值取卷积核覆盖的最小值。如果卷积核全部被白色覆盖,则最小值为255,否则只要卷积核内有黑色,最小值就为0。因此,腐蚀操作会使图像中的白色区域减少。
卷积核的大小和形状可以根据需要进行选择,常用的有3x3、5x5等大小的矩形或椭圆形卷积核1。
不同核大小和迭代次数都会对腐蚀操作产生影响。
示例2:
img=cv2.imread('erosion.jpg')
kernel=np.ones((30,30),np.uint8)
erosion_1=cv2.erode(img,kernel,iterations=1)
erosion_2=cv2.erode(img,kernel,iterations=2)
erosion_3=cv2.erode(img,kernel,iterations=3)
res=np.hstack((erosion_1,erosion_2,erosion_3))#将这些数组沿水平方向堆叠起来
cv2.imwrite('res.jpg',res)
cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蚀后图像(迭代次数分别为1,2,3)
6-膨胀操作
img=cv2.imread('fix.jpg')
kernel=np.ones((30,30),np.uint8)
tln_dilate=cv2.dilate(img,kernel,iterations=1)
cv2.imwrite('tln_dilate.jpg',tln_dilate)
cv2.imshow('tln_dilate',tln_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()
和腐蚀几乎是一样的操作
7-开运算与闭运算
开运算(Opening):
开运算是指先腐蚀后膨胀。这种操作可以用来去除图像中的小物体、填充小空洞,并且保留大物体的结构。因此,开运算常用于平滑图像、去除噪声和分割连接的对象。
闭运算(Closing):
闭运算是指先膨胀后腐蚀。这种操作可以用来填充图像中的小空洞、连接相邻的物体,并且保留小物体的结构。因此,闭运算常用于填充物体内部的空洞、连接断开的物体以及平滑物体边缘。
kernel=np.numpy((5,5),np.uint8)
opening=cv2.morphlogyEx(img,cv2.MORPH_OPEN,kernel)
closing=cv2.morphlogyEX(img,cv2.MORPH_CLOSE,kernel)
8-梯度运算
形态学梯度是通过用图像的膨胀结果减去其腐蚀结果,得到的使用之前,确保你已经定义了适当的kernel内核
kernel=np.ones((7,7),np.uint8)
gradiant=cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel)
9-礼帽和黑帽
礼帽:原始输入-开运算
黑帽:闭运算-原始运算
tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)#光剩刺了
blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
#闭运算先膨胀再腐蚀,毛刺去不掉-原始输入可以得到原始轮廓