图像处理基础(一)
写在前面的话✨
主要介绍图像的基本表示方法、像素的访问和操作、感兴趣区域处理、通道处理等知识点。使用的是面向Python的OpenCV,必须熟练掌握Numpy库,尤其是Numpy.array库。图像就是Numpy库中的一个数组。
参考书籍**《OpenCV轻松入门——面向Python》**李立宗著,电子工业出版社出版
1、图像的基本表示方法
1.1 二值图像
二值图像是指仅仅包含黑色(0) 和 **白色(1) **两种颜色的图像。
由于只有黑色和白色两种颜色,因此只使用一个比特位(0或者1)就可以表示。
1.2 灰度图像
如果想要表示更多的细节,就需要使用更多的颜色。通常,计算机会将灰度级表示为256个灰度级,用树枝区间[0,255]表示,其中,数值255表示纯白色,数值0表示纯黑色,其余数值表示从纯白到纯黑之间级别的灰度。
其中,用于表示256个灰度级的数值0~255可以用一个字节(8位二进制)来表示。有时也会用8位二进制值来表示一幅二值图像。
部分二进制值对应的十进制值及灰度值如下表。
二进制 | 十进制 | 颜色 |
---|---|---|
0000 0000 | 0 | 纯黑色 |
0001 0000 | 16 | 深灰色 |
1111 1111 | 255 | 纯白色 |
1.3 彩色图像
相比二值图像和灰度图像,彩色图像是更常见的一种图像,它包含了更多的细节信息。
三基色,即红、绿、蓝。自然界中常见的各种色光都可以通过三基色按照一定的比例混合构成。
首先介绍较为常见的RGB颜色空间。
在RGB颜色空间中,存在R、G、B三个颜色通道,每个色彩通道值都在[0,255]范围内。
部分RGB值如下(百度自行搜索):
因此,通常用一个三维数组表示RGB色彩空间的彩色图像。
一般情况下,在RGB色彩空间中,图像通道额顺序是R—G—B,但是特别注意的是,在OpenCV中,图像通道的顺序是B—G—R。
2、像素处理
2.1 二值图像及灰度图像
在OpenCV中,最小的数据类型是无符号的8位数。一个OpenCV图像是一个二维数组,可以用表达式访问其中的像素值。例如,可以用image[0,0]访问图像image第0行第0列位置上的像素点。第0行第0列位于图像的左上角,其中第1个索引表示第0行,第2个索引表示第0列。
例1:使用Numpy库生成一个元素值都是0的二维数组,用来模拟一幅黑色图像,并对其进行访问、修改。
import cv2
import numpy as np
# 使用函数zero生成一个8*8的二维数组,其中所有值都是0,数值类型是np.uint8.
# 根据该数组的属性,可以将其看做是一幅黑色图像
image = np.zeros((8,8),dtype = np.uint8 )
print("img =\n",img)
cv2.imshow("one",img)
print("读取像素点img[0,3]= ",img[0,3]) # img[0,3]访问的是img第0行第3列的像素点
img[0,3] = 255 # 将img第0行第3列的像素点的像素值设置为“255”
print("修改后img =\n",img[0,3])
print("读取修改后像素点img[0,3]=",img[0,3])
cv2.imshow("two",img)
#释放窗口
cv2.waitkey()
cv2.destroyALLWindows()
输出结果如下,窗口太小,因此没有放上。
例2:读取一个灰色图像,并对其像素进行访问、修改。
import cv2
img = cv2.imread("C:\\Users\\Kris\\Desktop\\lena.jpg",0)
cv2.imshow("before",img)
for i in range(10,100):
for j in range(10,100): #修改像素
img[i,j] = 255
cv2.imshow("after",img)
cv2.waitKey()
cv2.destroyALLWindows()
运行结果如下,左图为原始图像,右图是修改之后的图像。
2.2 彩色图像
RGB模式的图像在读入OpenCV中处理时,会按照行方向依次读取RGB图像的BGR通道的像素点,并将像素点以行为单位存储在ndarray的列中。
访问像素值:img[0,0,0]
式中,第一个索引表示第0行,第2个索引表示第0列,第3个索引表示第0个颜色通道(B0,G1,R2)
例3:读取一幅彩色图像,并对其像素进行访问、修改。
import cv2
img = cv2.imread("C:\\Users\\Kris\\Desktop\\lena_color.jpg")
cv2.imshow("before",img)
print("访问img[0,0]=",img[0,0])
print("访问img[0,0,0]=",img[0,0,0])
print("访问img[0,0,1]=",img[0,0,1])
print("访问img[0,0,2]=",img[0,0,2])
print("访问img[50,0]=",img[50,0])
print("访问img[100,0]=",img[100,0])
#区域1
for i in range(0,50):
for j in range(0,100):
for k in range(0,3):
img[i,j,k] = 255 #白色
#区域2
for i in range(50,100):
for j in range(0,100):
img[i,j] = [128,128,128] #灰色
#区域3
for i in range(100,150):
for j in range(0,100):
img[i,j] = 0 #黑色
cv2.imshow("after",img)
print("修改后img[0,0]=",img[0,0])
print("修改后img[0,0,1]=",img[0,0,1])
print("修改后img[0,0,2]=",img[0,0,2])
print("修改后img[50,0]=",img[50,0])
print("修改后img[100,0]=",img[100,0])
# 释放窗口
cv2.waitKey()
cv2.destroyALLWindows()
运行结果如下,左图为原始图像,右图是经过修改之后的图像。
同时,在控制台会输入如下内容。
3、使用Numpy.array访问像素
numpy.array提供了item() 和 itenset() 函数来访问和修改像素值,而且这两个函数都是经过优化处理,能够大幅度地提高处理效率。在访问及修改像素点的值时,利用numpy.array提供的函数比直接使用索引要快得多,同时,这两个函数的可读性也更好。
3.1 二值图像及灰度图像
将二值图像理解为特殊的灰度图像。
函数 item 能够更加高效地访问图像的像素点,该函数的语法格式为:item(行,列)
函数 itemset 可以用来修改图像的像素点,该函数的语法格式为:itemset(索引值,新值)
例4:读取一幅灰度图像,并对其像素进行访问、修改。
import cv2
img = cv2.imread("C:\\Users\\Kris\\Desktop\\lena.jpg",0)
# 测试读取、修改单个像素值
print("读取像素点img.item(3,2)=",img.item(3,2)) # 读取像素点
img.itemset((3,2),255) # 修改像素点
print("修改后像素点img.item(3,2)=",img.item(3,2))
# 测试修改一个区域的像素值
cv2.imshow("before",img)
for i in range(10,100):
for j in range(80,100):
img.itemset((i,j),255)
cv2.imshow("after",img)
cv2.waitKey()
cv2.destroyALLWindows()
程序运行结果如下。左图为原始图像,右图是经过修改之后的图像。
同时控制台输出如下结果。
3.2 彩色图像
我们也可以使用函数item()和函数itemset()来访问和修改彩色图像的像素值,过程与操作灰度图像相似,不同之处在与需要补充通道信息。
函数 item访问RGB图像的像素点时,该函数的语法格式为:item(行,列,通道)
函数 itemset 修改(设置)RGB图像的像素点时,该函数的语法格式为:itemset(三元组索引值,新值)
需要注意的是,针对RGB图像的访问,必须同时指定行、列以及行列索引(通道),例如img.item(a,b,c)
例5:生成一幅彩色图像,让其中的像素值均为随机数。
import numpy as np
import cv2
# 生成一幅256*256*3的彩色图像
img = np.random.randint(0,256,size = [256,256,3],dtype = np.uint8)
cv2.imshow("demo",img)
cv2.waitKey()
cv2.destroyALLWindows()
程序运行结果如下。
例6:读取一幅彩色图像,并对其像素进行访问、修改。
import numpy as np
import cv2
img = cv2.imread("C:\\Users\\Kris\\Desktop\\lena_color.jpg")
cv2.imshow("before",img)
print("访问img.item(0,0,0)=",img.item(0,0,0))
print("访问img.item(0,0,1)=",img.item(0,0,1))
print("访问img.item(0,0,2)=",img.item(0,0,2))
for i in range(0,50):
for j in range(0,100):
for k in range(0,3):
img[i,j,k] = 255 #白色
cv2.imshow("after",img)
print("修改后img.item(0,0,0)=",img.item(0,0,0))
print("修改后img.item(0,0,1)=",img.item(0,0,1))
print("修改后img.item(0,0,2)=",img.item(0,0,2))
cv2.waitKey()
cv2.destroyALLWindows()
程序运行结果如下,左图为原始图像,右图是经过修改之后的图像。
同时在控制台输出如下结果。