先来理解一下,图像与一般的矩阵或张量有何不同(不考虑图像的格式,元数据等信息)。首先,一张图像有自己的属性,宽,高,通道数。其中宽和高是我们肉眼可见的属性,而通道数则是图像能呈现色彩的属性。我们都知道,光学三原色是红色,绿色和蓝色,这三种颜色的混合可以形成任意的颜色。常见的图像的像素通道也是对应的R,G,B三个通道,在OpenCV中,每个通道的取值为0~255,。(注:还有RGBA,YCrCb,HSV等其他图像通道表示)。即,一般彩色图像读进内存之后是一个h * w * c的矩阵,其中h为图像高(相当于矩阵的行),w为图像宽(相当于矩阵列),c为通道数。
下面展示一个色块:
import numpy as np
import cv2 as cv
ad =r'E:\opencvdoment\pic\pic001.png'
img = cv.imread(ad,1)
print(img.shape)
cv.imshow('001', img)
cv.waitKey(0)
cv.destroyAllWindows()
这里
展示了它是一个2*2大小的3通道图片。
下面是对其像素的访问
print(img[1,1,1]) #[][][]分别为行,列,通道 输出坐标(1,1),通道为1的的颜色:255
另外,更好的访问像素和编辑图像的方法:
访问:
print(img.item(20,95,2)) # 参数分别为坐标 和通道
修改:
img.itemset((20,95,2),100) #参数分别为 像素位置 和 像素值
与一般的numpy.array一样,可以通过 img.shape 访问图像的形状。它返回一组由图像的行、列和通道组成的元组
print(img.shape) #(225, 212, 3) 注意 如果图像是灰度图像,则返回的元组仅包含行数和列数,因此它是检查加载的图像是灰度图还是彩色图的一种很好的方法
通过 img.size 访问图像的总像素数:
print(img.size)# 143100
图像数据类型可以由 img.dtype 获得:
print(img.dtype)# uint8
有时,您将不得不处理某些图像区域。对于图像中的眼部检测,在整个图像上进行第一次面部检测。当获得面部时,我们单独选择面部区域并在其内部搜索眼部而不是搜索整个图像。它提高了准确性(因为眼睛总是在脸上:D)和性能(因为我们在一个小区域搜索)。
import cv2 as cv
ad =r'E:\opencvdoment\pic\001.jpg'
img = cv.imread(ad,1)
print(img.shape)
goal = img[80:111, 57:211] # (50,57)--(111,211) 区域的像素
cv.imshow('001',goal)
cv.imshow('002',img)
cv.waitKey(0)
cv.destroyAllWindows()
有时您需要在 B,G,R 通道图像上单独工作。在这种情况下,您需要将 BGR 图像分割为单个通道。在其他情况下,您可能需要将这些单独的通道连接到 BGR 图像。
1.5.2 split
可以通过以下方式完成:
b,g,r = cv.split(img) #比较好时
或者 切片操作:
b = img[:,:,0] #比cv.split 块=快
g = img[:,:,1]
r = img[:,:,2]
borderType:边框的类型:
value 若边框的类型为cv.BORDER_CONSTANT,则这个值即为要设置的边框颜色
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
red = [255, 0, 0]
ad =r'E:\opencvdoment\pic\001.jpg'
img = cv.imread(ad,1)
t1 = cv.copyMakeBorder(img, 10, 10, 10, 10, cv.BORDER_CONSTANT, value=red)
t2 = cv.copyMakeBorder(img, 40, 40, 40, 40, cv.BORDER_REFLECT)
t3 = cv.copyMakeBorder(img, 40, 40, 40, 40, cv.BORDER_REFLECT_101)
t4 = cv.copyMakeBorder(img, 40, 40, 40, 40, cv.BORDER_REPLICATE)
t5 = cv.copyMakeBorder(img, 40, 40, 40, 40, cv.BORDER_WRAP)
plt.subplot(231),plt.imshow(img,'gray'),plt.title('origin')
plt.subplot(232),plt.imshow(t1,'gray'),plt.title('t1')
plt.subplot(233),plt.imshow(t2,'gray'),plt.title('t2')
plt.subplot(234),plt.imshow(t3,'gray'),plt.title('t3')
plt.subplot(235),plt.imshow(t4,'gray'),plt.title('t4')
plt.subplot(236),plt.imshow(t5,'gray'),plt.title('t5')
plt.show()
您可以通过 OpenCV 函数,cv.add()或简单地通过 numpy 操作将两个图像相加,res = img1 + img2。两个图像应该具有相同的深度和类型,或者第二个图像可以是像素值,比如(255,255,255),白色值。
注意 OpenCV 相加操作和 Numpy 相加操作之间存在差异。OpenCV 添加是饱和操作,而 Numpy 添加是模运算。要注意的是,两种加法对于结果溢出的数据,会通过某种方法使其在限定的数据范围内。
示例:
import numpy as np
import cv2 as cv
x = np.uint8([250])
y = np.uint8([10])
print(x+y)# [4]
print(cv.add(x,y))# [[255]]
将图像相加,但是对图像赋予不同的权重,从而给出混合感或透明感。图像按以下等式添加"
通过在(0,1)之间改变的值, 可以用来对两幅图像或两段视频产生时间上的 画面叠化 (cross-dissolve)效果.
示例:
import numpy
import cv2 as cv
import matplotlib.pyplot as plt
ad1 =r'E:\opencvdoment\pic\005.jpg'
ad2 =r'E:\opencvdoment\pic\006.jpg'
img1 =cv.imread(ad1,1)
img2 = cv.imread(ad2,1)
res = cv.addWeighted(img1, 0.6, img2, 0.4, 1)
# cv.imwrite(r'E:\opencvdoment\pic\007.jpg',res)
cv.imshow('res', res)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
------------------------------------------------
假如我想加一个OpenCV的 logo在一个图像上,如果只是简单的将两张图像想加,则会改变叠加处的颜色。如果进行上面所说的混叠操作,则会得到一个有透明效应的结果,但我希望得到一个不透明的logo。如果logo是一个矩形logo,那可以用上节所讲的ROI来做。但是OpenCV的logo是不规则形状的,所以用下面的bitwise操作来进行。
示例:
除了 OpenCV 之外,Python 还提供了一个时间模块,有助于记录代码执行时间。另一个模块配置文件有助于获取有关代码的详细报告,例如代码中每个函数花费的时间,调用函数的次数等。
该函数函数返回参考事件(如机器开启时刻)到调用此函数的时钟周期数。因此,如果在函数执行之前和之后调用它,则会获得用于执行函数的时钟周期数。
该函数返回时钟周期的频率,或每秒钟的时钟周期数。因此,要在几秒钟内找到执行时间,您可以执行以下操作
示例:
import cv2 as cv
import numpy as np
t1 = cv.getTickCount()
t2 = cv.getTickCount()
time = (t2-t1)/cv.getTickFrequency()
print(time)
3.3Opencv中的默认优化
3.3.1前言:
许多 OpenCV 功能都使用 SSE2,AVX 等进行了优化。它还包含未经优化的代码。因此,如果我们的系统支持这些功能,我们应该利用它们(几乎所有现代处理器都支持它们)。优化功能在编译时是默认启用的,因此,OpenCV 在启用时运行优化代码,否则运行未优化代码。
3.3.2相关函数:
cv.useOptimized():用于检查某优化是否开启
cv.setOptimized():开启或者关闭
示例: