Opencv计算机视觉之路(二)——基本I/O操作

计算机视觉之路——处理文件的基本操作

——————————————————————————

1. 基本 I/O脚本:

1.1 读文件操作

    opencv的imread函数和imwrite函数支持各种静态图像文件格式,不同系统支持的文件不一样,但是都支持BMP格式。接下来在Python和Numpy中展示一幅图像的细节(Python和Numpy的操作不在此处进行介绍,可查阅官方文档进一步了解)。

    每个像素对应一个数值,由8位整数来表示,因此每个像素的取值范围是0~255,可以用cv2.cvtColor将图像转换为BGR格式(Blue-Green-Red)。看一下这样处理的效果:

#in terminal environment
import numpy as np
import cv2
img = np.zeros((3, 3), dtype = np.uint8)  
print(img)   #打印一个纯黑的图像
[[0 0 0]
 [0 0 0]
 [0 0 0]]

print(img.shape)
(3,3)

    转换为BGR的图像:

#in terminal environment
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)  #gray to BGR
print(img)
[[[0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]]]

 print(img.shape)
 (3,3,3)

    可以看到,每一个像素由三元数组组成,每个整型向量代表一个B(blue)、G(green)、R(red)的通道来表述一个色彩空间。从图像的形状来看(shape),最开始的(3,3)变成了(3,3,3),表明BGR格式的图像每个像素存在着三个通道。

1.2 写文件操作

import cv2
image = cv2.imread('test.png')
cv2.imwrite('test.jpg', image)

    可以看到,读入png格式的文件,以jpg格式的文件写出,即imwrite可以改变文件的格式。注意:大多数常见的opencv的函数都在cv2的模块内,如果遇到cv2.cv,可能是较老的opencv的版本所采用的形式,如果对应的语句报错可以去度一下新版本该语句的语法。

    在默认的情况下,imread()总会返回一个BGR格式的图像,也就是常说的RGB,只是顺序反了一下,但是imread()函数会删除 a l p h a 通道的信息,即得到的图像会没有透明度。而imwrite()函数要求图像为BGR格式或者灰度格式,上面的代码为BGR格式,那么如何创建灰度格式呢?看下面的程序

import cv2
grayimg = cv2.imread('test.png', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('test.png', grayimg)

    除此之外,imwrite()函数输出的文件中会支持所有的通道,每个通道还会有一定的位数,bmp有8位,而png允许有16位。

                                                本小节结束
—————————————————————————————————————————

2. 图像与原始字节的转换:

    一个字节为8位,可以表示0~255的整数,每一个像素也由每个通道的一个字节表示。一个opencv的图像是.array类型的二维或三位数组,一个8位的灰度图像只有一个通道,因此它是一个二维数组,而BGR则可以理解为24位的三维数组。

    举例说明:image[0,0]和image[0,0,0],第一个坐标代表 y 坐标,0表示顶部;第二个坐标代表横坐标,0表示最左边,第三个值表示的即为颜色的通道。对于一个左上角有白色像素的8位灰度图而言,image[0,0]的值为255,对于左上角有一个蓝色像素的24位BGR图而言,image[0,0]的值为[255,0,0]。

    在对像素进行操作时,还可以用另外的表达式,比如image[0,0]可以表示为image.item((0,0)),image[0,0] =128可以表示为image.setitem((0,0),128)。对与单像素的操作而言,第二种表达方式更为有效,后文会提到这种处理形式。

    如果一幅图像的每个通道为8位,则可以将其显示转换为标准的一维python bytearray格式:

bytearray = bytrarray(image)

    相反,如果bytearray含有顺序恰当的字节,可以通过显示转换和重构,得到numpy.array形式的图像:

grayimage = numpy.array(grayByteArray).reshape(height, width)
bgrimage = numpy.array(bgrButeArray).reshape(height, width, 3)

    举例说明:

import numpy as np
import cv2
import os

# make an array of 120,000 random bytes
randombytearray = bytearray(os.urandom(120000))
flatnumpyarray = np.array(randombytearray)

#convert the array to make a 400*300 gray scale image
grayimage = flatnumpyarray.reshape(300, 400)
cv2.imwrite('gray.png', grayimage)    #Generated image

#convert the array to make a 400*100 color image 
bgrimage = flatnumpyarray.reshape(100, 400, 3)
cv2.imwrite('bgr.png', bgrimage)      #Generated image

                                                本小节结束
—————————————————————————————————————————

3. 使用numpy访问数据元素

    在对生成图像有了进一步的理解之后,下一步要进行基本的图像操作,从最基本的开始学起,将BGR图像在(0,0)处的像素转换为白像素。

import cv2
import numpy as np

img = cv.imread('test.png')
img[0, 0] = [255, 255, 255]

    可以看到上面的转换极为粗暴,如果利用numpy来进行转换,会比普通的python转换的快的多。

    假设想要改变一个特定像素的蓝色值,例如坐标(150,200)的坐标处的蓝色值,使用上文提到的item()方法会很便捷,注意:某一位置三个通道的数据也是按照BGR的顺序保存的,下面的例子会将(150,200)坐标出的蓝色值变为255:

import cv2
import numpy as np

img = cv2.imread('bgr.png')
img = np.array(img)             #convert to a numpy array
img.itemset((150, 120, 0), 255)  # 0 means blue,1 means green,2 means red

    使用numpy.array的原因为numpy处理这类问题是经过优化的,在矩阵处理上的确更胜一筹更且速度快了很多,是不是觉得很一般?那就看下面的例子:

img = cv2.imread('bgr.png')
img = np.array(img)  #convert to a numpy array
img[:, :, 1] = 0

    一段简单的代码,会将图像中所有区域的G值设为0,处理后会发现图像中不含绿色,可读性强,足够简洁,也令人惊讶。

    通过numpy的索引来访问原始数组,可以进行很多有趣的操作,比如设定感兴趣的区域ROI(region of interest):设定该区域后可以进行很多操作,例如将该区域和变量绑定,设定第二区域,将第一个区域的值付给第二区域:

import cv2
import numpy as np

img = cv2.imread('bgr.png')
img = np.array(img)

my_roi = img[0:100, 0:100]
img[300:400, 300:400] = my_roi

    当然numpy还有更多的操作,size,shape,dtype等,还要进一步熟悉numpy的操作,因为这是 python处理图像的基础。

    基本的IO操作介绍到这里,下一步开始介绍高级的图像处理操作。

                                                本小节结束
—————————————————————————————————————————

4. 小插曲:一些基本概念

    当前,在计算机视觉中有三种常见的色彩空间:灰度、BGR和HSV(Hue, Saturation, Value)。

    1.1 灰度色彩空间 灰度色彩空间是通过去除彩色信息来将其转换为灰阶,灰度色彩空间对中间处理也特别有效,比如人脸检测。
    1.2 BGR 即蓝-绿-红的色彩空间,每个像素点由三原数组构成,分别代表蓝、绿、红三种颜色,与RGB含义相同,只是顺序不同。
    1.3 HSV H:hue,表示色调,S:saturation,表示饱和度,V:value,表示黑暗的程度。

猜你喜欢

转载自blog.csdn.net/asd20172016/article/details/80898667
今日推荐