数字图像处理

                第一讲  图像数据的表示和基本运算

1.1图像文件读写与显示

模拟图像:可以理解为直接观测到的图像,例如生物或机械成像系统中直接获取的图 像,没有经过采样和量化

数字图像:将模拟图像进行离散化、数字化得到的图像,可以方便计算机处理。

opencv 读写和显示图像

​
import numpy as np
import cv2 as cv
import sys
#从当前工作目录下的imagedata子目录中读入一幅彩色图
img = cv.imread('./imagedata/old_villa.jpg', cv.IMREAD_COLOR)

​ #若没有正确读取图像,显示出错信息并退出运行
if img is None:
 sys.exit("Could not read the image! ")
 #转换为灰度图像
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
#将灰度图像保存到当前工作目录中
cv.imwrite('old_villa_gray.jpg', img_gray, [cv.IMWRITE_JPEG_QUALITY,100])
 #显示读入的彩色图像
cv.imshow('old_villa color image', img)
 #显示转换得到的灰度图像
cv.imshow('old_villa gray image', img_gray)
 #等待直到按下任意键继续
cv.waitKey(0)  
#关闭显示窗口,释放显示窗口占用的资源
cv.destroyAllWindows() 

 OpenCV读取摄像机视频图像帧

#导入用到的包
import numpy as np
 import cv2 as cv
 #创建VideoCapture对象,指定设备的索引号index = 0
 cap = cv.VideoCapture(0)
 #查看VideoCapture对象属性isOpened(),若摄像机打开失败,程序退出
if not cap.isOpened():
 print("Cannot open camera! ")
 exit()
 fps = cap.get(cv.CAP_PROP_FPS)  #获取VideoCapture对象的帧率属性
frame_index = 0  #用于图像帧保存时按顺序为文件命名
#创建图像显示窗口,窗口大小可用鼠标拖动调整
cv.namedWindow('Camera playing', cv.WINDOW_NORMAL | cv.WINDOW_KEEPRATIO)
#读取视频图像帧直至按Esc键退出
while cap.isOpened():
 #调用VideoCapture对象的read()方法捕获视频图像帧
ret, frame = cap.read()
 frame_index += 1  #帧序号加1
 #如果正确读取视频图像帧,返回值ret为True,否则为False则退出程序
if not ret:
 print("Can't receive frame (stream end?). Exiting ...")
 break
 #以下代码对图像帧进行简单处理
img = np.flip(frame, 1)  #水平翻转图像帧
img_montage = np.hstack((frame, img)) #将两幅图像水平拼接为一幅图像
cv.imshow('Camera playing', img_montage)  #显示拼接后的图像
#按Esc键退出,按s键将图像帧保存为文件(当前工作目录)
keycode = cv.waitKey(int(1000/fps)) & 0xFF
 if keycode == 27:
 break
 elif keycode == ord('s'):
 #形成图像文件名
frame_name = "camera_frame_{}.jpg".format(frame_index)  
cv.imwrite(frame_name, frame)  #保存图像
#机器视觉与图像处理
cap.release()  #退出视频捕捉并释放VideoCapture对象资源
cv.destroyAllWindows()  #关闭图像显示窗口并释放资源

1.2图像类型和图像数据

矢量图(Vector):在数学上定义为一系列由线连接的点;矢量文件中的图形元素称为对象;每个 对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性;

 位图(Bitmap):位图亦称点阵图或栅格图,它的特点是整幅图由许多的像素点组成,计算机会将 图片的每个像素点进行保存

RGB真彩色图像:人眼视网膜上存在分别对红Red、绿Green、蓝Blue光敏感的三类锥状细胞,人类对颜色的 感知,是大脑融合人眼接受到的红、绿、蓝三色光刺激而形成的。

 RGB真彩色图像(RGB image,true color image)每个像素的颜色,用红、绿、蓝三个分 量描述。每个分量采用8位无符号整数进行数字化,共24位组合,因此能够产生 (28)3=224=16777216种不同颜色。像素的颜色分量(color component),又称颜色通道 (color channel)、颜色平面(color plane)等。

 Python语言中,OpenCV、Matplotlib、Scikit-image、SciPy用一个M×N×3的NumPy三维数 组来保存RGB真彩色图像数据。

 要注意的是,OpenCV函数cv.imread()以彩色方式读取图像时,返回NumPy三维数组的颜 色分量顺序为BGR(蓝色、绿色、红色)。

改写彩色图像像素的RGB值

#RGB真彩色图像的数据结构
#导入用到的包
import numpy as np
 import cv2 as cv
 import matplotlib.pyplot as plt
 %matplotlib inline
 #读入一幅彩色图像
img = cv.imread('./imagedata/old_villa.jpg', cv.IMREAD_COLOR)
 #复制图像数组,对图像数组img2的修改/删除操作,将不会影响到原图像数组img
 img2 = img.copy()
 #查看图像信息
print('数组维数:', img.ndim)
 print('图像的高、宽及颜色分量数:', img.shape)
 print('图像数据类型:', img.dtype)
#读取像素值
#注意OpenCV读取彩色图像的颜色分量顺序为BGR
 #读取坐标(100,300)处像素的B分量值
pixb=img[100,300,0]
 #显示该像素的B分量值
print('坐标[100,300]处像素的B分量值:',pixb)
 #读取坐标(100,300)处像素的BGR值
pixbgr=img[100,300,:]
 #显示该像素的BGR值
print('坐标[100,300]处像素的BGR颜色分量值:',pixbgr)
#改写像素值
#改写img2坐标(100,300)处像素的G分量值为200
 img2[100,300,1] = 200
 #在图像中画一条200个像素长,10个像素宽的水平红线
img2[300:310,200:400,:] = [0,0,255]
 #采读取老别墅铭牌子图块所有像素的BGR值,并保存为数组nameplate
 nameplate=img2[197:257,390:490,:]
 #复制图块到指定位置,注意目的区域与图块大小一致
img2[200:260,266:366,:]=nameplate
#显示上述操作结果
plt.figure(figsize=(12,6)) 
plt.subplot(1,2,1); plt.imshow(img[:,:,::-1])
 plt.title('old_villa,Original image'); plt.axis('off')
 plt.subplot(1,2,2); plt.imshow(img2[:,:,::-1])
 plt.title('old_villa,Some pixels value are changed'); plt.axis('off')
 plt.show()

索引图像为每个像素分配一个颜色索引值,同时构造一个颜色映射表colormap,又称 调色板palette。颜色映射表是一个P行×3列的二维数组,每种颜色占用一行,以红R、 绿G、蓝B分量值定义该种颜色,P为颜色映射表的行数,也是其能提供的颜色种类数 量 

索引图像的读取及其数据构成

#导入用到的包及模块
from PIL import Image
 import numpy as np
 import matplotlib.pyplot as plt
 %matplotlib inline
 im = Image.open('./imagedata/trees.tif') #读入一幅索引图像
#显示读取的索引图像
plt.figure(figsize=(12,5))
 plt.imshow(im)
 plt.title('trees, original indexd image'); plt.axis('off')
 plt.show()
 #查询并显示图像的文件格式,高、宽,以及图像类型
print('图像文件格式:', im.format)
 print('图像的宽、高:', im.size)
 print('图像类型:', im.mode)
#将图像转换为ndarray型数组,得到图像的颜色索引值数组
imgX = np.array(im)
 #观察颜色索引值数组的数据构成
print('颜色索引值数组的大小:', imgX.shape)
 print('颜色索引值数组的元素:\n', imgX)
 #获取索引图像的调色板,数据结构为一个Python列表(list)
 impal = im.getpalette()
 #确定图像调色板的颜色数量
num_colours = int(len(impal)/3)
 #将调色板转换为一个num_colours×3的二维数组颜色表
cmaparray = np.array(impal).reshape(num_colours, 3)
 #观察调色板的数据构成
print('图像调色板数组的大小:', cmaparray.shape)
 print('图像调色板数组的元素:\n', cmaparray)

 顾名思义,二值图像(binary image)的每个像素值只能取两个离散值之一,这两个离 散值一个代表“黑”、另一个代表“白”,真正是“非黑即白”,也可将二值图像看 作特殊的灰度图像。

 OpenCV中,这两个离散值为255和0,或1和0;Scikit-image中,二值图像像素值常用 bool型的True和False来表示。二值图像数据也用一个M×N二维数组来保存,数据类型 为uint8型、逻辑型(logical)等。

 视频图像(video)并不是新的图像类型,只是一组内容连续渐变的图像序列(image sequence),按一定时间间隔顺次显示,因人眼“视觉暂留”现象,从而产生运动视觉 感受。

 视频中每幅图像称为帧(frame),每秒显示的图像帧数称为帧率(frame rate,fps frames per second),例如NTSC制式视频帧率为30fps,PAL制式视频帧率为25fps。

 数字视频图像的数据量很大,在存储和传输时要采用压缩编码技术,如MPEG-4、 H264等压缩编码格式,要获取视频文件中的每帧图像数据,需对其解码。

图像类型总结:

 RGB彩色图像,用一个M×N×3三维数组保存像素的RGB颜色分量值。

 索引图像,用一个M×N二维数组保存像素的颜色索引值、一个P×3二维数组保存颜色 映射表。  灰度图像,用一个M×N二维数组保存像素的灰度值。  二值图像,用一个M×N的二维数组保存像素的灰度值。

 视频图像,一组连续渐变的静态图像序列,顺次显示每一帧图像,就可以产生运动视 觉感受。  在Python语言环境下,各类图像的数据类型视所采用的图像扩展包而定。

1.3 图像的数字化

 模拟图象: 如果图像f(x, y)定义域(x,y)和值域均为连续值时,称其为模拟图像。  数字图像: 如果图像f(x, y)的定义域(x,y)和值域均为有限的离散数值时,称其为数字图 像。

 来自场景的光线,经相机光学镜头会聚后形成光影像,投射到图像传感器的靶面上, 这个光影像本质上是一种时间和空间连续的二维光能量分布

。为了把这个光影像转换 成计算机可以操作的数字图像,需经过空间采样、时间采样、像素值量化三个主要步 骤

空间采样:对光影像的空间采样,依赖于数码相机或摄像机图像传感器的光电转换单元数量和几 何结构。

空间采样间隔∆x、∆y的选择非常重要,它决定了采样后图像的质量和数据量的大小。

要想不失真地重构图像,采样频率应该大于等于模拟信号频谱中最高频率的2倍,即必 须满足香农采样定理。

数码相机图像传感器的像素数:1600万、2000万等;扫描仪分辨率的选择:200dpi、 600dpi等,用分辨率定义了采样间隔。

时间采样:时间采样,也就是通常所说的曝光。曝光时间是指从快门打开到关闭的时间间隔,在 这段时间内,视场内物体可以在图像传感器靶面上留下光影像。

像素:数字图像由有限个元素(采样点)组成,每个元素都有一个特定的位置和幅值, 这些元素称为 图像元素(picture element),简称 像素(pixel)。

空间分辨率:是图像中可辨别的最小细节的度量,依赖于成像面阵传感器的有效像素 数,像素数越多,对细节的分辨和捕捉能力就越强,图像就越清晰。当然分辨率只是 影响图像清晰度的重要因素之一。

灰度分辨率:是灰度图像像素明暗程度可分辨的最小变化,或彩色图像像素彩色分量 强弱可分辨的最小变化。

1.4图像的坐标系

右图显示了一种坐标系约定 机器视觉与图像处理 。x轴垂直向下、对应数组行序,y轴水平向右、对应数组 列序;这样的约定,可以保证数字图像空间坐标正方向与数组或矩阵的行列下标有一 个自然对应。

OpenCV、Scikit-image、SciPy约定图像坐标系缘点为图像左上角,x轴水平向右、对 应数组列序,y轴垂直向下、对应数组行序。

图像几何变换-旋转变换

#图像旋转变换
#导入用到的包及模块
import cv2 as cv
 from skimage import transform,util
 import numpy as np
 import matplotlib.pyplot as plt
 %matplotlib inline
 #读入一幅彩色图像
img = cv.imread('./imagedata/baboon.jpg',cv.IMREAD_COLOR
img = cv.cvtColor(img,cv.COLOR_BGR2RGB)  #将色序有BGR调整为RGB
 rows,cols=img.shape[0:2]  #获取图像的高、宽
#构建旋转矩阵,指定旋转中心,旋转角度,旋转后的缩放因子
#绕图像中心将图像逆时针旋转45度,不改变输出图像大小
matrotate = cv.getRotationMatrix2D(center=(cols/2, rows/2), angle=45, scale=1)
 #采用仿射变换进行图像旋转,边缘处背景设为亮灰色
imgdst1 = cv.warpAffine(img,matrotate,dsize=(cols,rows),borderValue =(200,200,200))
 #skimage绕图像中心逆时针旋转45度,改变输出图像大小,边界颜色设为中灰色
imgdst2 = transform.rotate(img, 45, resize=True, cval=0.5)
 #将图像的数据类型由浮点小数[0,1]转换为uint8型[0,255]
 imgdst2 = util.img_as_ubyte(imgdst2)

1.5 图像的基本运算

NumPy图像的算术运算:

#用NumPy数组计算图像与常数的加、乘等算术运算,增强图像的亮度与对比度
#导入用到的包及模块
from skimage import io
 import numpy as np
 import matplotlib.pyplot as plt
 %matplotlib inline
 img = io.imread('./imagedata/old_villa.jpg')  #读入一幅彩色图像
#增加图像的亮度,每个像素的3个颜色分量BGR值均加50
 img1 = img.astype(np.float)+50
 img1= np.clip(img1,0,255).astype(np.uint8)
 #颜色分量也可不同,如[0,50,50],图像变亮且呈现黄色调
img2 = img.astype(np.float)+[50,50,0]
 img2= np.clip(img2,0,255).astype(np.uint8)
 mg3 = img.astype(np.float)*1.5 #增加图像的对比度,每个像素值乘1.5
 img3= np.clip(img3,0,255).astype(np.uint8)

OpenCV图像的算术运算:

#OpenCV: 图像的算术运算示例
#导入用到的包及模块
import cv2 as cv
 import numpy as np
 import matplotlib.pyplot as plt
 %matplotlib inline
 #读入一幅彩色图像
img = cv.imread('./imagedata/old_villa.jpg',cv.IMREAD_COLOR)
 #增加图像的亮度,每个像素的3个颜色分量BGR值均加50
 M = np.ones(img.shape, dtype = "uint8") * 50
 img1 = cv.add(img, M)
 #颜色分量也可以不同,如[0,50,50](BGR),图像变亮且呈现黄色调
M[:,:,0] = 0
 img2 = cv.add(img, M)
 #增加图像的对比度,每个像素值乘1.5,# dst = src1*alpha + src2*beta + gamma;
 img3 = cv.addWeighted(src1=img,alpha=1.5,src2=0,beta=0,gamma=0)

 掩膜通常是一个二值图像(二维数组),用值255或1表示感兴趣区像素,其余像素值为0,主要 用于:

 提取兴趣区域,用预先制作的兴趣区域掩膜与待处理图像相乘,得到兴趣区域图像,兴趣区内 图像值保持不变,而兴趣区外的像素值都为0。

 屏蔽作用,用掩膜对图像上某些区域作屏蔽,使其不参加处理,或仅对屏蔽区域作处理或统计。

1.6像素之间的位置关系

 像素是构成数字图像的基本单元,图像处理常以单个像素或一组像素为操作对象。

 为便于界定参与运算的像素集合,常用“邻域”(neighborhood)描述像素之间的 位置关系。假定某一像素p的坐标为(x,y),其邻域是指以坐标(x,y)为中心的一组相邻像 素构成的集合。

 定义邻域,是为了便于表达参与运算的像素集合,并根据中心像素p的坐标(x,y)确定其 他邻域像素坐标。  像素p的4-邻域、4-对角邻域和8-邻域不包括像素p本身,而像素p的m×n邻域则包括像 素p本身。  如果像素p位于图像的边界,则p的某些邻域像素将位于图像的外部,根据坐标(x,y)得 到的坐标值也超出了图像范围,图像空域滤波时要认真处理这个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值