原文链接:http://www.juzicode.com/opencv-python-pixel-operation
图像的像素级操作包括读某个或某些像素值、以及写像素值。因为在OpenCV-Python中图像是以numpy数组形式表示的,所以可以使用下标索引的方式来访问像素。
1、numpy数组的访问
在做像素操作前需要先搞清楚下标索引的方法,下面以一个宽高为16×10的灰度图(单通道)为例。
在图片中x轴方向的大小为0~15,y轴方向的大小为0~9且是向下的,我们通常描述一个二维空间的位置是以(x,y)的坐标形式表示,比如图中a点坐标为(x,y)=(9,1),图中b点坐标为(x,y)=(2,7),但是在numpy中如果用下标方法表示时,比如a点并不是表示成img[9,1],而是第0个参数为行数,第1个参数为列数,所以a点应该表示成img[1,9],同样b点则是以img[7,2]表示的。
下面用代码验证下,先创建一个10行16列的二维数组,数组元素的值是下图这样子的:
import numpy as np
import cv2
img = np.arange(0, 160, step=1,dtype=np.uint8)
img = img.reshape(10,16)
print('img.shape',img.shape)
print(img)
运行结果:
接下来访问a点(x,y)=(9,1)和b点(x,y)=(2,7),读出这2个位置的值:
print('a点,img[1,9]:',img[1,9])
print('b点,img[7,2]:',img[7,2])
运行结果:
a点,img[1,9]: 25
b点,img[7,2]: 114
同样的如果要访问的是多行多列的元素值,可以使用切片方法访问,第0个下标是行数的切片,第1个下标是列数的切片,比如要访问下图中第4-6行,第5-10列的元素,则要使用img[4:7,5:11]的方法(Python里的左闭右开现象 ):
print('img[4:7,5:11]:\n',img[4:7,5:11])
运行结果:
img[4:7,5:11]:
[[ 69 70 71 72 73 74]
[ 85 86 87 88 89 90]
[101 102 103 104 105 106]]
2、像素值读取
在Windows画图板中,用鼠标移动到某个位置,其状态栏左下角就会出现该像素的位置值:
上图中鼠标所在位置为x=199,y=161,人眼观察到的颜色是红色,对应的像素值为(0,0,255),同样的方法可以观察到x=100,y=330的颜色为绿色,像素值一个为(0,255,0)。我们可以通过图像的索引img[161,199],img[330,100]获取到该像素的值,验证下是否和观察的一致。
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\opencv-logo.png')
pixel=img[330,100]
print('img[330,100]:',pixel)
pixel=img[161,199]
print('img[161,199]:',pixel)
运行结果和预期一样:
cv2.__version__: 4.5.2
img[330,100]: [ 0 255 0]
img[161,199]: [ 0 0 255]
下面这个例子获取y坐标100~200,x坐标200~300的像素值:
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\opencv-logo.png')
pixel=img[100:200,200:300]
print('pixel.shape:',pixel.shape)
print('img[100:200,200:300]:',pixel)
运行结果:
cv2.__version__: 4.5.2
pixel.shape: (100, 100, 3)
img[100:200,200:300]: [[[ 0 0 255]
[ 0 0 255]
[ 0 0 255]
...
[255 255 255]
[255 255 255]
[255 255 255]]
[[ 0 0 255]
[ 0 0 255]
[ 0 0 255]
...
3、像素值修改
同样的方法,如果要修改某一片区域的像素值,可以通过切片或索引的方法赋值修改该区域的像素值。
下面这个例子仍以opencv-logo.png为例,修改左下绿色部分的内容为白色,绿色部分的大致位置其左上角坐标(x,y)=(0,270),右下角坐标(x,y)=(300,560),如果使用图像下标访问,行数的范围为270:560,列数的范围为0:300,最后要赋值的对象用下标索引的表示方法为img[270:560,0:300]。
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\opencv-logo.png')
img[270:560,0:300]=255
cv2.imshow('juzicode.com',img)
cv2.waitKey(0)
运行结果:
小结:本文介绍了如何通过下标索引或切片的方法进行像素操作,因为图像在OpenCV-Python是以numpy数组形式表示的,所以numpy数组的访问方法就是图像访问方法。另外和习惯有所差异的地方是访问数组的下标是以[行数,列数]的形式进行的,和通常的坐标表示方法[x,y]有所区别。
下标访问这里讲得够明了!