掩膜/遮罩 Masking
可以通过位运算来实现,来让我们更好地关注图像的某一部分。
import cv2 as cv
import numpy as np
img = cv.imread('Photos/cats.jpg')
cv.imshow('Cats',img)
blank = np.zeros(img.shape[:2],dtype='uint8')
#遮罩的大小(the dimensions of the mask)必须和所作用图像大小一致
cv.imshow('Blank Image',blank)
mask = cv.circle(blank,(img.shape[1]//2,img.shape[0]//2),100,255,-1) #圆形遮罩
#这里的遮罩不是遮起来,而是需要显示的部分
cv.imshow('Mask',mask)
masked = cv.bitwise_and(img,img,mask=mask) #img & img = img
cv.imshow('Masked Image',masked)
cv.waitKey(0)
直方图计算 Histogram Computation
可视化像素强度分布。先查看灰度直方图(Grayscale Histogram)。
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('Photos/cats.jpg')
cv.imshow('Cats',img)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('Gray',gray)
#Grayscale Histogram
gray_hist = cv.calcHist([gray],[0],None,[256],[0,256])
#images传递的参数格式为列表,传入图像应该用中括号[]括起来
#channels传入图像的通道,如果是灰度图像那只有一个通道,值为0,用[]传入
#mask是掩膜图像
#histSize是灰度级的个数,需要中括号
#ranges是像素值的范围,通常取[0,256]
plt.figure()
plt.title('Grayscale Histogram')
plt.xlabel('Bins') #x轴标题
plt.ylabel('num of pixels') #y轴标题
plt.plot(gray_hist)
plt.xlim([0,256])
plt.show()
cv.waitKey(0)
x轴表示像素强度值,y轴表示该像素强度值的像素个数。
查看颜色直方图(Colour Histogram),顺便在其中再应用一下遮罩。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
img = cv.imread('Photos/cats.jpg')
cv.imshow('Cats',img)
blank = np.zeros(img.shape[:2],dtype='uint8')
circle = cv.circle(blank,(img.shape[1]//2,img.shape[0]//2),100,255,-1)
mask = cv.bitwise_and(img,img,mask=circle)
cv.imshow('Mask',mask)
#Colour Histogram
plt.figure()
plt.title('Colour Histogram')
plt.xlabel('Bin')
plt.ylabel('num of pixels')
colors = ('b','g','r')
for i,col in enumerate(colors):
hist = cv.calcHist([img],[i],circle,[256],[0,256])
#注意此处的遮罩参数不是mask而是circle
plt.plot(hist,color=col)
plt.xlim([0,256])
plt.show()
cv.waitKey(0)
阈值 Thresholding
选择一个值作为阈值,当图像像素高于这个值时设为某一固定值,否则设为0。这一过程也能被称作二值化。之前轮廓检测时也有通过阈值将图像二值化后获取轮廓。
import cv2 as cv
img = cv.imread('Photos/cats.jpg')
cv.imshow('Cats',img)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('Gray',gray)
#Simple Thresholding 简单的阈值化
threshold,thresh = cv.threshold(gray,150,255,type=cv.THRESH_BINARY)
#当像素值大于150时,将像素值设置为255(白),否则则设为0(黑)
#thresh为返回的二值化图像,threshold就是设置的阈值150
cv.imshow('Simple Thresholded',thresh)
#逆阈值图像
threshold,thresh_inv = cv.threshold(gray,150,255,type=cv.THRESH_BINARY_INV)
cv.imshow('Simple Thresholded Inverse',thresh_inv)
#Adaptive Thresholding 自适应阈值
adaptive_thresh = cv.adaptiveThreshold(gray,255,adaptiveMethod=cv.ADAPTIVE_THRESH_MEAN_C,
thresholdType=cv.THRESH_BINARY,blockSize=11,C=3)
#method:选用的方法是计算像素领域的均值作为阈值(使用高斯方法会加权重)
#blockSize:内核大小(用于计算的领域大小)
#C:表示可以给所得均值减去C用来微调我们的阈值
cv.imshow('Adaptive Thresholding',adaptive_thresh)
cv.waitKey(0)
图像梯度和边缘检测 Gradient and Edge Detection
之前曾使用过Canny边缘检测器抓取图像的边缘,现在使用Laplacian和Sobel来进行边缘检测和对比。
import cv2 as cv
import numpy as np
img = cv.imread('Photos/park.jpg')
cv.imshow('Park',img)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('Gray',gray)
#有一些函数要求输入的image是单通道图像
#Laplacian 拉普拉斯算子 本质上是计算该图像的梯度
lap = cv.Laplacian(gray,ddepth=cv.CV_64F)
#ddepth:期望的图像深度
lap = np.uint8(np.absolute(lap))
#uint8是专门用于存储各种图像的(包括RGB,灰度图像等),范围是从0–255
#图像本身不能具有负像素,故使用np.absolute
cv.imshow('Laplacian',lap)
#Sobel 在x方向和y方向上计算梯度
sobelx = cv.Sobel(gray,cv.CV_64F,1,0)
sobely = cv.Sobel(gray,cv.CV_64F,0,1)
combined_sobel = cv.bitwise_or(sobelx,sobely)
cv.imshow('Sobel X',sobelx)
cv.imshow('Sobel Y',sobely)
cv.imshow('Combined Sobel',combined_sobel)
canny = cv.Canny(gray,135,175)
cv.imshow('Canny',canny)
cv.waitKey(0)
Canny得到的版本看上去最为简洁。