本节中几乎所有的操作都与Numpy相关,而不是OpenCV。 需要熟悉Numpy才能使用OpenCV编写更好的优化代码。
注:本文翻译自openCV官网教程,为方便理解,有些许添加或者改动
[英文版链接]
https://docs.opencv.org/trunk/d3/df2/tutorial_py_basic_ops.html
首先,读取彩色图片
import numpy as np
import cv2 as cv
img = cv.imread('xxx.jpg')
您可以通过其行和列坐标访问像素值。 对于BGR图像,它返回一个蓝色,绿色,红色值的数组。 对于灰度图像,只返回相应的亮度。
px = img[100,100] #取坐标值为(100,100)的像素点
print(px)#输出一个数组,比如[157,166,200]
#只访问蓝色像素,绿色像素,红色像素
blue = img[100,100,0] #157
green= img[100,100,1] #166
red= img[100,100,2] #200
同样,可以修改像素值
img[100,100] = [255,255,255]
print(img[100,100])#输出[255,255,255]
温馨提示:Numpy是用于数组快速计算的优化库。 因此,简单地访问每个像素值并修改它将会非常缓慢,
所以不鼓励这样做。
注:上述方法通常用于选择一个数组的区域,比如前5行和后3列。 对于单个像素访问,Numpy数组方法array.item()和array.itemset()被认为更好,但是它们总是返回一个标量。 如果你想访问所有的B,G,R值,你需要分别调用array.item()。
更好的像素访问和编辑方法:
#访问红色通道值,0蓝 1绿 2红
img.item(10,10,2) #59
#修改红色通道值
img.itemset((10,10,2),100)
img.item(10,10,2) #100
图片的属性包括行数,列数,通道数,图片数据类型,像素数等
print(img.shape) #(342,548,3)
#通过img.shape来获取img的形状,返回一个元组(tuple),
#分别为行数,列数和通道数(如果是彩色图片就返回第三个参数)
注:如果是灰度图,则返回的元组仅包含行数和列数,因此检查加载的图像是灰度还是颜色是一种好方法。
print(img.size)#返回总的像素数目 = 行数*列数(*通道数)
print(img.dtype)#返回图片的数据类型 如:unit8,float32,float64等
注:调试时img.dtype非常重要,因为OpenCV-Python代码中的大量错误是由无效的数据类型引起的。
有时候,检测图像时,需要选取一定的图像区域。 比如,对于图像中的眼睛检测,首先在整个图像上进行人脸检测。 当获得脸部时,我们单独选择脸部区域并在其内部搜索眼睛而不是搜索整个图像。 它提高了准确性(因为眼睛总是在脸上)和性能(因为我们在一个小区域搜索)
ROI也是使用Numpy索引获得,在下面的例子中,我选择球,并将其复制到图像中的另一个区域:
ball = img[284:340,330:390]
img[273:333,100:160]=ball
有时您需要分别处理B,G,R图像通道。 在这种情况下,您需要将BGR图像拆分为单个通道。 在其他情况下,您可能需要将这些单个频道加入BGR图像。 你可以简单地通过:
b,g,r = cv.split(img)
img=cv.merge(b,g,r)
#或者
b = img[:,:,0]
#假设您要将所有红色像素设置为零,则不需要先分割通道。 Numpy索引速度更快:
img[:,:,2]=0
温馨提示:cv.split()是一个代价高昂的操作(就时间而言)。 所以只有在你需要的时候才能做到。
否则,推荐使用Numpy索引。
如果你想在图像周围创建边框,就像是一个相框,你可以使用cv.copyMakeBorder()。 但它有更多的应用卷积操作,零填充等。这个函数有以下参数:
以下是展示所有这些边界类型以便更好理解的示例代码:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
BULE=[255,0,0]
img1 = cv.imread('XXX.png')
replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect_101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.coprMakeBorder(img1,10,10,10,10,cv.BORDER_WRAP)
constant = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_CONSTANT,value=BLUE)
plt.subplot(231)
plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232)
plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233)
plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234)
plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235)
plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236)
plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()