OpenCV是计算机视觉中经典的用C++开发的专用库,其支持多语言、跨平台,功能强大。opencv-python是OpenCV库的Python接口,能让开发者在Python中方便调用OpenCV的函数。
opencv-python中的图像数据使用了Numpy 库的 ndarray 类进行管理,便于进行各种数值计算和转换。
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img = cv2.imread('lena.jpg')
print(type(img),img.shape)
<class 'numpy.ndarray'> (350, 350, 3)
opencv-python从图像文件中读取数据的通道顺序是BGR,要转换为RGB才符合人们常用的通道顺序。通道转换可以用OpenCV自带的cvtColor()函数,也可以直接拆解然后重组图像数据。
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
# 用OpenCV自带的cvtColor()函数
img_bgr = cv2.imread('lena.jpg')
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img_bgr)
ax[0].set_title('Channel order:BGR')
ax[1].imshow(img_rgb)
ax[1].set_title('Channel order:RGB')
plt.show()
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img_bgr = cv2.imread('lena.jpg')
img_rgb = np.zeros_like(img_bgr)
# 手动拆解再重组
b, g, r = (img_bgr[:,:,i] for i in range(3))
img_rgb[:,:,0] = r
img_rgb[:,:,1] = g
img_rgb[:,:,2] = b
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img_bgr)
ax[0].set_title('Channel order:BGR')
ax[1].imshow(img_rgb)
ax[1].set_title('Channel order:RGB')
plt.show()
通道顺序
ROI:Region of Interest,感兴趣区域。由于opencv-python中的图像数据是<class 'numpy.ndarray'>,所以截取ROI非常简单,相当于矩阵切片操作。
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img = cv2.imread('lena.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
roi = img[100:265,100:250,:] # H,W,C
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img)
ax[0].set_title('Original Image')
ax[1].imshow(roi)
ax[1].set_title('ROI')
plt.show()
用ROI把头部切出来
彩色图的BGR三个通道是可以分开单独访问的,也可以将单独的三个通道合并成一副图像,分别使用cv2.split()和cv2.merge()函数
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img = cv2.imread('lena.jpg')
b,g,r = cv2.split(img) # 拆解通道
img = cv2.merge((r,g,b)) # 合成图像
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img)
ax[0].set_title('Original Image')
ax[1].imshow(r,cmap='gray')
ax[1].set_title('r')
plt.show()
拆解合并通道
阈值分割:将像素点值大于阈值变成一类值,小于阈值变成另一类值。用cv2:threshold()函数实现。
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img = cv2.imread('lena.jpg', flags=cv2.IMREAD_GRAYSCALE)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray',vmin=0,vmax=255)
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
各种阈值分割效果
自适应阈值分割:在前面固定阈值中,我们是随便选了一个阈值如127,那如何知道我们选的这个阈值效果好不好呢?答案是:不断尝试,所以这种方法在很多文献中都被称为经验阈值。Otsu阈值法就提供了一种自动高效的二值化方法。
import math
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
img = cv2.imread('lena.jpg', flags=cv2.IMREAD_GRAYSCALE)
# 固定阈值
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值, ADAPTIVE_THRESH_MEAN_C:小区域内取均值
th2 = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 4)
# 自适应阈值, ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核
th3 = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 6)
titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i], fontsize=8)
plt.xticks([]), plt.yticks([])
plt.show()
自适应阈值
《Python OpenCV库的常见应用2》
网友评论