目录
OpenCV: Core Operationshttps://docs.opencv.org/4.1.1/d7/d16/tutorial_py_table_of_contents_core.html
2.1 图像基本操作
OpenCV: Basic Operations on Imageshttps://docs.opencv.org/4.1.1/d3/df2/tutorial_py_basic_ops.html
2.1.1 访问和修改像素值
import numpy as np
import cv2 as cv
import os
# 图片读取
img_path = os.getcwd() + r"\resources\02\keji.jpeg"
img = cv.imread(img_path)
print(img.shape)
print(img[100,100]) #一个像素值,bgr
print(img[100,100,0]) #像素值的b值
#注意,不要一个一个像素改,要学会用numpy加速
2.1.2 获取图片属性
import numpy as np
import cv2 as cv
import os
# 图片读取
img_path = os.getcwd() + r"\resources\02\keji.jpeg"
img = cv.imread(img_path)
print(img.shape)
print(img.size) #多少个数据,461x640x3
print(img.dtype)#数据类型
#访问和修改像素更好的方法
#访问
print(img.item(10,10,2))
#修改
img.itemset((10,10,2),100) #将图片10X10位置像素的r值改为100
print(img.item(10,10,2))
2.1.3 图片分割
#比如我们要截取图片左上角、中间的一部分
import numpy as np
import cv2 as cv
import os
# 图片读取
img_path = os.getcwd() + r"\resources\02\keji.jpeg"
img = cv.imread(img_path)
img_leftup = img[0:300,0:300]
cv.imshow("img_leftup",img_leftup)
cv.waitKey(0)
cv.destroyAllWindows()
2.1.4 分割与合并通道
#比如我们要截取图片左上角、中间的一部分
import numpy as np
import cv2 as cv
import os
# 图片读取
img_path = os.getcwd() + r"\resources\02\keji.jpeg"
img = cv.imread(img_path)
#分割通道
b,g,r = cv.split(img)
#合并通道
img = cv.merge((b,g,r))
注意:split是个耗时的操作,必要时才需要,否则,最好用numpy索引(如:img[0:300,0:300])
2.1.5 为图像创建边框
(在jupyter编辑)如果不知道函数的参数,按住Shift 并双击tab,即会打开函数说明。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
import os
BLUE = [255,0,0]
img_path = os.getcwd() + r"\resources\02\115.jpg"
img=cv.imread(img_path,1)
#转为rgb
b,g,r = cv.split(img)
img=cv.merge((r,g,b))
replicate = cv.copyMakeBorder(img, 20, 20,20,20,cv.BORDER_REPLICATE) #复制边缘像素
reflect = cv.copyMakeBorder(img,20, 20,20,20,cv.BORDER_REFLECT) #镜像边缘像素
reflect101 = cv.copyMakeBorder(img,20, 20,20,20,cv.BORDER_REFLECT101) #镜像边缘像素
wrap = cv.copyMakeBorder(img,20, 20,20,20,cv.BORDER_WRAP)
constant = cv.copyMakeBorder(img,20, 20,20,20,cv.BORDER_CONSTANT,value=BLUE) #加上特定颜色的边框
#显示
plt.subplot(231),plt.imshow(img,'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('reflect101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('wrap')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('constant')
plt.show()
2.2 图像的运算
OpenCV: Arithmetic Operations on Images
2.2.1 图像的加法
x = np.uint8([250])
y = np.uint8([10])
print(cv.add(x,y)) # 250+10 = 260 => 255 ,最大只能是255
print( x+y ) # 250+10 = 260 % 256 = 4 ,这个就溢出了
import numpy as np
import cv2 as cv
import os
# 图片读取
img_path1 = os.getcwd() + r"\resources\02\keji.jpeg"
img1 = cv.imread(img_path1)
img1 = cv.resize(img1,(300,300)) #注意矩阵大小一致
img_path2 = os.getcwd() + r"\resources\02\115.jpg"
img2 = cv.imread(img_path2)
img2 = cv.resize(img2,(300,300))
img3 = cv.add(img1,img2)
cv.imshow("img3",img3)
cv.waitKey(0)
cv.destroyAllWindows()
2.2.2 图像混合
这个也是图像的加法,只不过两个加起来时各自的权重不同
其中:α的取值范围是0-1
下面是变换后的公式
import cv2 as cv
import os
img1 = cv.imread(os.getcwd()+ r"\resources\02\ml.png")
img1 = cv.resize(img1,(196,233))
img2 = cv.imread(os.getcwd()+ r"\resources\02\opencv-logo.png")
img2 = cv.resize(img2,(196,233))
dst = cv.addWeighted(img1,0.7,img2,0.3,0) #相当于减淡了img2
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()
2.2.3 图片位运算
这个包含与,或,非和异或操作,在提取图片的任何一部分、非矩形剪切时非常有用。
现在,我想把opencv的logo放在一幅图上面,如果用add叠加,图片颜色会改变。如果用混合的办法,只能是透明度的变化。下面看下如何叠加logo更加显眼。
#加载图片
import cv2 as cv
import os
import typing
img1 = cv.imread(os.getcwd() + r"\resources\02\robot.jpeg")
img2 = cv.imread(os.getcwd() + r"\resources\02\opencv-logo.png")
def img_show(name:str,img, time:int): #1 表示略过,0 表示一直显示,除非按enter跳过
cv.imshow(name,img)
cv.waitKey(time)
cv.destroyAllWindows()
#获取img2的shape
rows,cols,channels = img2.shape
roi = img1[0:rows,0:cols] #按照图像2的大小获取图片1的区域(剪切)
img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)#将图片2转为灰度图
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY) #将10作为阈值,小于10,置为0,大于10,置为255,相当于做二值化处理
img_show("mask", mask, 0)
mask_inv = cv.bitwise_not(mask) #图像反转,即非操作
img_show("mask_inv", mask_inv, 0)
img1_bg = cv.bitwise_and(roi, roi, mask = mask_inv) #mask表示要用什么盖住
img_show("img1_bg", img1_bg, 0)
img2_fg = cv.bitwise_and(img2, img2, mask = mask)
img_show("img2_fg", img2_fg, 0)
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols] = dst #修改img1的像素
img_show("img1", img1, 0)
2.3 性能测量和改进技术
2.3.1 用OpenCV测量代码性能
import cv2 as cv
start = cv.getTickCount() #开始计时点
#代码
for i in range(100000):
pass
end = cv.getTickCount() #再次计时点
time = (end - start)/cv.getTickFrequency() #运行代码所用的时间,单位是秒
print(time)
2.3.2 OpenCV中的默认优化
OpenCV中的很多函数是用SSE2,AVX等优化的,当然也包含非优化代码。如果我们的系统支持,那么我们就应该使用优化代码,从而提高运行速度。你可以用cv.useOptimized()来检查系统是否可以用优化代码,并且用cv.setUseOptimized()来设置是否使用优化功能。代码优化是默认设置
import cv2 as cv
import os
img = cv.imread(os.getcwd() + r"\resources\02\keji.jpeg")
# print(cv.useOptimized())
# cv.setUseOptimized(True)
start = cv.getTickCount()
for i in range(5,49,2):
img = cv.medianBlur(img,i) #中值滤波
end = cv.getTickCount()
time = (end-start)/cv.getTickFrequency()
print(str(time) + " s")