写在前面: 这个部分是Numpy模块与OpenCV有关的部分。如果想了解Numpy库是什么,或者想要直接单独学习Numpy库,可以看看我以前写的这篇Numpy学习笔记。一些内容如数组类型、数组创建、数组运算和数组索引在链接文章里有,就不在这里赘述了。
在OpenCV中,黑白图像实际上就是一个二维数组,彩色图像是一个三维数组,数组中每个元素就是图像对应位置的像素值。因此,修改图像像素的操作实际上就是修改数组的操作。
- 数组行索引 = 像素所在行数 - 1 = 像素纵坐标
- 数组列索引 = 像素所在行数 - 1 = 像素横坐标
在黑白图像中,像素值为0表示黑色,像素值为255表示白色。
实例1: 创建纯黑色图像
创建一个100行、200列(即宽200、高100)的数组,数组元素格式为无符号8位整数,用0填充整个数组,将该数组当作图像显示出来,查看显示的结果。
import cv2
import numpy as np
width = 200
height = 100
img = np.zeros((height, width), np.uint8)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
结果如下:
创建纯白图像有两种方式:第一种是线创建纯黑图像,然后将图像中所有的像素值改为255;第二种使用NumPy提供的ones()方法创建一个像素值均为1的数组,然后让数组乘以255,同样可以得到一个纯白色的图像。
实例2: 创建纯白色图像
创建一个100行、200列(即宽200、高100)的数组,数组元素格式为无符号8位整数,用1填充整个数组,然后让数组乘以255,最后将该数组当作图像显示出来,查看显示的结果。
import cv2
import numpy as np
width = 200
height = 100
img = np.ones((height, width), np.uint8)*255
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
通过切片式索引操作可以修改图像中指定区域内的像素,以达到修改图像内容的效果。
实例3: 在黑色图像内部绘制白色矩形
先绘制纯黑色图像作为背景,然后使用切片式索引将图像中横坐标为50 ~ 100、纵坐标为25 ~ 75的矩形区域颜色改为纯白色。
import cv2
import numpy as np
width = 200
height = 100
img = np.zeros((height, width), np.uint8) # 创建指定宽高、单通道,像素值都为0的图像
img[25:75, 50:100] = 255 # 图像纵坐标为25~75,横坐标为50~100之间的区域变成白色
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
实例4: 创建黑白相间的图像
先绘制纯黑色图像作为背景,然后在循环中使用切片式索引操作绘制成黑白间隔图像。
import cv2
import numpy as np
width = 200
height = 100
img = np.zeros((height, width), np.uint8) # 创建指定宽高、单通道,像素值都为0的图像
for i in range(0, width, 40):
img[:, i:i + 20] = 255
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
显示颜色需要引入光谱三基色的概念,无法用二维数组表示,而是用到三维数组。OpenCV中华彩色图像默认为BGR格式,彩色图像的第三个索引表示的就是蓝、绿、红这三个颜色的颜色分量。
实例5: 创建彩色图像
创建彩色图像数组是将数组创建成三维数组,元素类型仍然为无符号8位整数。创建好表示纯黑色图像的三维数组后,复制出三个副本,三个副本分别修改最后一个索引代表的元素值。根据BGR的顺序,索引0表示蓝色分量,索引1表示绿色分量,索引2表示红色分量,让三个副本分别显示纯蓝色、纯绿色和纯红色。
import cv2
import numpy as np
width = 200
height = 100
img = np.zeros((height, width, 3), np.uint8) # 创建指定宽高、3通道,像素值都为0的图像
blue = img.copy()
blue[:, :, 0] = 255 # 1通道所有像素都为255
green = img.copy()
green[:, :, 1] = 255 # 2通道所有像素都为255
red = img.copy()
red[:, :, 2] = 255 # 3通道所有像素都为255
cv2.imshow("blue", blue)
cv2.imshow("green", green)
cv2.imshow("red", red)
cv2.waitKey()
cv2.destroyAllWindows()
随机图像是指图像中每一个像素值都是随机生成的,因为像素之间不会组成有效的视觉信息,所以这样的图像看上去就像杂乱无章的沙子。虽然随机图像没有任何视觉信息,但对于图像处理技术仍然很重要,毫无规律的像素数组称为干扰图像的噪声,或者当作图像加密的密钥。
实例6: 创建随机像素的雪花点图像
使用random.randint()方法就可以创建随机数组,将随机值的取值范围定在0 ~ 256之间(即像素值范围),元素类型定为无符号8位整数。
import cv2
import numpy as np
width = 200
height = 100
img = np.random.randint(256,size=(height,width),dtype=np.uint8) # 创建指定宽高、单通道、随机像素值的图像,随机值在0~256之间,数字为无符号8位整数
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
img = np.random.randint(256,size=(height,width,3),dtype=np.uint8) # 创建指定宽高、3通道、随机像素值的图
hstack()方法可以对数组进行水平拼接(或叫横向拼接)
array = numpy.hstack(tup)
hstack()方法可以拼接多个数组,拼接效果如下所示。被拼接的数组必须在每一个维度都具有相同的长度,也就是数组“形状相同”。
例如,创建三个一维数组,将这三个数组进行水平拼接:
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
c = np.array([7,8,9])
result = np.hstack((a,b,c))
print(result)
vstack()方法可以对数组进行垂直拼接(或叫纵向拼接)
array = numpy.vstack(tup)
例如,创建三个一维数组,将这三个数组进行垂直拼接:
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
c = np.array([7,8,9])
result = np.vstack((a,b,c))
print(result)
在OpenCV中,图像就是一个二维或三维的像素数组,这些数组同样可以被NumPy拼接。
实例7: 按照水平和垂直两种方式拼接两个图像
import cv2
import numpy as np
img = cv2.imread("1.jpg")
img_h = np.hstack((img, img))
img_v = np.vstack((img, img))
cv2.imshow("img_h", img_h)
cv2.imshow("img_v", img_v)
cv2.waitKey()
cv2.destroyAllWindows()
结果如下: