欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计算机视觉之OpenCV图像的基础操作

程序员文章站 2022-03-25 20:37:15
...

9. 图像的基础操作

import cv2
import numpy as np
import matplotlib.pyplot as plt

for i in [cv2, np]:
    print(i.__name__,": ",i.__version__,sep="")

输出:

cv2.cv2: 4.2.0
numpy: 1.17.4
# 定义显示图片函数
def showImage(img):
    plt.figure()
    plt.imshow(img)
    plt.axis("off")
    plt.show()

9.1 获取并修改像素值

# 根据行列坐标获取像素值
img = cv2.imread("1.jpg")
showImage(img)

px = img[100,100]
print(px)

blue = img[100,100,0]
print(blue)

px2 = img[100,100,1]
print(px2)

输出:

计算机视觉之OpenCV图像的基础操作

[252 154 100]
252
154
img[100,100] = [255,255,255]
print(img[100,100])

showImage(img)

输出:

[255 255 255]

计算机视觉之OpenCV图像的基础操作

可以看到坐标(100,100)附近有个白点,即是修改的像素值。

numpy是非常高效的运算库,对于获取和修改像素值,使用array.item()和array.itemset()会更好。

print(img.item(100,100,1))
img.itemset((200,100,0),255)
img.itemset((200,100,1),255)
img.itemset((200,100,2),255)

print(img[200,100])
showImage(img)

输出:

255
[255 255 255]

计算机视觉之OpenCV图像的基础操作

9.2 获取图像属性

图像属性:包括行、列、通道、图像数据类型、像素数目等

img = cv2.imread("1.jpg")
print("shape: ",img.shape)
print("number of pixel: ",img.size)
print("data type: ",img.dtype)

输出:

shape:  (600, 800, 3)
number of pixel:  1440000
data type:  uint8

9.3 图像ROI(Region of Interest)

img = cv2.imread("2.jpg")
print(img.shape)
showImage(img)

ball = img[20:100,50:90]
print(ball.shape)
img[200:280,100:140] = ball

print(img[273:333,100:160].shape)

showImage(img)

输出:

(280, 450, 3)

计算机视觉之OpenCV图像的基础操作

(80, 40, 3)
(7, 60, 3)

计算机视觉之OpenCV图像的基础操作

9.4 拆分及合并图像通道

img = cv2.imread("2.jpg")

b,g,r = cv2.split(img)
img = cv2.merge((b,g,r))
showImage(img)

输出:

计算机视觉之OpenCV图像的基础操作

img[:,:,2]=0  # 通道2像素值全部设为0
showImage(img)

输出:

计算机视觉之OpenCV图像的基础操作

9.5 为图像扩边(填充)

cv2.copyMakeBorder()函数通常在卷积运算或0填充时使用,参数如下:

  • 1. src:输入图像
  • 2. top,bottom,left,right:对应边界的像素数目
  • 3. borderType:添加边界的类型
    • cv2.BORDER_CONSTANT:添加常数值像素边界,需要value参数指定该常数
    • cv2.BORDER_REFLECT:添加像素镜像对称,例如:fedcba|abcdefgh|hgfedcb
    • cv2.BORDER_REFLECT101:与上面类似,微小差别,例如gfedcb|abcdefgh|gfedcba
    • cv2.BORDER_REPLICATE:最后一个像素值被重复
    • cv2.BORDER_WRAP:无法书面描述,类似cdefgh|abcdefgh|abcdefg
  • 4. value:边界颜色
BLUE = [255,0,0]

img1 = cv2.imread("4.jpg")

constant = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)
reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT101)
replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)
warp = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)

img_list = [img1,constant,reflect,reflect101,replicate,warp]
names_list = ["origin","constant","reflect","reflect101","replicate","warp"]
plt.figure(figsize=(10,5))
plt.subplots_adjust(wspace=0.1,hspace=0.1)
for i in range(len(img_list)):
    plt.subplot(2,3,i+1)
    plt.imshow(img_list[i])
    plt.axis("off")
    plt.title(names_list[i]+": "+str(img_list[i].shape))

plt.tight_layout()
plt.show()

输出:

计算机视觉之OpenCV图像的基础操作

10. 图像上的算术运算

学习函数:cv2.add(),cv2.addWeighted()等

10.1 图像加法

x = np.uint8([250,222,100])
y = np.uint8([10,20,30])
print(cv2.add(x,y))
print(x+y)

输出:

[[255]
 [242]
 [130]]
[  4 242 130]

第一个输出结果:如果像素值相加后大于255,则取255。第二个输出结果:250+10=260%256=4。(因为uint8只能表示0-255之间的数)

10.2 图像混合

与图像加法类似,但可以设置权重。也就说图像加法类似普通加法,图像混合类似加权求和。

img1 = cv2.imread("1.jpg")
img1 = cv2.resize(img1,(500,500))
showImage(img1)

img2 = cv2.imread("2.jpg")
img2 = cv2.resize(img2,(500,500))
showImage(img2)

dst = cv2.addWeighted(img1,0.5,img2,0.5,0)
showImage(dst)

输出:

计算机视觉之OpenCV图像的基础操作计算机视觉之OpenCV图像的基础操作计算机视觉之OpenCV图像的基础操作

10.3 按位运算

按位操作有:AND,OR,NOT,XOR等。

如果将OpenCV标志放到另外的图像上。如果使用加法,则颜色被改变。如果使用混合,会产生透明效果。此时按位运算就派上用场了。

img1 = cv2.imread("2.jpg")
img2 = cv2.imread("3.jpg")

rows, cols, channels = img2.shape
roi = img1[0:rows,0:cols]

img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
showImage(img2gray)
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)

img1_bg = cv2.bitwise_and(roi, roi, mask=mask)
img2_fg = cv2.bitwise_and(img2,img2,mask=mask_inv)

dst = cv2.add(img1_bg, img2_fb)
img1[0:rows,0:cols] = dst

showImage(img1)

输出:

计算机视觉之OpenCV图像的基础操作

11. 程序性能检测及优化

学习函数:cv2.getTickCount, cv2.getTickFrequency

11.1 使用OpenCV检测程序效率

img1 = cv2.imread("1.jpg")

e1 = cv2.getTickCount()

for i in range(5,49,2):
    img1 = cv2.medianBlur(img1,i)
    
e2 = cv2.getTickCount()
time = (e2 - e1)/ cv2.getTickFrequency()
print(time)

输出:

0.7994256561491656
import time

start = time.time()

for i in range(5,49,2):
    img1 = cv2.medianBlur(img1,i)
    
end = time.time()
times = end - start
print(times)

输出:

0.7700002193450928

两种方法计算出的时间还是有一定的差别。

11.2 OpenCV中的默认优化

OpenCV中很多代码都被优化过,并且编译时默认开启了优化。使用cv2.useOptomized()来查看优化是否被开启,使用cv2.setUseOptimized()来开启优化。

cv2.useOptimized()

输出:

True
%timeit res = cv2.medianBlur(img1, 49)

输出:

33.3 ms ± 174 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
cv2.setUseOptimized(False)
cv2.useOptimized()

输出:

False
%timeit res = cv2.medianBlur(img1, 49)

输出:

35.8 ms ± 153 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

从以上对比的结果可以发现,开启优化时间效率更高。