Python 基于 OpenCV 视觉图像处理实战 之 图像相关的基本概念,以及图像的基础操作 一
目录
[Python 基于 OpenCV 视觉图像处理实战 之 图像相关的基本概念,以及图像的基础操作 一](#Python 基于 OpenCV 视觉图像处理实战 之 图像相关的基本概念,以及图像的基础操作 一)
[三、OpenCV 的一些基本图像处理函数介绍](#三、OpenCV 的一些基本图像处理函数介绍)
[5、简单案例:Python 读取一张图片并显示和存储](#5、简单案例:Python 读取一张图片并显示和存储)
[四、NumPy 的简单介绍](#四、NumPy 的简单介绍)
[1、Numpy 安装](#1、Numpy 安装)
[2、测试 numpy 的](#2、测试 numpy 的)
[3、NumPy 库中的一些基本函数介绍](#3、NumPy 库中的一些基本函数介绍)
[五、简单案例:使用 NumPy 成一幅二维灰度图像](#五、简单案例:使用 NumPy 成一幅二维灰度图像)
一、简单介绍
Python是一种跨平台的计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。Python是一种解释型脚本语言,可以应用于以下领域: Web 和 Internet开发、科学计算和统计、人工智能、教育、桌面界面开发、软件开发、后端开发、网络爬虫。
这里使用 Python 基于 OpenCV 进行视觉图像处理,......
二、图像相关的一些基本概念
1、像素
像素(Pixel)由 Picture(图像) 和 Element(元素)这两个单词的字母所组成的,是用来计算数码影像的一种单位,如同摄影的相片一样,数码影像也具有连续性的浓淡阶调,我们若把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小方点所组成,这些小方点就是构成影像的最小单位"像素"(Pixel)。
像素是带颜色的,这是因为一个像素就是一个很小的图像单元,单元里面包含很多信息,其中最重要的信息就是颜色。图像颜色的RGB取值范围是0~255,数值的变化代表颜色的深浅变化,值越大表示颜色越浅。对于只有黑白两色的灰度图像,0表示纯黑,255表示纯白。如下图
2、图像的构成
像素是构成图像的最小单元,像素在一幅图像上规则地排布着。在计算机眼中,图像就像是一个数组,每个数组里面装着一个像素单元。
如下图二维灰度图像像素排列示意图;二维灰度图像是一个二维数组,如图所示,x、y坐标代表了像素的位置,因为通常用f(x,y)表示坐标(x,y)处的像素值。对于灰度图像,f(x,y)的取值范围就是0~255,x的取值范围是从0到图像的高,y的取值范围是从0到图像的宽。
二维彩色图像是怎么构成的呢?
彩色图像的像素包含了RGB的3个值,因此彩色图像就是用3个二维数组表示的,每一个二维数组里面装的就是对应颜色的数值。对于一个BGR构成的图像呢?第1个二维数组里面装的就是坐标(x,y)处B的数值,第2个二维数组里面装的就是坐标(x,y)处G的数值,第3个二维数组里面装的就是坐标(x,y)处R的数值。
3、图像的格式
在使用图像时,我们经常会看到图像文件有.jpg、.png、.bmp等这样的后缀。这些都是图片的格式,只是不同图片的编解码不同。图片一共有16种格式,一般用得最多的就是前面列出的几种。在OpenCV里面,已经封装了各种图片格式的编解码器,这样用户可以不用关心图片的格式。
一般在存储图片的时候,灰度图片会存储为.bmp格式,彩色图片存储为.jpg格式,带有透明度的图片存储为.png格式。
4、图像的位深和通道
一个像素的最大值是255,用二进制表示为11111111,在计算机中占8bit的存储空间。
那么什么是位深呢?
位深就是为每个像素分配的比特数。如果比特数是8,每个像素的值可以是0~255。如果是4,每个像素的值是0~15(二进制中为1111)。一般都用255。
前面说灰度图像只需要一个二维数组表示
彩色图像需要3个二维数组表示,如图所示。这样就引入了图像通道的概念。彩色图像至少包含3个平面:Red、Green和Blue。使用这3种颜色的特定组合可以创建任何颜色。所有的像素都是这3种颜色值的组合。(255,0,0)表示Pure Red;(0,255,0)表示Pure Green;(255,0,255)表示Pure Violate,它的位深为24,因为每个像素为8×3 bit(每个通道8bit)。
彩色图像可以看成3个二维数组,每个二维数组放在一个颜色通道里面。单独拎出一个颜色通道数组显示出来的都是灰度图像,只有3个通道合并才能称之为彩色图像。
因此在图像处理中,经常把颜色通道分离,单独处理一个通道的数组,然后再合并成一幅彩色图像。
三、OpenCV 的一些基本图像处理函数介绍
1、读取一幅画图像
python
src=cv2.imread(filename,flags=1)
参数如下:
·filename:文件的位置,如果只提供文件名,那么文件应该和C++文件在同一目录,否则必须提供图片的全路径。
·flags:表示读取的参数,可以省略,说明原图不做任何修改,如果是0,则表示读取后的是单通道图像。
·函数输出为读取的图像矩阵。
2、显示图像
python
cv2.imshow(winname,mat)
在指定名字的窗口中显示存储在mat中的图像。如果窗口是使用WINDOW_AUTOSIZE创建的,图像会显示为它的原始尺寸,否则图像会调整到窗口尺寸的大小。
参数如下:
·winname:窗口的名字,这个名字是namedWindow()函数创建窗口时使用的。
·mat:存储图像数据的Mat对象。
3、输出图像到文件
python
cv2.imwrite(filename,img)
参数如下:
·filename:const string&类型的filename,写入文件名加上后缀。
·img:ImputArray类型的img,一般填写一个Mat类型的图像数据。
4、等待按键
python
cv2.waitKey(delay=0)
waitKey()函数通过指定delay(毫秒)等待按键的时间。
- 如果delay是0或负数,它会永久等待;
- 如果任意键被按下,该函数就会返回按键的ASCII值,程序继续执行;如果指定的时间没有按下键,该函数返回-1,程序继续执行。
5、简单案例:Python 读取一张图片并显示和存储
1)编写代码,注意添加图片
2)点击 小三角形运行, Run 'xxxx' 运行
3)运行结果
4)具体代码
python
"""
读取一张图片并显示和存储
(1)在代码中加入一行import cv2,就完成了OpenCV的包导入。
(2)调用函数的时候需要在OpenCV原本的函数前加上cv2.,以确保能找到该函数。
(3)注意Python的缩进方式,它代表了函数的范围。
(4)imwrite()函数可以将图像保存成不同的格式。
"""
import cv2
def main():
img = cv2.imread("Images/Dog.jpg")
cv2.imshow("Dog", img)
cv2.imwrite("Images/save_Dog.jpg", img)
cv2.waitKey(0)
if __name__ == '__main__':
main()
5)cv2 报错处理
如果提示没有 cv2 模块,可以使用 pip 安装即可
(3.10 python 环境下安装的 pencv-python==4.8.0.74)
命令:pip install opencv-python==4.8.0.74
6、简单案例:把图片保存为灰度图
彩色图像比灰度图像拥有丰富的信息,它的每个像素通常是由红(R)、绿(G)、蓝(B)3个分量来表示的,每个分量介于0~255之间。
图像中呈现的不同的颜色都是由R、G、B这3种颜色混合而成的。在OpenCV里面,彩色图像拥有3个颜色通道,但是通道的顺序是可以变换的,RGB、BRG、BGR、GBR、GRB都有可能。在读取一幅图像的时候,我们对于图像的颜色通道排布并不清楚,因此需要先把图像的颜色通道固定下来,这就需要调用OpenCV的cvtColor()函数。
cvtColor()函数的功能是对图像进行颜色空间变换,原型如下:
pythondst=cv2.cvtColor(src,code)
参数说明:
·src:输入图像即要进行颜色空间变换的原图像,可以是Mat类。
·code:转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片,后面会详细讲述。
注意:
- cvtColor()函数还可以通过改变参数cv2.COLOR_RGB2BRG等改变图像颜色通道的排列顺序。
- 另外也可以直接在读取图像函数imread时设置参数为0,直接将彩色图像读取为灰度图像,img=cv2.imread('1.jpg',0)。
python
"""
读取一张图片保存为灰度图
(1)在代码中加入一行import cv2,就完成了OpenCV的包导入。
(2)调用函数的时候需要在OpenCV原本的函数前加上cv2.,以确保能找到该函数。
(3)注意Python的缩进方式,它代表了函数的范围。
(4)imwrite()函数可以将图像保存成不同的格式。
"""
import cv2
def main():
# 读取图片
image = cv2.imread('Images/Dog.jpg')
# 转换为灰度图
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 保存灰度图
cv2.imwrite('Images/Gray_Dog.jpg', gray_image)
if __name__ == '__main__':
main()
运行代码,就会保存一张灰度图
四、NumPy 的简单介绍
1、Numpy 安装
在环境中,使用 pip install numpy
2、测试 numpy 的
1)编写代码测试生一个排列
2)运行结果
3)代码
python
"""
使用 numpy 生成一个排列
"""
import numpy as np
def main():
np_arang = np.arange(20).reshape(5, 4)
print(np_arang)
if __name__ == '__main__':
main()
3、NumPy 库中的一些基本函数介绍
1)一些基础的函数
- ndim:维度。
- shape:各维度的尺度。
- size:元素的个数。
- dtype:元素的类型。
- itemsize:每个元素的大小。
2)ndarray数组的创建
- np.arange(n):元素从0到n-1的ndarray类型。
- np.ones(shape):生成全1。
- np.zeros((shape),ddtype=np.int32):生成int32型的全0数组。
- np.eye(n):生成单位矩阵。
- np.ones_like(a):按数组a的形状生成全1的数组。
- np.zeros_like(a):按数组a的形状生成全0的数组。
- np.linspace(1,10,4):根据起止数据等间距地生成数组。
3)数组的维度变换
- reshape(shape):不改变当前数组,依shape生成。
- resize(shape):改变当前数组,依shape生成。
- swapaxes(ax1,ax2):将两个维度进行调换。
- flatten():对数组进行降维,返回折叠后的一维数组。
五、简单案例:使用 NumPy 成一幅二维灰度图像
1、编写代码
2、运行代码
3、运行结果,显示一个灰色图(可能太小),Images 保存一个 Numpy_GrayImg 图片
六、彩色图像的通道分离和混合
1、知识介绍
灰度图像是单通道的,彩色图像拥有R、G、B三个颜色通道。因此在图像处理时,经常把颜色通道分离,单独处理一个通道的数组,然后再合并成一幅彩色图像。
在实际的代码编写中,只需要调用OpenCV中的split()和merge()函数就可以实现图像的通道分离和合并。
A、split()函数的功能是将多通道的矩阵分离成单通道矩阵,原型如下:
python
[,mv]=cv2.split(src)
参数说明:输入参数为要进行分离的图像矩阵,输出参数为一个Mat数组。
B、merge()函数的功能是将多个单通道图像合成一幅多通道图像,原型如下:
python
dst=cv2.merge([,dst])
参数说明:输入参数可以是Mat数组,输出为合并后的图像矩阵。
2、简单案例:彩色图像的通道分离和混合
1)编写代码
2)运行代码,结果如下
3)具体代码
python
"""
彩色图像的通道分离和混合
1)输入一幅彩色图像,通过程序将其分割成R、G、B这3个通道的图像并显示。
2)在分割前需要先确定图像的颜色通道分布,因此先调用cvtColor()函数固定颜色通道
3)在图像通道分离后,不同颜色通道的图像显示深浅不一,单通道的图像呈现该颜色通道的灰度信息
4)把这3个颜色通道混合一下,这样img3又回到了原来输入的彩色图像样式
"""
import numpy as np
import cv2
def main():
# 读取图片
img = cv2.imread("Images/Dog.jpg")
# 设置窗口属性,并显示图片
cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Dog", img)
# 固定 rgb 通道,分离颜色
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
r, g, b = cv2.split(img2)
cv2.namedWindow("Red", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Red", r)
cv2.namedWindow("Green", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Green", g)
cv2.namedWindow("Blue", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Blue", b)
# 合并颜色通道
mergeImage = cv2.merge([b, g, r])
cv2.namedWindow("mergeImage", cv2.WINDOW_KEEPRATIO)
cv2.imshow("mergeImage", mergeImage)
cv2.waitKey(0)
if __name__ == '__main__':
main()
七、彩色图像的二值化
1、知识介绍
图像的二值化是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果。彩色图像二值化最简单的步骤如下:
(1)彩色图像转灰度。
(2)图像阈值化处理,即像素值高于某阈值的像素赋值为255,反之为0。其中,阈值的操作会调用OpenCV的threshold()函数。
threshold()函数声明如下:
python
ret, dst = cv2.threshold(src, thresh, maxval, type);
函数功能:实现图像固定阈值的二值化。
参数说明:
·src:输入图,只能输入单通道图像,通常来说为灰度图。
·dst:输出图。
·thresh:阈值。
·maxval:当像素值超过了阈值(或者小于阈值,根据type来决定)时所赋予的值。
·type:二值化操作的类型,包含5种类型,即cv2.THRESH_BINARY、cv2.THRESH_BINARY_INV、cv2.THRESH_TRUNC、cv2.THRESH_TOZERO和cv2.THRESH_TOZERO_INV。
2、简单案例:彩色图像二值化
1)编写代码
2)运行,得到二值化图像
3)具体代码
python
"""
彩色图像二值化
1)高于127的像素全部置为255,低于的全部置为0
"""
import cv2
def main():
# 读取图片,并且灰度处理
img = cv2.imread("Images/save_Dog.jpg", 0)
# 设置窗口属性,并显示图片
cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Dog", img)
# 图像二值化
thresh, dst = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 设置窗口属性,并显示图片
cv2.namedWindow("dst", cv2.WINDOW_KEEPRATIO)
cv2.imshow("dst", dst)
cv2.waitKey(0)
if __name__ == '__main__':
main()
八、彩色图像的遍历
灰度图像的遍历按照访问二维数组的方式得到坐标位置的像素。那对于彩色图像呢?彩色图像可以看出是3维数组,遍历方式如下
python
"""
彩色图像的遍历
1)把第一个通道里面的颜色信息全部变为了0
"""
import cv2
def main():
img = cv2.imread("Images/Dog.jpg")
# 设置窗口属性,并显示图片
cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Dog", img)
# 得到图片的宽高、和维度
height, width, n = img.shape
# 拷贝一个图片
img2 = img.copy()
for i in range(height):
for j in range(width):
# 将第一个通道内的元素重新赋值
img2[i, j][0] = 0
# 设置窗口属性,并显示图片
cv2.namedWindow("img2", cv2.WINDOW_KEEPRATIO)
cv2.imshow("img2", img2)
cv2.waitKey(0)
if __name__ == '__main__':
main()
运行,结果如下:
九、彩色图像和灰度图像的转换
1、知识介绍
彩色图像转成灰度图像有3种路径:
- imread读取图像的时候直接设置参数为0,彩色图像自动被读成灰度图像。
- 调用cvtColor()函数,参数设置为cv2.COLOR_BGR2GRAY。
- 调用split()函数,可以将一幅彩色图像分离成3个单通道的灰度图像。
那么灰度图像有没有可能转换成彩色图像呢?
我们知道灰度图像是单通道的,彩色图像是RGB 3这个颜色通道。
那么是否可以人为地增加图像的通道,伪造出另外两个通道,而另外两个通道可以随机地赋值呢?
2、简单案例:彩色图像和灰度图像的转换
1)编写代码
2)运行结果
3)具体代码
python
"""
彩色图像和灰度图像的转换
1)主要实现原理:增加图像通道
2)新建了一个3通道的空的彩色图像,
3)然后将读取的灰度图像放在新建的彩色图像的第一个通道,也就是B通道,
4)其他两个通道赋值0,所以图像整体呈现蓝色
"""
import numpy as np
import cv2
def main():
img = cv2.imread("Images/Dog.jpg")
# 设置窗口属性,并显示图片
cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Dog", img)
# 获取图片长宽
height, width, n = img.shape
# 生成一个空的彩色图像
gray = np.zeros((height, width, 3), np.uint8)
# 遍历像素,0 通道赋值,其余通道 0
for i in range(height):
for j in range(width):
gray[i, j][0] = img[i, j][0]
gray[i, j][1] = 0
gray[i, j][2] = 0
# 设置窗口属性,并显示图片
cv2.namedWindow("grayToColor", cv2.WINDOW_KEEPRATIO)
cv2.imshow("grayToColor", gray)
cv2.waitKey(0)
if __name__ == '__main__':
main()
4)上述方法转换的图像颜色很单一。有没有更加智能的方法呢?在摄像技术不是很成熟的时期,人们给拍摄出来的黑白照片上色,发明了一种伪彩色图像技术。在OpenCV里面,可以用预定义好的Colormap(色度图)来给图片上色,效果如下
代码如下:
python
"""
彩色图像和灰度图像的转换
1)用预定义好的Colormap(色度图)来给图片上色
2)伪彩色图像目前主要应用在对高度、压力、密度、湿度等描述上,彩色数据可视化。
"""
import numpy as np
import cv2
def main():
img = cv2.imread('Images/Gray_Dog.jpg')
# 设置窗口属性,并显示图片
cv2.namedWindow("Dog", cv2.WINDOW_KEEPRATIO)
cv2.imshow("Dog", img)
# 色度图上色
img_Color = cv2.applyColorMap(img, cv2.COLORMAP_JET)
# 设置窗口属性,并显示图片
cv2.namedWindow("img_Color", cv2.WINDOW_KEEPRATIO)
cv2.imshow("img_Color", img_Color)
cv2.waitKey(0)
if __name__ == '__main__':
main()