Python版冈萨雷斯 V1.0
第三章已更
系列 【第三章 亮度变换和空间滤波】
使用OpenCV 库,OpenCV 是计算机视觉中经典的专用库,其支持多语言、跨平台,功能强大。
使用cv.imread(‘filename’, 0)函数读取图像,其中,filename是一个含有图像文件取名的字符串,具体用法如下:
import cv2 as cv
img = cv.imread('E:/0.jpg',-1)
第二个参数是一个标志,它指定了读取图像的方式。
cv.IMREAD_COLOR: 加载彩色图像。任何图像的透明度都会被忽视。它是默认标志。
cv.IMREAD_GRAYSCALE:以灰度模式加载图像。
cv.IMREAD_UNCHANGED:加载彩色图像,包括alpha通道(透明度)。
可以分别简单地用整数1、0或-1表示。
函数shape可给出一幅图像的宽高和通道数,函数size给出像素数目,函数dtype给出图像类型:
rows, cols, chn = img.shape
size = img.size
print('image shape:', rows, cols, chn)
print('image size:', size)
print('image type:', img.dtype)
会输出以下结果:
image shape: 839 468 3
image size: 1177956
image type: uint8
使用函数cv.imshow()在窗口中显示图像。窗口自动适合图像尺寸。
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()
第一个参数是窗口名称,它是一个字符串。第二个参数是对象。
使用函数cv .imwrite()保存图像。
cv.imwrite('image_01.png', img)
第一个参数是文件名,第二个参数是要保存的图像,图像并以PNG格式保存在工作目录中。
在计算机中,按照颜色和灰度的多少可以将图像分为四种基本类型。
1. 二值图像
2. 灰度图像
3. 索引图像
4. 真彩色RGB图像
2.6.1二值图像
一幅二值图像的二维矩阵仅由0、1两个值构成,“0”代表黑色,“1”代表白色。由于每一像素取值仅有0、1两种取值,所以计算机中二值图像的数据类型通常为1个二进制位。二值图像通常用于文字、线条图的扫描识别(OCR)和mask图像的存储。
2.6.2灰度图像
灰度图像矩阵元素的取值范围通常为[0,255]。因此其数据类型一般为8位无符号整数的(int8)。“0”表示纯黑色,“255”表示纯白色,中间的数字从小到大表示由黑到白的过渡色。
2.6.3索引图像
索引图像的文件结构比较复杂,除了存放图像的二维矩阵外,还包括一个称之为颜色索引矩阵MAP的二维数组。MAP的大小由存放图像的矩阵元素值域决定,如矩阵元素值域为[0,255],则MAP矩阵的大小为256Ⅹ3,用MAP=[RGB]表示。MAP中每一行的三个元素分别指定该行对应颜色的红、绿、蓝单色值,MAP中每一行对应图像矩阵像素的一个灰度值,如某一像素的灰度值为64,则该像素就与MAP中的第64行建立了映射关系,该像素在屏幕上的实际颜色由第64行的[RGB]组合决定。也就是说,图像在屏幕上显示时,每一像素的颜色由存放在矩阵中该像素的灰度值作为索引通过检索颜色索引矩阵MAP得到。索引图像的数据类型一般为8位无符号整形(int8),相应索引矩阵MAP的大小为256Ⅹ3,因此一般索引图像只能同时显示256种颜色,但通过改变索引矩阵,颜色的类型可以调整。索引图像的数据类型也可采用双精度浮点型(double)。索引图像一般用于存放色彩要求比较简单的图像,如Windows中色彩构成比较简单的壁纸多采用索引图像存放,如果图像的色彩比较复杂,就要用到RGB真彩色图像。
2.6.4真彩色RGB图像
在RGB色彩空间中,存在R (red,红色) 通道、G (green,绿色)通道和B(blue,蓝色)通道,共三个通道。每个色彩通道值的范围都在[0,255]之间,用这三个色彩通道的组合表示颜色。在OpenCV中,通道的顺序是B→G→R,其实,彩色图像就是类似灰度图像的叠加,图像的每个像素点都有一个值即(B,G,R),也就是三种颜色的叠加。RGB图像每一个像素的颜色值(由RGB三原色表示)直接存放在图像矩阵中,由于每一像素的颜色需由R、G、B三个分量来表示,M、N分别表示图像的行列数,三个M xN的二维矩阵分别表示各个像素的R、G、B三个颜色分量。RGB图像的数据类型一般为8位无符号整型,通常用于表示和存放真彩色图像,也可以存放灰度图像。
Matlab中图像数据类型转换函数:
默认情况下,matlab将图像中的数据存储为double型,即64位浮点数;matlab还支持无符号整型(uint8和uint16);uint型的优势在于节省空间,但涉及运算时要转换成double型。MATLAB中读入图像的数据类型是uint8,但在矩阵运算中的数据类型是double;因此I2 = im2double(I1) :把图像数组uint8类型(I1)转换成double精度类型;如果不转换,在对uint8进行加减时会产生溢出,可能提示的错误为:Function ‘*’ is not defined for values of class ‘uint8’。
Opencv中图像数据类型的转换不同深度图像的转换,要注意范围:
比如:IPL_DEPTH_8U 转到 IPL_DEPTH_32F,要用cvConvertScale(pImg8, pImg32, 1.0/255, 0); 要除255;反过来IPL_DEPTH_32F 转到 IPL_DEPTH_8U,要用cvConverScale(pImg32, pImg8, 255, 0),要乘以255;
2.7.2图像类和类型间的转换
# 颜色空间转换
img_BGR = img.copy()
img_RGB = cv.cvtColor(img_BGR, cv.COLOR_BGR2RGB)
cv.imshow('img_RGB.jpg',img_RGB)
img_GRAY = cv.cvtColor(img_BGR, cv.COLOR_BGR2GRAY)
cv.imshow('img_GRAY.jpg',img_GRAY)
img_HSV = cv.cvtColor(img_BGR, cv.COLOR_BGR2HSV)
cv.imshow('img_HSV.jpg',img_HSV)
img_YcrCb = cv.cvtColor(img_BGR, cv.COLOR_BGR2YCrCb)
cv.imshow('img_YcrCb.jpg',img_YcrCb)
img_HLS = cv.cvtColor(img_BGR, cv.COLOR_BGR2HLS)
cv.imshow('img_HLS.jpg',img_HLS)
img_XYZ = cv.cvtColor(img_BGR, cv.COLOR_BGR2XYZ)
cv.imshow('img_XYZ.jpg',img_XYZ)
img_LAB = cv.cvtColor(img_BGR, cv.COLOR_BGR2LAB)
cv.imshow('img_LAB.jpg',img_LAB)
img_YUV = cv.cvtColor(img_BGR, cv.COLOR_BGR2YUV)
cv.imshow('img_YUV.jpg',img_YUV)
2.8.1向量索引
import numpy as np
# 数组操作
v = [0,1,2,3]
print(v[2])
arr = np.arange(15).reshape((3,5))
print(arr.T)
arr = np.arange(16).reshape((2,2,4))
print(arr)
print(arr.swapaxes(1,2))
输出:
2
[[ 0 5 10]
[ 1 6 11]
[ 2 7 12]
[ 3 8 13]
[ 4 9 14]]
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]]
[[[ 0 4]
[ 1 5]
[ 2 6]
[ 3 7]]
[[ 8 12]
[ 9 13]
[10 14]
[11 15]]]
2.8.2矩阵索引
print(arr[:,2])
print(arr[0:2,-1])
print(arr[:,2:])
arr = np.arange(15).reshape((3,5))
print(arr.sum(axis=0)) # sum of each column
print(arr.min(axis=1)) # min of each row
print(arr.cumsum(axis=1)) # cumulative sum along each row
a = np.random.randn(3,2)
print(a)
print(np.hstack((arr,a)))
b = np.random.randint(10,size=(2,5))
print(b)
print(np.vstack((arr,b)))
from time import process_time as now
run = now()
c = np.concatenate((arr,a),axis=1) # hstack效果一样 水平拼接
print(c)
d = np.concatenate((arr,b),axis=0) # vstack 效果一样 垂直拼接
print(d)
end = now()
print('time: % .3f second' % -(run - end))
输出:
1
[ 2 7 12]
[4 9]
[[ 2 3 4]
[ 7 8 9]
[12 13 14]]
[15 18 21 24 27]
[ 0 5 10]
[[ 0 1 3 6 10]
[ 5 11 18 26 35]
[10 21 33 46 60]]
[[-0.45803823 -0.51157836]
[ 2.38636014 0.15317811]
[-0.65488299 -1.19634613]]
[[ 0. 1. 2. 3. 4. -0.45803823
-0.51157836]
[ 5. 6. 7. 8. 9. 2.38636014
0.15317811]
[10. 11. 12. 13. 14. -0.65488299
-1.19634613]]
[[1 9 6 9 0]
[6 9 7 9 7]]
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[ 1 9 6 9 0]
[ 6 9 7 9 7]]
[[ 0. 1. 2. 3. 4. -0.45803823
-0.51157836]
[ 5. 6. 7. 8. 9. 2.38636014
0.15317811]
[10. 11. 12. 13. 14. -0.65488299
-1.19634613]]
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[ 1 9 6 9 0]
[ 6 9 7 9 7]]
time: 0.016 second
2.9一些重要的标准数组
# ones_like,zeros_like创建与指定数组相似的都是1/都是0的数组
arr4 = np.ones((2,2), dtype = 'int16')
print(arr4)
arr5 = np.zeros((2,3))
print(arr5)
num = [1,2,3,4,5]
arr = np.asarray(num)
arr6 = np.ones_like(arr)
print(arr6)
arr7 = np.zeros_like((3,4))
print(arr7)
# empty创建新数组,只分配内存空间不填充任何值
arr8 = np.empty((2,2))
print(arr8)
# empty_like创建与指定数组相似的数组
arr9 = np.empty_like((2,2),dtype='int64')
print(arr9)
# eye,identity创建一个正方的 N*N单位矩阵(对角线为1,其余为0)
arr10 = np.eye((3))
print(arr10)
arr11 = np.identity((4),dtype = 'float64')
print(arr11)
输出:
[[1 1]
[1 1]]
[[0. 0. 0.]
[0. 0. 0.]]
[1 1 1 1 1]
[0 0]
[[ 1.60237731e+050 -8.55322771e-244]
[ 0.00000000e+000 0.00000000e+000]]
[5357991523421248858 970345782754014874]
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]