import cv2 #opencv讀取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()
直方圖
cv2.calcHist(images,channels,mask,histSize,ranges)
- images: 原圖像圖像格式為 uint8 或 ?oat32。當傳入函數時應 用中括號 [] 括來例如[img]
- channels: 同樣用中括號括來它會告函數我們統幅圖 像的直方圖。如果入圖像是灰度圖它的值就是 [0]如果是彩色圖像 的傳入的參數可以是 [0][1][2] 它們分別對應著 BGR。
- mask: 掩模圖像。統整幅圖像的直方圖就把它為 None。但是如 果你想統圖像某一分的直方圖的你就制作一個掩模圖像并 使用它。
- histSize:BIN 的數目。也應用中括號括來
- ranges: 像素值范圍常為 [0256]
img = cv2.imread('cat.jpg',0) #0表示灰度圖
hist = cv2.calcHist([img],[0],None,[256],[0,256])
hist.shape
plt.hist(img.ravel(),256);
plt.show()
img = cv2.imread('cat.jpg')
color = ('b','g','r')
for i,col in enumerate(color): histr = cv2.calcHist([img],[i],None,[256],[0,256]) plt.plot(histr,color = col) plt.xlim([0,256])
?
?mask操作
# 創建mast
mask = np.zeros(img.shape[:2], np.uint8)
print (mask.shape)
mask[100:300, 100:400] = 255
cv_show(mask,'mask')
img = cv2.imread('cat.jpg', 0)
cv_show(img,'img')
masked_img = cv2.bitwise_and(img, img, mask=mask)#與操作
cv_show(masked_img,'masked_img')
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()
直方圖均衡化?
?
?
img = cv2.imread('clahe.jpg',0) #0表示灰度圖 #clahe
plt.hist(img.ravel(),256);
plt.show()
?
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
?
res = np.hstack((img,equ))
cv_show(res,'res')
自適應直方圖均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)
res = np.hstack((img,equ,res_clahe))
cv_show(res,'res')
模板匹配
模板匹配和卷積原理很像,模板在原圖像上從原點開始滑動,計算模板與(圖像被模板覆蓋的地方)的差別程度,這個差別程度的計算方法在opencv里有6種,然后將每次計算的結果放入一個矩陣里,作為結果輸出。假如原圖形是AxB大小,而模板是axb大小,則輸出結果的矩陣是(A-a+1)x(B-b+1)
# 模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2]
img.shape
template.shape
- TM_SQDIFF:計算平方不同,計算出來的值越小,越相關
- TM_CCORR:計算相關性,計算出來的值越大,越相關
- TM_CCOEFF:計算相關系數,計算出來的值越大,越相關
- TM_SQDIFF_NORMED:計算歸一化平方不同,計算出來的值越接近0,越相關
- TM_CCORR_NORMED:計算歸一化相關性,計算出來的值越接近1,越相關
- TM_CCOEFF_NORMED:計算歸一化相關系數,計算出來的值越接近1,越相關
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF) res.shape min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) min_val max_val min_loc max_loc
for meth in methods:img2 = img.copy()# 匹配方法的真值method = eval(meth)print (method)res = cv2.matchTemplate(img, template, method)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)# 如果是平方差匹配TM_SQDIFF或歸一化平方差匹配TM_SQDIFF_NORMED,取最小值if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:top_left = min_locelse:top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 畫矩形cv2.rectangle(img2, top_left, bottom_right, 255, 2)plt.subplot(121), plt.imshow(res, cmap='gray')plt.xticks([]), plt.yticks([]) # 隱藏坐標軸plt.subplot(122), plt.imshow(img2, cmap='gray')plt.xticks([]), plt.yticks([])plt.suptitle(meth)plt.show()
?
?
匹配多個對象
img_rgb = cv2.imread('mario.jpg') img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) template = cv2.imread('mario_coin.jpg', 0) h, w = template.shape[:2]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED) threshold = 0.8 # 取匹配程度大于%80的坐標 loc = np.where(res >= threshold) for pt in zip(*loc[::-1]): # *號表示可選參數bottom_right = (pt[0] + w, pt[1] + h)cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)cv2.imshow('img_rgb', img_rgb) cv2.waitKey(0)
?
?
?
?
?