数字图像处理之图像基础

1.二值图、灰度图、彩色图

二值图:只有两种取值,黑白

灰度:对8位灰度图,有256中取值,0为黑色、255为白色

彩色:真彩色:RGB通道各有8位

​ 假彩色:8位表示256种颜色

通常用8位表示图像,是无符号的,负数或者大于255的数将会通过运算循环到0~255范围内

2.图像的矩阵表示

灰度图用二维矩阵表示,RGB彩色图用三维矩阵表示。

分辨率概念:下图为4x2的分辨率

  • 下为灰度图的矩阵和图像

[ [ 0 50 100 200 ]

​ [ 255 200 150 20 ] ]

image.png

  • 下为RGB的矩阵和图像

[[[255,127,255,255],

[127,255,0,255]],

[[127,0,0,255],

[127,255,127,0]],

[[127,255,127,0],

[255,127,127,255]]]

image.png

代码函数

1
2
3
4
5
6
7
8
9
10
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv

def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray')
else:
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.show()

矩阵与图像

1
2
3
4
A = np.random.randint(0, 256, (2,4), dtype=np.uint8)
show(A) #灰度图
B = np.random.randint(0, 256, (2,4,3), dtype=np.uint8)
show(B) #彩色图

通道分离与合并

1
2
3
4
img = cv.imread('pic/cubic500x500.jpg')
show(img)
b, g, r = cv.split(img) #openCV中顺序为BGR,按字母顺序排序
show(r)

彩色图转化为灰度图

灰度图转化公式

gray(x,y) = 0.299 r(x,y) + 0.587 g(x,y) + 0.114 b(x,y)

1
2
3
4
5
6
gray1 = 1/3*b + 1/3*g + 1/3*r	#直接加权相加

gray2 = np.uint8(gray1) #将数组转为uint8型
gray3 = gray1.astype(np.uint8) #将数组转为uint8型

gray4 = cv.cvtColor(img, cv.COLOR_BGR2GRAY) #使用函数

图像二值化

1
2
3
4
5
6
7
thresh = 125
gray4[gray4 > thresh] = 255
gray4[gray4 <= thresh] = 0
show(gray4) #将大于125的值赋值为255,小于等于的赋值为0

ignore, img_bin = cv.threshold(gray2, 125, 1, cv.THRESH_BINARY)
show(img_bin) #将gray2中大于125的值变为1,

3.图像相加、相减

示例图片读入

1
2
3
4
5
6
obj = cv.imread('pic/hedgehog500x500.jpg', 0)
bg = cv.imread('pic/line500x500.jpg', 0)
mask = cv.imread('pic/mask500x500.jpg', 0)
noise = cv.imread('pic/hedgehog_noise_500x500.jpg', 0)

show(np.hstack([obj, bg, mask, noise]))

相加:混合图像、添加噪声

相减:消除背景,差影法(比较差异,运动跟踪)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 相加
img_add = obj + bg
show(img_add) #直接相加
#add函数
img_add = cv.add(obj*0.5, bg*0.5)
show(img_add) #加权相加,不转换类型
#addWeighted函数
img_add2 = cv.addWeighted(obj, 0.5, bg, 0.5, 0)
show(img_add2) #加权相加,自动转换为uint8xing

# 减法
img_sub = np.uint8((img_add - bg * 0.5)*2)
img_sub2 = cv.subtract(img_add, bg*0.5)

show(np.hstack([img_sub, img_sub2]))

4.图像相乘、相除

相乘:掩膜

相除:矫正设备,比较差异

1
2
3
4
5
6
7
8
9
10
11
12
# 乘法
mask = mask/255 #先将一个乘数的值变换到0~1之间,保证最后结果

img_mul = obj * mask #直接相乘
img_mul2 = cv.multiply(obj*1.0, mask) #函数相乘,需要相同类型
show(np.hstack([img_mul, img_mul2]))

#除法(一般用减法)
img_div = obj / (np.float64(noise) + 1)
img_div2 = cv.divide(obj, noise+1)

show(np.hstack([img_div, img_div2]))

5.图像线性和非线性变换

线性变换

1
2
3
4
5
6
7
b = 20
k = 2
img2 = b + k * img.astype(np.int32) #变换后超出了范围,需要对结果进行处理
img2 = np.clip(img2, 0, 255) #将超出范围的值截断
show(img2)

img3 = cv.convertScaleAbs(img, alpha=2, beta=20)

np.clip(a,a_min,a_max) 将a数组中小于a_min的变成a_min,大于a_max的a_max变成

img3 = cv.convertScaleAbs(img, alpha=2, beta=20)

cv.convertScaleAbs(原图像 , k , b ) 函数中还包含其他参数,使用时需要指定alpha和beta 取绝对值再从255截断

非线性变换

1
2
3
img4 = 10 + np.log(img.astype(np.float32) + 1) / 0.1	#非线性变换运算,注意类型范围

show(img4)

λ变换

1
2
3
4
5
6
img01 = img / 255	#把图片放到0~1

img05 = np.power(img01, 0.5) * 255
img15 = np.power(img01, 1.5) * 255

show(np.hstack([img05, img, img15]))