OpenCV入门(二)快速学会OpenCV1图像基本操作

news2024/9/30 19:43:01

OpenCV入门(一)快速学会OpenCV1图像基本操作

不讲大道理,直接上干货。操作起来。

众所周知,OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大。今天就从读取图片,显示图片,输出图片信息和简单的界面编程和大家一起进入OpenCV的世界。

图像基本操作

1、读取图片

函数imread用于读取图像文件或加载图像文件,声明如下:

cv2.imread()

cv2.imread (const String &filename, int flags=IMREAD_COLOR)

其中,参数filename表示要读取的图像文件名,flags表示读取模式,取值如下:

· cv.IMREAD_ANYDEPTH:其值是2,取这个标志的话,若载入的图像深度为16位或者32位,就返回对应深度的图像,否则转换为8位图像再返回。

· cv.IMREAD_COLOR:其值是1,取这个标志的话,图像转为彩色图像(BGR,3通道)。

· cv.IMREAD_GRAYSCALE:其值是0,取这个标志的话,始终将图像转换成灰度图,即返回灰度图像,1通道。

· cv. IMREAD_UNCHANGED,其值是-1,不加改变地载入原图。

如果从指定文件加载图像成功就返回一个存储着图片像素数据的矩阵。如果无法读取图像(缺少文件、权限不正确、格式不受支持或无效),那么函数将返回空。

imread的第一个参数一般是图像文件的绝对路径或相对路径。对于绝对路径,imread除了不支持单右斜线形式(),其他斜线形式都支持,比如双右斜线形式(\)、双左斜线形式(//)、单左斜线形式(/)等。

通常相对路径更加方便点,只要把图像文件放在工程目录下即可。

在这里插入图片描述

实例如下:

#导入cv模块
import cv2 as cv
#读取图像,支持 bmp、jpg、png、tiff 等常用格式
img = cv.imread("yd.jpg") #yd.jpg在工程目录下 
print(img)

输出结果:

[[[123 132 145]
  [124 133 146]
  [125 134 147]
  ...
  [238 243 242]
  [238 243 242]
  [238 243 242]]

 [[121 130 143]
  [120 129 142]
  [121 130 143]
  ...
  [238 243 242]
  [238 243 242]
  [238 243 242]]

 [[116 125 138]
  [115 124 137]
  [115 124 138]
  ...
  [238 243 242]
  [238 243 242]
  [238 243 242]]

 ...

 [[ 56  65  68]
  [ 55  64  67]
  [ 52  64  66]
  ...
  [ 12  12  12]
  [ 15  15  15]
  [ 18  18  18]]

 [[ 59  71  73]
  [ 59  71  73]
  [ 59  71  73]
  ...
  [ 12  12  12]
  [ 15  15  15]
  [ 19  19  19]]

 [[ 76  88  90]
  [ 77  89  91]
  [ 79  91  93]
  ...
  [ 14  14  14]
  [ 17  17  17]
  [ 22  22  22]]]

Process finished with exit code 0

在这里插入图片描述

2、显示图片

cv2.imshow可以帮助我们显示图片。

定义:

cv2.imshow(window_name, image)

显示实例:

import cv2 as cv 
import numpy as np #导入numpy模块 

#imgpath = "d:\\我的图片\\p1.jpg";
#imgpath = "d://test//p1.jpg";
#imgpath = "d:/test/p1.jpg"
#imgpath = "d:/test//test2\\test3//test4//p1.jpg";#-- 4 --以上三种混合法 
imgpath = "p1.jpg"; #-- 5 --相对路径法,放工程目录下
img = cv.imdecode(np.fromfile(imgpath,dtype=np.uint8),-1)
cv.imshow("img",img) #显示窗口
cv.waitKey(0) #等待按键
cv.destroyAllWindows() #释放窗口

我们对上面的六种路径进行了测试,其中任何一种都是支持的,都可以成功读取并显示图片,其中较常用的是相对路径,也就是第五种。放在和3.1.py同一路径下,既可以在PyCharm中直接运行来打开图片,也可以到命令行窗口下执行pthon 3.1.py来打开图片。

输出结果:

在这里插入图片描述

3、输出图片的信息

3.1输出图片形状:

# 输出图像形状
print(img.shape)

实例代码:

#导入cv模块
import cv2 as cv
#读取图像,支持 bmp、jpg、png、tiff 等常用格式
img = cv.imread("yd.jpg")  
print(img.shape)

输出结果:

(376, 597, 3)

3.2输出图片大小:

# 输出图像大小
print(img.size)

实例代码:

#导入cv模块
import cv2 as cv
#读取图像,支持 bmp、jpg、png、tiff 等常用格式
img = cv.imread("yd.jpg")  
print(img.size)

输出结果:

673416

3.3输出图片数据类型

# 输出数据类型
print(img.dtype)

实例代码:

#导入cv模块
import cv2 as cv
#读取图像,支持 bmp、jpg、png、tiff 等常用格式
img = cv.imread("yd.jpg")  
print(img.dtype)

输出结果:

uint8

看完这些实例是不是很简单呀!!!

4、OpenCV简单界面编程

4.1创建窗口
OpenCV也支持有限的界面编程,主要是针对窗口、控件和鼠标事件等,比如滑块。有了这些窗口和控件,可以更好地展现图像并调节图像的一些参数。

这些界面编程主要由High-level GUI(高层次图形用户界面)模块支持。在High-level GUI模块中,用于新建窗口的函数是nameWindow,同时可以指定窗口的类型。

该函数声明如下:

     namedWindow(winname[, flags]) 

其中,参数winname表示新建的窗口名称,自己随便取;flags表示窗口的标识(一般默认为cv2.WINDOW_AUTOSIZE,表示窗口大小自动适应图片大小,并且不可手动更改;
cv2.WINDOW_NORMAL表示用户可以改变这个窗口大小;cv.WINDOW_OPENGL窗口创建的时候会支持OpenGL)。

在High-level GUI模块中,用于显示窗口的函数是imshow,声明如下:

     imshow(winname, mat) 

其中,参数winname表示显示的窗口名,可以使用namedWindow函数创建窗口,如不创建,imshow函数将自动创建;image表示需要显示的图像。
根据图像的深度,imshow函数会自动对其显示灰度值进行缩放,规则如下:

(1)如果图像数据类型是8U(8位无符号),就直接显示。

(2)如果图像数据类型是16U(16位无符号)或32S(32位有符号整数),那么imshow函数内部会自动将每个像素值除以256并显示,即将原图像素值的范围由[0-255×256]映射到[0~255]。

(3)如果图像数据类型是32F(32位浮点数)或64F(64位浮点数),那么imshow函数内部会自动将每个像素值乘以255并显示,即将原图像素值的范围由[0-1]映射到[0~255](注意:原图像素值必须要归一化)。

需要注意的一点就是imshow之后必须有waitKey函数,否则显示窗口将一闪而过,不会驻留屏幕。

waitKey函数声明如下:

     waitKey([delay])

其中,参数delay表示一个延时值,单位为ms,默认为0,永久延时,一直等待,直到用户按键。如果在指定时间之前没有按下任何键,就返回-1;如果在指定时间之前按下任何键,就返回按键的对应值。

当delay≤0时,函数waitKey无限地等待一个键事件,当delay>0时,则等待delay毫秒。由于操作系统在切换线程之间有一个最短的时间间隔,因此该函数不会正好等待delay毫秒,而是等待比delay毫秒长一些,这取决于当时计算机上运行的其他操作。

如果在指定时间之前没有按下任何键,就返回按下键的代码或-1。注意,此函数是HighGUI模块中唯一可以获取和处理事件的方法,因此需要定期调用它以进行正常的事件处理,除非HighGUI是在负责事件处理的环境中使用的。

另外,只有在至少创建了一个HighGUI窗口并且该窗口处于活动状态时该函数才起作用。如果有几个HighGUI窗口,那么其中任何一个都可以是活动的。

实例应用:新建窗口并显示5秒后退出

import cv2 as cv 
import numpy as np #导入numpy模块 

img = cv.imread('p1.jpg')
cv.namedWindow("myimg", cv.WINDOW_AUTOSIZE); 
cv.imshow("myimg",img);#在“窗口1”这个窗口输出图片。
cv.waitKey(5000);#等待5秒,程序自动退出。改为0,不自动退出。

4.2单窗口显示多图片

在某些场景下,比如有多个摄像头视频图像,如果一个视频图像显示在一个窗口中,则会因为窗口过多而显得凌乱。此时就需要一个窗口能显示多个视频图像。

在OpenCV中,我们可以利用hstack函数来实现单窗口显示多幅图像。首先熟悉一下hstack函数。hstack函数就是把两个行相同的数组或者矩阵的列从左到右排列起来,也就是把列水平排列起来,声明如下:

     numpy.hstack(tup)

其中,tup是ndarrays数组序列。这里说的数组就是NumPy库的array,比如定义了一个3行5列的二维矩阵数组:

在这里插入图片描述
这里的行数是矩阵的高度,列数是矩阵的宽度。比如建立一个一维矩阵b,长度为b.shape:

     b =np.array([1,2,3,4])
     print(b.shape)

输出是(4,),4就是一维矩阵的长度,因为不存在二维,也就没有二维的长度,因此括号里的逗号后面是空的。

了解了hstack函数后,我们可以在一个窗口中显示多幅图片,原理是直接通过imread函数返回的二维矩阵数组传入hstack函数中。

import cv2 as cv 
import numpy as np #导入numpy模块 
  
def opecv_muti_pic():
    img1 = cv.imread('1.jpg')
    print(img1.shape)
    img2 = cv.imread('2.jpg')
    print(img2.shape)
    img3 = cv.imread('3.jpg')
    print(img3.shape)
    imgs = np.hstack([img1,img2,img3])
    # 展示多个
    cv.imshow("mutil_pic", imgs)
    #等待关闭
    cv.waitKey(0)
	 
opecv_muti_pic()

在上述代码中,首先读取了3幅图片,并各自返回了二维矩阵数组,这3幅图片在工程目录下可以找到,这里不对是否读取成功进行判断,但一线开发则不能少这个判断。

随后,把3幅图片的矩阵数组传入hstack函数中进行合并,并返回合并后的矩阵数组,然后通过imshow显示出来。

我们每次读取一幅图片,就把它的宽度和高度打印出来。可以发现,高度(行数)都是相同的,否则是不能用于hstack的。

例如,把图片3缩放后保存,再运行程序,就会报错。运行工程,结果如图所示。

在这里插入图片描述

4.3销毁窗口

既然有新建窗口,就会有销毁窗口。
在OpenCV中,销毁窗口时窗口也将自动关闭,可以通过函数destroyWindow和destroyAllWindows来实现,前者是销毁某一个指定名称的窗口,后者是销毁所有新建的窗口。函数destroyWindow声明如下:

     destroyWindow(winname)

参数winname是要销毁窗口的名称。destroyAllWindow函数更加简单,声明如下:

     destroyAllWindows() 

实例:销毁3个窗口:

import cv2 as cv 
import numpy as np  
  
szName = ["", "", ""]
srcImage=[1,2,3]
for i in range(0,2):
	szName[i] = ( "%d.jpg") % (i+1)
	srcImage[i] = cv.imread(szName[i]); 
	cv.imshow(szName[i], srcImage[i]); 
	cv.waitKey(5000); 
	cv.destroyWindow(szName[i]);
 
print("所有的窗口已经销毁了")
cv.waitKey(0);

4.4键盘事件

最简单、最常用的键盘事件是等待按键事件,它是由waitKey函数来实现的。无论是刚开始学习OpenCV,还是使用OpenCV进行开发调试,都可以看到waitKey函数的身影,然而最基础的往往容易忽略,在此可以好好了解一下这个基础又常用的waitKey函数。该函数延时一段时间,返回按键的值。当参数为0时就永久等待,直到用户按键。

函数声明如下:

     waitKey([delay]) 

其中,参数delay是延时的时间,单位是ms,默认是0,表示永久等待。该函数仅在至少创建了一个HighGUI窗口并且该窗口处于活动状态时才有效。如果有多个HighGUI窗口,则其中任何一个都可以处于活动状态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380873.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录自己遇到的关于Hashmap的面试题

一.麻烦讲述一下Hashmap的扩容原理 jdk1.8中的hashmap扩容原理 1.put流程图 首先贴一张图(图片来源于传送门),多谢大佬的美图,此图已经完美的描述了put的整个流程,我也就不想自己画了,嘿嘿: 2.hashmap中几个比较重…

hive临时目录清理

hive运行失败会导致临时目录无法自动清理,因此需要自己写脚本去进行清理 实际发现hive临时目录有两个: /tmp/hive/{user}/* /warehouse/tablespace//hive/**/.hive-staging_hive 分别由配置hive.exec.scratchdir和hive.exec.stagingdir决定: 要注意的…

requests---(4)发送post请求完成登录

前段时间写过一个通过cookies完成登录,今天我们写一篇通过post发送请求完成登录豆瓣网 模拟登录 1、首先找到豆瓣网的登录接口 打开豆瓣网站的登录接口,请求错误的账号密码,通过F12或者抓包工具找到登录接口 通过F12抓包获取到请求登录接口…

每日分享(微信社区小程序/h5/圈子论坛贴吧交友/博客/社交)

1.Java单元测试实战 高清PDF中文版 Java单元测试实战来自于作者多年来的单元测试实践,最初发表在阿里内网的ATA上,成为了很多阿里同学单元测试学习的必读文章。很多程序员认为单元测试会花费大量的时间,因此他们写单元测试的意愿比较低&…

【同步工具类:Semaphore】

同步工具类:Semaphore介绍源码分析构造函数acquire 获取信号量release 释放信号量业务场景代码测试结果总结介绍 官方说明: Semaphore用于限制可以访问某些资源(物理或逻辑的)的线程数目,他维护了一个许可证集合,有多少资源需要限…

vue2、vue3组件传值,引用类型,对象数组如何处理

vue2、vue3组件传值,引用类型,对象数组如何处理 Excerpt 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父… 下述组件传值指引…

【Go|第1期】Go遍历目录的三种方法

日期:2023年3月1日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方&#xff…

web,h5海康视频接入监控视频流记录一

项目需求,web端实现海康监控视频对接接入,需实现实时预览,云台功能,回放功能。 web端要播放视频,有三种方式,一种是装浏览器装插件,一种是装客户端exe,还有就是无插件了。浏览器装插…

垃圾回收的概念与算法(第四章)

《实战Java虚拟机:JVM故障诊断与性能优化 (第2版)》 第4章 垃圾回收的概念与算法 目标: 了解什么是垃圾回收学习几种常用的垃圾回收算法掌握可触及性的概念理解 Stop-The-World(STW) 4.1. 认识垃圾回收 - 内存管理清洁工 垃圾…

vue keep-alive多层级路由支持

keep-alive使用 属性值 1.include - 字符串或正则表达式。只有名称匹配的组件会被缓存。 2.exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。 3.max - 数字。最多可以缓存多少组件实例。 注:匹配首先检查组件自身的 name 选项,如果 nam…

用ab压测工具搞垮目标网站

一、介绍ab 命令会创建很多的并发访问线程,模拟多个访问者同时对某一 URL 地址进行访问。它的测试目标是基于 URL 的,因此,既可以用来测试 Apache 的负载压力,也可以测试 nginx、lighthttp、tomcat、IIS 等其它 Web 服务器的压力。…

数据结构与算法——6.Comparable接口

这篇文章我们一起来看一下java中的Comparable接口 目录 1.学数据结构与算法的小套路 2.Comparable接口介绍 3.小结 1.学数据结构与算法的小套路 我们知道java是面向对象的,并且底层为我们封装了许多的方法。在java的开发工具包jdk中,已经给我们提供…

XGBoost简单介绍

1. 概述 XGBoost本身的核心是基于梯度提升树实现的集成算法,整体来说可以有三个核心部分:集成算法本身,用于集成的弱评估器,以及应用中的其他过程。 1.1 提升集成算法: XGBoost的基础是梯度提升算法,因此…

kali linux安装换源切换系统语言

安装 去官网 https://www.kali.org/ 找到自己合适的虚拟机版本,我们不要下载那个torrent,那个还要重新下载一遍 换源 sudo vim /etc/apt/sources.list 按 i 进入vim的编辑模式 用 # 把用来的注释掉,一定要去掉 在后面补上国内的源&#x…

【论文/写作】计算机论文写作全攻略总结

如果觉得我的分享有一定帮助,欢迎关注我的微信公众号 “码农的科研笔记”,了解更多我的算法和代码学习总结记录。或者点击链接扫码关注【论文/写作】计算机论文写作全攻略总结 机器翻译学术论⽂写作⽅法和技巧 https://nlp.csai.tsinghua.edu.cn/~ly/tal…

一篇搞定ShardingSphere-jdbc 实战

谈到分库分表中间件时,我们自然而然的会想到 ShardingSphere-JDBC 。这篇文章,我们聊聊 ShardingSphere-JDBC 相关知识点,并实战演示一番。1 ShardingSphere 生态Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产…

操作系统权限提升(二十三)之Linux提权-通配符(ws)提权

系列文章 操作系统权限提升(十八)之Linux提权-内核提权 操作系统权限提升(十九)之Linux提权-SUID提权 操作系统权限提升(二十)之Linux提权-计划任务提权 操作系统权限提升(二十一)之Linux提权-环境变量劫持提权 操作系统权限提升(二十二)之Linux提权-SUDO滥用提权 利用通配符…

redis的集群方式

1.主从复制 主从复制原理: 从服务器连接主服务器,发送SYNC命令; 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令; 主服务器BGSAVE执行完后,向所有从服务…

阿里测试7年,薪资从7K到25K,我的成功值得每一个人借鉴

7年从业经验,这篇文章将汇集自动化测试所需知识,拒绝标题党,水文。让所有想学习提升技术的能从文中获取有价值的知识。 在这个吃技术的IT行业来说,我之前每天做的是最基础功能测试的工作,但是随着时间的消磨&#xff…

C++回顾(五)—— 构造函数和析构函数

5.1 构造和析构 5.1.1 构造函数 (1)定义 1)C中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数;2)构造函数在定义时可以有参数;3)没有任何返回类型的…