【计算机视觉】OpenCV 4高级编程与项目实战(Python版)【1】:图像处理基础

news2024/11/15 9:18:57

目录

1. OpenCV简介

2. OpenCV开发环境搭建 

3. 读取图像

4. 读取png文件出现警告

5. 显示图像

6. 保存图像

7. 获取图像属性


        本系列文章会深入讲解OpenCV 4(Python版)的核心技术,并提供了大量的实战案例。这是本系列文章的第一篇,主要讲解OpenCV处理图像的基本方法,主要包括读取图像、显示图像、保存图像和获取图像的属性。

1. OpenCV简介

        OpenCV是目前最流行的计算机视觉处理库之一,受到了计算机视觉领域众多研究人员的喜爱。计算机视觉是一门研究如何让机器“看”的科学,即用计算机来模拟人的视觉机理,用摄像头代替人眼对目标进行识别、跟踪和测量等,通过处理视觉信息获得更深层次的信息。例如,通过拍摄环绕建筑物一周的视频,利用三维重建技术重建建筑物三维模型;通过放置在车辆上方的摄像头拍摄前方场景,推断车辆能否顺利通过前方区域等决策信息。对于人类来说,通过视觉获取环境信息是一件非常容易的事情,因此有人会误认为实现计算机视觉是一件非常容易的事情。但事实不是这样的,因为计算机视觉是一个逆问题,通过观测到的信息恢复被观测物体或环境的信息,在这个过程中会缺失部分信息,造成信息不足,增加问题的复杂性。例如,当通过单个摄像头拍摄场景时,因为失去了距离信息,所以常会出现图像中“人比楼房高”的现象。因此,计算机视觉领域的研究还有很长的路要走。

        无论是图像处理还是计算机视觉,都需要在计算机中处理数据,因此研究人员不得不面对一个非常棘手的问题:将自己的研究成果通过代码输入计算机,进行仿真验证。而在这个过程中会重复编写基本的程序,这相当于为了制造一辆汽车,需要重新发明轮子。为了给所有研究人员提供“车轮”,英特尔(Intel)提出了开源计算机视觉库(Open Source Computer Vision Library,OpenCV)的概念,通过在计算机视觉库中包含图像处理与计算机视觉的通用算法,避免重复无用的工作。因此,OpenCV应运而生。OpenCV由一系列C语言函数和C++类构成,除支持使用C/C+语言进行开发之外,它还支持很多其他编程语言,如Java、Python、C#、Ruby等。OpenCV可以在Linux、Windows、macOS、Android、iOS等系统上运行。OpenCV的出现极大地方便了计算机视觉研究人员的算法验证,得到了众多研究者的喜爱。经过20多年的发展,OpenCV已经成为计算机视觉领域最重要的研究工具之一。图1是OpenCV的Logo。

图1

2. OpenCV开发环境搭建 

本节会介绍如何搭建OpenCV-Python的开发环境。

OpenCV-Python目前最新版本是4.5.5.62。安装OpenCV-Python可以直接使用下面的命令安装:

pip install opencv-python

或者直接到下面的页面下载whl文件安装OpenCV-Python:

https://pypi.org/project/opencv-python/#files

下载页面如图2所示。

        在该页面包含了多个操作系统的OpenCV-Python版本,读者应该根据当前使用的操作系统下载相应的OpenCV-Python版本,假设读者使用的是Windows10,需要下载opencv_python-4.5.5.62-cp36-abi3-win_amd64.whl文件,然后使用下面的命令安装whl文件。

pip install opencv_python-4.5.5.62-cp36-abi3-win_amd64.whl

        安装完OpenCV-Python后,进入Python的REPL环境,执行import cv2,如果没有报错,说明OpenCV-Python已经安装成功,如图3所示。

图3

3. 读取图像

OpenCV提供了用于读取图像的imread函数,该函数的原型如下:

cv.imread( filename[,flags])->retval

参数说明:

  • filename:待读取图像的文件名(绝对路径或相对路径)。
  • flags:读取文件的类型,默认值是1,表示读取的是彩色图像(RGB格式),如果为0,表示灰度类型的图像。其中彩色图像也可以用cv2.IMREAD_COLOR表示,灰度图像可以用cv2.IMREAD_GRAYSCALE表示。
  • retval:imread函数的返回值,一个由数字组成的矩阵,用于表示图像中的数据(颜色值),如果图像不存在或不可读,imread函数返回None。

注意:imread函数通过文件内容确定文件格式,而不是通过文件扩展名确定文件格式。例如,如果将png格式的图像文件book.png改名为book.jpg,imread函数仍然会按png格式读取book.jpg文件。

下面的例子使用imread函数读取了当前目录中的book.png文件,并输出返回结果。

import cv2
# 读取book.png文件
image = cv2.imread("images/book.png")
// 也可以使用下面的代码读取book.png文件
// image = cv2.imread("images/book.png", cv2.IMREAD_COLOR)
print(image) # 打印book.png中的数据(颜色值)

执行这段代码,会输出如图4所示的内容。

由于图像文件数据过大,所以只是输出了一部分数据,其余部分用省略号代替。

4. 读取png文件出现警告

在执行上一节代码时,尽管可以正常输出图像的数据,但还会输出如下的警告:

libpng warning: iCCP: known incorrect sRGB profile

         一般情况下,忽略这个警告并不影响OpenCV的正常工作,不过对于有强迫症的同学就太碍眼了,所以在这一节会将这个警告去掉。 

       出现这个警告的原因是从libpng 1.6开始在检查ICC配置文件方面更为严格,所以可以删除png图像的iCCP块。下面先解释一下什么是ICC配置文件和iCCP块。

  • ICC配置文件:ICC是International Color Consortium(国际色彩联盟)的缩写。ICC配置文件是描述如何正确地将图像文件从一个颜色空间转换到另一个颜色空间的文件。ICC 配置文件有助于为图像获取正确的颜色。通过ICC配置文件,无论单个设备的色彩特性如何,都可以通过标准化的色彩空间正确显示色彩。
  • iCCP块:嵌入式ICC配置文件。在PLTE和IDAT之前。如果存在iCCP块,则不应该存在sRGB块。另外,PNG数据流最多应包含一个嵌入式配置文件。如果违反这些原则,在检测iCCP块时就可能会输出前面提到的警告。

        去除这个警告的方法也很简单,就是去除iCCP块即可,如果使用macOS、Linux或Unix非常简单,在终端直接使用convert命令即可:

convert book.png book1.png

        执行这行命令,可以去除book.png文件中的iCCP块,并生成新的book1.png文件,再使用上一节的代码读取book1.png文件,就不会输出这个警告了。

        如果使用的是Windows,可以通过第三方图像编辑工具去除iCCP块,如跨平台的ImageMagick(https://imagemagick.org),安装完ImageMagick后,在终端执行下面的命令即可:

magick convert book.png book1.png

5. 显示图像

        将图像以矩阵形式输出是给分析程序用的,如果要想给人展示图像,就应该将图像显示出来,而不是输出密密麻麻的数字。为此,OpenCV提供了imshow函数用来显示图像。imshow函数会弹出一个窗口,并在窗口中显示图像。

        如果只使用imshow函数显示窗口,那么这个窗口闪一下就退出了,所以还需要使用waitKey函数让阻止窗口提出。waitKey函数的作用是等待任意一个按键按下,如果有按键按下,waitKey函数就会执行完毕,继续执行下面的代码,否则waitKey函数将一直处于等待状态。

        尽管Python程序执行完后会释放所有资源,但一个好的习惯是在程序执行完后,主动释放资源,如果使用imshow函数打开一个窗口,那么这个窗口就是资源,所以在程序执行完毕后,需要使用destroyAllWindows方法释放通过imShow函数创建的窗口,当然,如果还有其他窗口,也会一起释放。

下面看一下这几个函数的原型:

(1) imshow函数

cv.imshow( winname, mat)-> None

参数说明:

  • winname:显示图像的窗口名称。
  • mat:要显示的图像的矩阵数据,也就是imread函数返回的值。

imshow函数的返回值是None。

(2) waitKey函数

cv.waitKey([delay])-> retval

参数说明:

  • delay:可选参数,表示用户等待按下键盘上按键的时间,单位是毫秒(ms)。如果超过了这个时间,用户仍然未按下键盘上的任何键,那么waitKey函数将自动结束。如果不指定delay参数,默认值是0,表示无限等待,也就是说,只要用户不按下键盘上的键,waitKey函数将一直处于阻塞状态。
  • retval:waitKey函数的返回值。如果用户按下键盘上的按键,那么waitKey函数返回按键对应的ASCII码,例如,用户按下了a键,那么waitKey函数的返回值是97。如果在等待delay毫秒后,用户仍然未按下任何按键,那么waitKey函数自动结束运行,并返回-1。

(3) destroyAllWindows函数

cv.destroyAllWindows()-> None

        destroyAllWindows函数没有参数,返回值是None。该函数用于销毁所有正在显示图像的窗口。

        下面的代码使用imread函数读取了当前目录中的book.png文件,并通过imshow函数显示book.png,最后通过waitKey函数输出用户按键的ASCII值。

import cv2
image = cv2.imread("images/book.png")  	# 读取book.png文件
cv2.imshow("book", image)  				# 在名为book的窗口中显示book.png
print(cv2.waitKey()) 		 			# 窗口将一直显示图像,按任意键关闭窗口,并输出按键值
cv2.destroyAllWindows()  				# 销毁所有窗口

执行这段代码,会弹出如图5所示的窗口。

阅读这段代码应注意如下几点:

(1) 显示图像的窗口名称不能是中文,例如,将“book”改成“我写的书”,再运行程序,窗口左上角的标题就会呈现乱码,如图6所示。

(2) imshow函数的作用只是显示窗口,但如果整个Python程序都退出了,那么imshow函数显示的窗口也会自动关闭,所以要在imshow函数后面使用waitKey函数阻止Python程序退出。

        如果想将彩色图像变成灰度图像,只需要将imread函数的第2个参数指定为cv2.IMREAD_GRAYSCALE或0即可,代码如下:

image = cv2.imread("images/book.png",cv2.IMREAD_GRAYSCALE)

重新执行程序,会看到如图7所示的效果。

如果想让窗口在等待10秒后自动关闭,可以通过waitKey函数指定等待时间,代码如下:

cv2.waitKey(10000)    

6. 保存图像

        OpenCV提供了用于保存图像的imwrite函数,该函数可以将一个图像保存为另外一个图像文件,imwrite函数的原型如下:

imwrite(filename, img[, params]) -> retval

参数说明:

  • filename:保存图像时使用的绝对或相对路径,如file.jpg、d:\pic\test.png等。
  • img:待保存图像的数据,也就是imread函数返回的图像矩阵。
  • params:可选参数,图像的特殊格式,需要成对的数据。params参数是一个列表,列表元素个数需要是偶数。列表索引为偶数的元素(从0开始)表示格式ID,列表索引为奇数的元素表示格式值。这些格式ID都在cv2中定义,所有以cv2.IMWRITE开头的都是格式ID,例如,cv2.IMWRITE_JPEG_QUALITY表示jpeg格式图像的质量,值从0到100,默认是95。

        下面的代码将images目录中的book.png文件以新文件名new_book.png再重新保存到images目录,然后分别以10、30、50、80、100五个质量等级将book.png转为jpg格式的图像,并以不同文件名保存着5个jpg图像。

import cv2

image = cv2.imread("images/book.png") 				# 读取book.png
cv2.imwrite("images/new_book.png", image)			# 保存为new_book.png
params = []										# 定义参数列表
params.append(cv2.IMWRITE_JPEG_QUALITY)				# 指定参数
params.append(10)									# 指定参数(jpg图像质量为10)
cv2.imwrite("images/new_book1.jpg", image,params)		# 以质量为10保存为jpg图像
params[1] = 30										# 修改参数(jpg图像质量为30)
cv2.imwrite("images/new_book2.jpg", image,params) 	# 以质量为30保存为jpg图像
params[1] = 50										# 修改参数(jpg图像质量为50)
cv2.imwrite("images/new_book3.jpg", image,params)		# 以质量为50保存为jpg图像
params[1] = 80										# 修改参数(jpg图像质量为80)
cv2.imwrite("images/new_book4.jpg", image,params) 	# 以质量为80保存为jpg图像
params[1] = 100									# 以质量为100保存为jpg图像
cv2.imwrite("images/new_book5.jpg", image,params)		# 以质量为100保存为jpg图像

        执行这段程序,会在当前目录生成6个图像文件,其中有5个jpg文件,这5个jpg文件的尺寸是不断增大的,本例的尺寸分别是23KB、38KB、49KB、73KB和202KB,这说明质量越高,图像尺寸越大。

阅读这段代码应注意如下几点:

(1)  尽管imwrite函数的效果与复制文件类似,但并不是文件复制,就算原图像文件与目标图像文件都是同一个格式,但根据复制时使用的参数不同,这两个文件的尺寸也可能不同,而且原图像文件中的隐藏信息(非图像数据)也有可能丢失。

(2) imwrite函数可以进行图像格式转换,转换后的图像格式由图像文件的扩展名绝对。例如,本例文件名使用了new_book1.jpg,那么就会将book.png图像文件转换为jpg格式的图像文件。

(3) 如果图像矩阵包含多个图像,那么可以使用imwrite函数将图像保存为TIFF格式的图像文件。

7. 获取图像属性

        在处理图像的过程中,经常需要使用图像的各种属性,例如,图像的尺寸、类型等。为此,OpenCV提供了shape、size和dtype这3个常用属性,这3个常用属性代表的含义如下:

  • shape:元组类型的值。如果是彩色图像,元组中有3个值,分别表示像素行数,像素列数和通道数。如果是灰度图像,元组中有2个值,分别表示像素行数和像素列数。我们通常所说的图像分辨率就是“像素列数×像素行数”,如1920×1080。所以通过shape属性可以得到图像的分辨率。
  • size:图像包含的像素个数,其值是shape元组中3个值的乘积,也就是“像素行数×像素列数×通道数”,灰度图像的通道数为1。
  • dtype:图像数据使用的位数。灰度图像通常是8位单通道图像(通道数为1),大多数彩色图像是8位3通道图像(通道数为3),也就是我们常说的RGB格式的图像。这里的8位是指二进制的位数,也就是说,8位图像就是用1个字节表示最基本的像素数据。当然,还有16位、32位图像,这样的图像尺寸更大,展现的效果会更好。

        下面的代码通过imread函数读取当前目录中的book.png文件,然后从imread函数返回值获取彩色图像和对应的会读的图像的不同属性。

import cv2

image_Color = cv2.imread("images/book.png")    # 读取book.png
print("获取彩色图像的属性:")
print("shape =", image_Color.shape)     # 获取彩色图像的像素行数、像素列数和通道数
print("size =", image_Color.size)       # 获取彩色图像包含的像素个数
print("dtype =", image_Color.dtype)     # 获取彩色图像的数据位数
# 读取与book.png(彩色图像)对应的灰度图像
image_Gray = cv2.imread("images/book.png", cv2.IMREAD_GRAYSCALE)
print("获取灰度图像的属性:")
print("shape =", image_Gray.shape)      # 获取灰度图像的像素行数和像素列数
print("size =", image_Gray.size)        # 获取灰度图像包含的像素个数
print("dtype =", image_Gray.dtype)      # 获取灰度图像包含的数据位数

 运行这段程序,会输出如图8所示。

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

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

相关文章

简单了解计算机的工作原理

文章目录一.计算机操作系统二.进程/任务三、进程控制块抽象(PCB)四、进程调度相关属性五、内存管理一.计算机操作系统 概念:操作系统是一组做计算机资源管理的软件的统称. 目前常见的操作系统有:Windows系列、Unix系列、Linux系列、OSX系列、Android系列、iOS系列…

百度安全在线查询,网站弹出风险提示怎么处理

站长们要避免网站打开弹出风险提示,需要要时刻关注自己的网站是否存在风险,时刻知道自己的网站是不是安全的。 百度安全在线查询步骤: 1、打开站长工具 2、添加需要查询的网站域名。 3、勾选百度安全。 4、点击开始查询。 等…

22个Python的万用公式分享

在大家的日常python程序的编写过程中,都会有自己解决某个问题的解决办法,或者是在程序的调试过程中,用来帮助调试的程序公式。小编通过几十万行代码的总结处理,总结出了22个python万用公式,可以帮助大家解决在日常的py…

再学C语言22:循环控制语句——循环嵌套和数组处理

嵌套循环&#xff08;nested loop&#xff09;&#xff1a;在一个循环内使用另一个循环 一、循环嵌套 示例代码&#xff1a; #include <stdio.h> int main(void) {int i;int j;for(i 0; i < 10; i){for(j 0; j < 9; j){printf("%5d", j); // 里面的…

共享模型之管程(二)

1.Moniter对象 1.1.Java对象头 1>.以32位虚拟机为例 ①.普通对象 Klass Word表示对象的类型,它是一个指针,指向了对象所从属的class; ②.数组对象 在32位虚拟机中,integer包装类型的长度为12个字节,而int基本数据类型的长度为4个字节; 其中Mark Word结构为: 2>.64位…

shell第一天练习

题目&#xff1a; 1、在当前主机编写脚本文件history_max.sh显示主机中执行频率最高的前5个命令。 2、判断主机是否存在rhel用户&#xff0c;如果存在则设置密码为redhat,如果不存在则创建用户并设置密码。 3、通过设置变量HISTTIMEFORMAT&#xff0c;使得当执行history命令时…

16. BootStrap

文章目录一、Bootstrap1、概念2、快速入门二、响应式布局三、CSS样式和JS插件1、全局CSS样式2、组件1. 导航条2. 分页条3、插件1. 轮播图四、案例1、案例描述2、案例分析3、实现一、Bootstrap 1、概念 * 概念&#xff1a; 一个前端开发的框架&#xff0c;Bootstrap&#xff0…

Linux网络配置(如何设置静态IP?如何设置查看主机名?)

文章目录Linux网络配置一、网络地址配置1.1. 查看网络地址1.2. 测试两个地址是否连接1.3. Linux系统的网络配置二、主机名以及hosts映射2.1. 查看和设置主机名2.2. hosts映射2.3. DNSLinux网络配置 一、网络地址配置 如果在一台Windows电脑上安装了Linux虚拟机&#xff0c;那…

颤抖开篇,从php角度谈谈IO模型(BIO)

颤抖开篇&#xff0c;从php角度谈谈IO模型&#xff08;BIO&#xff09; IO 是什么? 在计算机系统中I/O就是输入&#xff08;input&#xff09;和输出&#xff08;Output&#xff09;的意思。针对不同的操作对象&#xff0c;可以划分为磁盘I/O模型&#xff0c;网络I/O模型&am…

开发神器VSCode配置C/C++编译环境

hi&#xff0c;小伙伴们大家好&#xff0c;今天给大家介绍一款程序员常用的开发神器VSCode&#xff0c;想必大家肯定有所了解&#xff0c;也有很多小伙伴在日常工作中经常使用。当木荣君初次见到VSCode时&#xff0c;真正的被它惊艳到了&#xff0c;可以说是一见钟情。从此就爱…

13.6-14.8读书笔记

13.6 对象移动 13.6.1 右值引用 概念: 为了支持移动操作,新标准引入了的一种新的引用类型.所谓右值引用就是必须绑定到右值的引用. 通过&&来获得右值引用 int i 42;int &r i;int &&rr i; // 错误,不能将一个右值引用绑定到一个左值上int &r3 …

【python基础_05】面向对象

文章目录1. 类和对象1.1 使用对象组织数据的模版1.2 成员变量和成员方法1.3 实现代码2. 内置方法&#xff08;魔术方法&#xff09;2.1 构造方法&#xff1a;__init__&#xff08;&#xff09;1. 类和对象 1.1 使用对象组织数据的模版 1.2 成员变量和成员方法 1.3 实现代码 1…

jupyter notebook无法启动内核

jupyter notebook无法启动内核问题概述方法一使用Window PowerShell方法二更改文件路径重新启动内核参考问题概述 遇到的问题是在使用jupyter的时候无法正常运行,所以在这里尝试一些办法,在这里进行记录,希望能够帮助到大家 方法一 使用Window PowerShell 首先第一个方法就…

Java IO流 - 释放资源的方式

资源释放的方式 书接上文, 在上一篇文章我们做过一个文件拷贝的练习, 但是在联系中是有释放资源隐患的的, 例如在下面代码中, 在文件释放之前有许多行的逻辑代码; 如果这许多行的逻辑代码有报错, 导致程序不运行, 那么资源就得不到释放 public static void main(String[] args)…

Crack:ActiveReportsJS 3.2.2 EN:ActiveReportsJS

ActiveReportsJS - 高级 JavaScript 报告解决方案 ActiveReportsJS 是一种用于在前端应用程序中可视化数据的报告解决方案。Ω578867473自定义报告布局并将我们的报告设计器和查看器组件集成到 Web 应用程序中&#xff0c;以便在任何平台上预览、导出或打印报告。 使用我们的跨…

WPF+ASP.NET SignalR实现动态折线图

在实际业务中&#xff0c;当后台数据发生变化&#xff0c;客户端能够实时的收到通知&#xff0c;而不是由用户主动的进行页面刷新才能查看&#xff0c;这将是一个非常人性化的设计。有没有那么一种场景&#xff0c;后台数据明明已经发生变化了&#xff0c;前台却因为没有及时刷…

ElementUI——案例2用户管理(基于SpringBoot实现增删改)

1.ElementUI整合SpringBoot前后端分离实现用户增删改查 效果展示 2.前端核心代码 项目目录 main.js引入 import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import router from ./router import axios from axiosVue.prototype.$http ax…

SQL 存储过程

文章目录存储过程简介存储过程的创建及调用存储过程的删除 如何删除存储过程存储过程的优缺点现需要向学生表中插入新的学生数据。但在插入学生数据的时&#xff0c;需要同 时检查老师表里的数据。如果插入学生的老师不在老师表里&#xff0c;则先向老师表中插入一条老师数据&a…

高级IO-多路转接

高级IO 以前的都是拷贝接口。write什么的就是将字符串拷贝到发送缓冲区中。 应用层等待接收缓冲区填写数据的过程算是IO吗&#xff1f;算 IO等待拷贝数据&#xff1b; 真正的IO的过程就是拷贝的过程。比如等待鱼上钩的时候也算是钓鱼(adj)&#xff0c;当把鱼拿上来的时候也…

【Spring篇】代理模式

&#x1f353;个人主页&#xff1a;个人主页 &#x1f352;系列专栏&#xff1a;SSM框架 目录 一、场景模拟 二、提出问题 三、代理模式 1.静态代理 2.动态代理 一、场景模拟 ①声明接口 声明计算器接口Calculator&#xff0c;包含加减乘除的抽象方法 public interface…