- 目标
学习:
访问像素值并修改它们
访问图像属性
设定兴趣区域(ROI)
分裂和合并图片
本节几乎所有的操作都与Numpy而不是OpenCV有关。对Numpy有很好的了解,需要使用OpenCV编写更好的优化代码。
(示例将在Python终端中显示,因为它们中的大多数都只是单行代码)
访问和修改像素值
让我们先加载一个颜色图像:
import numpy as np
import cv2 as cv
img = cv.imread('lenna.jpg')
你可以通过它的行和列坐标来访问一个像素值。对于BGR图像,它返回一个蓝色、绿色、红色值的数组。
px = img[100,100]
print(px)
结果
[ 73 95 177]
对于灰度图像,只返回相应的强度。
blue = img[100,100,0]
print( blue )
结果
73
Numpy是一个用于快速数组计算的优化库。因此,简单地访问每个像素值并修改它将会非常缓慢,而且会被阻止。
请注意
上面的方法通常用于选择一个数组的区域,比如前5行和最后3列。对于单个像素访问,Numpy数组方法、array.item()和array.itemset()被认为是更好的,但是它们总是返回一个标量。如果你想要访问所有的B、G、R值,你需要分别调用array.item()。
更好的像素访问和编辑方法:
# accessing RED value
>>> img.item(10,10,2)
59
# modifying RED value
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100
- 访问图像属性
图像属性包括行数、列和通道数、图像数据类型、像素数等。
图像的形状是由img形状来访问的。它返回一组行、列和通道的元组(如果图像是颜色):
print( img.shape )
(450, 210, 3)
请注意
如果一个图像是灰度级的,那么返回的元组只包含行和列的数量,所以这是一个很好的方法来检查加载的图像是灰度还是彩色。
print( img.size )
283500
图像数据类型是通过“img.dtype”获得的:
print( img.dtype )
uint8
opencv python代码中的大量错误是由无效的数据类型引起的。
- 图像ROI
有时,你必须要玩特定的图像区域。为了在图像中进行眼睛检测,首先在图像上进行第一次人脸检测。当获得一张人脸时,我们只选择脸部区域,并在里面搜索眼睛,而不是搜索整个图像。它提高了准确性(因为眼睛总是盯着脸:D)和性能(因为我们在一个小区域内搜索)。
使用Numpy索引再次获得ROI。在这里,我选择了脸并将其复制到图像中的另一个区域:
import numpy as np
import cv2 as cv
img = cv.imread('lenna.jpg')
ball = img[35:80, 90:120]
img[5:50, 10:40] = ball
cv.imshow('res', img)
cv.waitKey(0)
cv.destroyAllWindows()
分割和合并图像通道
有时你需要在B、G、R的图像通道上分开工作。在这种情况下,您需要将BGR图像分割成单个通道。在其他情况下,您可能需要将这些单独的通道连接到BGR映像。你可以简单地通过:
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
cv.imshow('res', g)
cv.waitKey(0)
cv.destroyAllWindows()
或者
b = img[:,:,0]
假设您想将所有的红色像素设置为0,您不需要首先分割通道。Numpy索引更快:
img[:,:,2] = 0
split()是一个代价高昂的操作(就时间而言)。所以只有在你需要的时候才去做。否则就会使用Numpy索引。
- 为图像(填充)创建边框
如果你想在图像周围创建一个边框,比如一个相框,你可以使用cv.copyMakeBorder()。但是它有更多的关于卷积运算,零填充等的应用,这个函数需要以下参数:
src -输入图像
top, bottom, left, right-边界宽度在相应方向上的像素数量
borderType-标记要添加什么类型的边框。它可以是以下类型:
cv.BORDER_CONSTANT-增加一个恒定的颜色边界。该值应该作为下一个参数给出。
cv.BORDER_REFLECT-边界将是边界元素的镜像反射,像这样:fedcba|abcdefgh|hgfedcb
cv.BORDER_REFLECT_101 or cv.BORDER_DEFAULT—和上面一样,但是有一点变化,像这样:gfedcb|abcdefgh|gfedcba
cv.BORDER_REPLICATE——最后一个元素在整个过程中被复制,像这样:aaaaaa|abcdefgh|hhhhhhh
cv.BORDER_WRAP无法解释,它会是这样的:cdefgh|abcdefgh|abcdefg
value -边界类型为cv.BORDER_CONSTANT
下面是一个示例代码,演示了所有这些边界类型,以便更好地理解:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
BLUE = [255,0,0]
img1 = cv.imread('python.jpg')
replicate = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1,10,10,10,10,cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(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()