openCV第一篇

简介: openCV第一篇

前言:计算机眼中的图片

计算机中一个像素点的值在0-255表示该点亮度  0暗(黑)-255亮(白)

一张彩图通常是由RGB(red、green、blue)三个颜色通道所组成

一个500x500的图片那他们的 RGB 矩阵也各是500x500。

上图我们将一个大的图片分割成许多如20x20的小图片,同理每个小图片它们的RGB矩阵也各自是20x20。

注:opencv默认顺序不是RBG 而是 BGR。

1. 图片的读取与显示

1.1 图片的读取

1. import cv2 
2. img = cv2.imread('./data/abv.jpg')
  • img = cv2.imread('./data/abv.jpg')

比如我读入这样一张图片,命名为img

我们可以看到img是一个三维ndarray结构,内部数据类型dtype=unit8:

  • 三维:(1080,1920,3)表示高度、宽度、颜色通道个数(cv彩图BGR)
  • ndarray结构:数据类型dtype=unit8, 0-255。

1.2 显示的图片

1.2.1 显示原始图片

cv2.imshow('image',img) # 第一个参数表示窗口指定的名字 第二个为上方img
cv2.waitKey(5000) # 等待时间  如果是5000则在5s后图片窗口自动关闭  0表示任意键关闭
cv2.destroyAllWindows() # 时间一到关闭窗口

ps: 图像的显示也可以是多个窗口


cv2.imshow('image',img) 自己给将要弹出的窗口起个名  再加入变量img

cv2.waitKey(5000) 等待时间  如果是5000则在5s后图片窗口自动关闭  0表示任意键关闭

cv2.destroyAllWindows() 时间一到关闭窗口

为方便下面使用,我们自己定义一个函数cv_show():

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

执行代码,弹出窗口,显示图片:

cv_show('winName',img)

1.2.2 灰度图

在之前的基础之上加入参数:cv2.IMREAD_GRAYSCALE

img2=cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE)  # cv2.IMREAD_COLOR

mg2=cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE)  

  • cv2.IMREAD_GRAYSCALE  读取为灰度图,也可以写0。
  • cv2.IMREAD_COLOR           读取为彩图

我们执行:

cv_show('win2',img2)

可以看到该图片最终显示结果为二维(1080,1920) :

ps: img.size 输出像素点的个数,可以看到同一张图片BGR彩图是灰度图的三倍。

1.3 BGR转换成灰度图、RGB

当然我们也可以把已经读取进来的BGR彩图转换成灰度图,或者转换为RGB。

img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
cv_show('win3',img2)

img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

  • cv2.COLOR_BGR2RGB 将BGR格式转换成RGB
  • cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片

2. 保存图片

cv2.imwrite('./data/grayPhoto.jpg',img2)
  • cv2.imwrite('./data/grayPhoto.jpg',img2)

此时我的data文件夹下就多了一张刚刚处理好名为grayPhoto的灰度图。

3. 视频的读取与显示

视频也是由图像组成的,每一帧都可以当作是一个静止的图像,把图像连在一起看着就像是一个视频了。 我们打游戏时,也是追求一些更高的帧率。

vc = cv2.VideoCapture('./data/stu.mp4')
  • vc = cv2.VideoCapture('./data/stu.mp4')
1. # 检查是否正确打开
2. if vc.isOpened():
3. open,frame = vc.read()
4. else:
5. open = Flase

vc.read()

  • 读取视频中的第一帧 ,再次执行vc.read()的话读取视频第二帧
  • 返回值中:第一个:布尔类型,能读进来就是True   第二个像是上面的img,这一帧图片的ndarray矩阵

循环图片播放视频:

while open:
    ret,frame = vc.read()
    if frame is None:
        break
    if ret == True:
        # 原本frame是(h,w,3)的BGR图片矩阵 经下方加入参数转换成黑白gray
        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 
        cv2.imshow('result',gray)
        # cv2.waitKey(num) 该图片显示时间/速度 自己可以找一个合适的值
        # 27指退出键ESC 退出窗口  当然也可以是 =='q'等
        if cv2.waitKey(20)&0xFF == 27: 
            break
vc.release()
cv2.destroyAllWindows()

注:视频放完 ret, frame = vc.read()返回False和None 再次进行循环无法播放视频,需要重新读取。

  • if cv2.waitKey(20)&0xFF == 27:
  • 不是新知识点了,表示每张图片等20毫秒,如果按ESC键直接退出。

4. 截取图像部分

我们上面介绍,img是一个ndarray矩阵,因此对其进行切片操作:

1. pho = img[100:800,200:800]  # 进行切片 高100到800 宽200到800
2. cv_show('win2',pho)
  • pho = img[100:800,200:800]

5. 颜色通道提取

1. b,g,r = cv2.split(img)
2. # b.shape g.shape r.shape 都为 (1080, 1920)

执行

cv_show('win3',g) # 或者填 b、r

结果就是单通道图。

如果我们想显示单一颜色,如红色:

cur_img = img.copy()
cur_img[:,:,0] = 0 # B不要了 设置为0
cur_img[:,:,1] = 0 # G不要了 设置为0
#cur_img[:,:,2] = 0 # R不要了 设置为0
cv_show('winR',cur_img)

6. 边界填充

这个一般用于卷积,在图像周围填充一些像素。

我们以这个图片为例:

1. img = cv2.imread('./data/gd01.jpg')
2. # img.shape 为 (300, 400, 3)
3. cv_show('win1',img)

在图片的上下左右填充50个像素,介绍5种方法:

top_size,bottom_size,left_size,right_size=(50,50,50,50)
# 不同的填充方法 最后参数改个type值就行
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)
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')
# 注matplotlib默认R G B本例只介绍边界填充
plt.show()

cv2.BORDER_REPLICATE

复制最边缘的像素

cv2.BORDER_REFLECT

反射法对感兴趣的图像中的像素在两边进行复制 如fedcba|abcdefgh|hgfedcb 其中abcdefgh是图像"|"外的是填充内容

cv2.BORDER_REFLECT_101

反射法,也就是以最边缘的像素为轴,对称,gfedcb|abcdefgh|gfedcba 上面是ba|ab 这个是bab。

cv2.BORDER_WRAP

外包装法 如:cdefgh|abcdefgh|abcdefg。

cv2.BORDER_CONSTANT

常量法,常数值value填充。

7. 数值计算

由于是uint8类型最大255 超过相当于结果为 num%256了

我们使用以下方法保留最大值:

cv2.add(img,img2)
  • cv2.add(img,img2)

8. 图像融合

效果如下:

我们导入宽高相同的2张图片:

img = cv2.imread('./data/gd04.jpg')
img2 = cv2.imread('./data/gd05.jpg')
img3 = cv2.imread('./data/gd06.jpg')
print(img.shape,img2.shape,img3.shape) # (281, 600, 3) (281, 600, 3) (337, 600, 3)

如果大小不同 需要手动设置成一样的

img3 = cv2.resize(img3,(600,281))
# img3.shape (281, 600, 3)
  • img3 = cv2.resize(img3,(600,281))

ps: cv2.resize()另一种操作

img4 = cv2.resize(img3,(0,0),fx=2,fy=1)

我们执行:

res = cv2.addWeighted(img,0.6,img2,0.4,0)
plt.imshow(res)
  • res = cv2.addWeighted(img,0.6,img2,0.4,0)

R = ax1 + bx2 + c  a、b为权重 c为偏置 这里意为在原亮度上变化多少

9. 知识点总结*

  • 读取图片:
import cv2 
img = cv2.imread('./data/abv.jpg')
img2 = cv2.imread('./data/abv.jpg',cv2.IMREAD_GRAYSCALE) 
img3 = cv2.imread('./data/abv.jpg',cv2.IMREAD_COLOR) 
  • 显示图片:
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  • BGR转换成灰度图、RGB:
img2 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
img3 = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) 
  • 保存图片:
cv2.imwrite('./data/grayPhoto.jpg',img2)
  • 视频的读取与显示:
vc = cv2.VideoCapture('./data/stu.mp4')
# 检查是否正确打开
if vc.isOpened():
    open,frame = vc.read()
else:
    open = Flase
while open:
    ret,frame = vc.read()
    if frame is None:
        break
    if ret == True:
        # 原本frame是(h,w,3)的BGR图片矩阵 经下方加入参数转换成黑白gray
        gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 
        cv2.imshow('result',gray)
        # cv2.waitKey(num) 该图片显示时间/速度 自己可以找一个合适的值
        # 27指退出键ESC 退出窗口  当然也可以是 =='q'等
        if cv2.waitKey(20)&0xFF == 27: 
            break
vc.release()
cv2.destroyAllWindows()
  • 截取图片部分:
pho = img[100:800,200:800]  # 进行切片 高100到800 宽200到800
  • 颜色通道提取:
b,g,r = cv2.split(img)
cur_img = img.copy()
cur_img[:,:,0] = 0 # B不要了 设置为0
cur_img[:,:,1] = 0 # G不要了 设置为0
#cur_img[:,:,2] = 0 # R不要了 设置为0
cv_show('winR',cur_img)
  • 边界填充:
top_size,bottom_size,left_size,right_size=(50,50,50,50)
# 不同的填充方法 最后参数改个type值就行
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)
  • 数值计算:
cv2.add(img,img2)
  • 图像融合:
img3 = cv2.resize(img3,(600,281))
res = cv2.addWeighted(img,0.6,img2,0.4,0)
相关文章
|
机器学习/深度学习 存储 编解码
Tiny Time Mixers (TTM)轻量级时间序列基础模型:无需注意力机制,并且在零样本预测方面表现出色
IBM研究人员提出Tiny Time Mixers (TTM),这是一个轻量级、基于mlp的TS模型,参数量小于1M,在M4数据集上表现优于大型SOTA模型,且具备优秀的零样本预测能力。TTM无注意力机制,利用TSMixer进行多级建模,自适应补丁和频率前缀调整等创新特性提升性能。预训练和微调阶段各有独特设计,预训练仅用单变量序列,微调时学习多变量依赖。TTM在某些任务中证明了小模型的优越性,且模型已开源。
762 1
|
分布式计算 DataWorks Oracle
MaxCompute产品使用合集之如何创建表
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
307 7
|
SQL 存储 分布式计算
Kylin使用心得:从入门到进阶的探索之旅
【5月更文挑战第2天】Apache Kylin是开源大数据分析平台,提供亚秒级OLAP查询。本文深入解析Kylin的工作原理,包括预计算模型Cube、构建过程和查询引擎。常见问题涉及Cube设计、查询性能和资源管理,解决方案涵盖合理设计、性能监控和测试验证。文中还分享了Cube创建的JSON示例,并探讨了Cube构建优化、查询优化、与其他组件集成、监控维护及生产环境问题解决。通过学习和实践,读者能有效提升数据洞察力和决策效率。
724 5
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
886 0
|
小程序 前端开发 JavaScript
WXML模板语法-条件渲染和列表渲染
本文档介绍了微信小程序中的条件渲染和列表渲染。条件渲染主要使用`wx:if`、`wx:elif`、`wx:else`和`hidden`属性。`wx:if`通过判断表达式决定是否渲染代码块,而`hidden`通过切换CSS的`display`属性控制元素隐藏。两者在性能和使用场景上有区别,频繁切换推荐使用`hidden`,复杂条件推荐使用`wx:if`。列表渲染则利用`wx:for`遍历数组生成列表,可以通过`wx:for-index`和`wx:for-item`自定义索引和项的变量名,同时需使用`wx:key`为列表项指定唯一标识以优化渲染效率。
187 0
|
算法 C# C语言
取高八位与低八位,高八位与低八位合并
取高八位与低八位,高八位与低八位合并
898 0
取高八位与低八位,高八位与低八位合并
|
Linux 开发工具 虚拟化
Centos7超详细安装教程
Centos7超详细安装教程
6934 1
|
负载均衡 前端开发 JavaScript
谷粒学院(八)阿里云oss | 头像上传 | Nginx(二)
谷粒学院(八)阿里云oss | 头像上传 | Nginx
谷粒学院(八)阿里云oss | 头像上传 | Nginx(二)
|
SQL Ubuntu Oracle
Ubuntu安装MySQL 8.0 - APT(结尾附视频)
Ubuntu安装MySQL 8.0 - APT(结尾附视频)
544 0
|
机器学习/深度学习 传感器 算法
【滤波】基于最近邻算法实现多目标航迹关联附matlab代码
【滤波】基于最近邻算法实现多目标航迹关联附matlab代码