OpenCV7影像金字塔與輪廓檢測

木瞳發表於2020-11-18

7.影像金字塔與輪廓檢測

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

#影像金字塔 拉普拉斯金字塔 影像輪廓

#顯示圖片

def imgShow(title,imgData):
    cv2.imshow(title,imgData)
    cv2.waitKey()
    cv2.destroyAllWindows()

#影像金字塔   向下取樣cv2.pyrUp(img)圖片縮小一倍損失的畫素是畫素的偶數行和列   向上取樣cv2.pyrDown(img)圖片放大一倍 填充的畫素用0填充

img = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll\lenna.jpg")
up = cv2.pyrUp(img) #向上取樣
down = cv2.pyrDown(img) #向下取樣
# r = np.hstack((img,up,down))
# imgShow(r"result",up)


#拉普拉斯金字塔 輸入影像-向上取樣(向下取樣)
lup = img - cv2.pyrUp(cv2.pyrDown(img))
# imgShow(r"result",lup)



#影像輪廓  
# 1.尋找輪廓 binary,contours,hierarchy = cv2.findContours(img,model,method)   
# ! opencv2返回兩個值:contours:hierarchy。注:opencv3會返回三個值,分別是img, countours, hierarchy
# {binary:圖片,
# contours:輪廓點資料,
# hierarchy:層
# }
# model輪廓檢索模式  [
# RETR_EXTERNAL:只檢索最外面的輪廓,
# RETR_LIST:檢索所有的輪廓,並將其儲存到一條連結串列中,
# RETR_CCOMP:檢索所有的輪廓,並將它們組織為兩層,頂層是各部分的外部邊界,第二層是空洞的邊界,
# RETR_TREE:檢索所有的輪廓,並重構巢狀整個輪廓所有的層次
#]
#method輪廓逼近的方法[
# CHAIN_APPROX_NONE:以Freeman鏈碼的方式輸出輪廓,所有其他方法輸出多邊形,
# CHAIN_APPROX_SIMPLE:壓縮水平的,垂直的和斜的部分,也就是函式只保留它們的終點部分
# ]

# 2.繪製輪廓 dst = cv2.drayContours(img,contours,-1,(0,0,255),2) 
# {
# img:處理影像資料,
# contours:輪廓點數,
# -1:表示繪製所有輪廓,
# (0,0,255):表示繪製使用的顏色,
# 2:繪製的寬度,
# dst:生成輪廓的結果
# }  




#處理  1.先將圖片做灰階處理 2.將影像做二值閾值處理

cImg = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll\cont.jpg")
cImg1 = cv2.cvtColor(cImg,cv2.COLOR_BGR2GRAY) #灰階處理
ret,thresh = cv2.threshold(cImg1,127,255,cv2.THRESH_BINARY) #閾值二值化處理

contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE) #尋找輪廓點
dst = cImg.copy()
dst = cv2.drawContours(cImg,contours,-1,(0,0,255),2)  #繪製輪廓點  -1顯示所有輪廓
# imgShow(r"result",dst)


#輪廓特徵


con = contours[25]
##獲取輪廓面積 cv2.contourArea(contour)
print(cv2.contourArea(con)) 
##獲取輪廓周長 True:表示閉合的  cv2.arcLength(contour,True)
print(cv2.arcLength(con,True))


#輪廓近似  approx = cv2.approxPolyDP(con,epsion,True)  取輪廓近似值 {cnt:輪廓,epsion:周長}
epsion = 0.1*cv2.arcLength(con,True)
approx = cv2.approxPolyDP(con,epsion,True)
dstImg = cImg.copy()
dstApprox = cv2.drawContours(dstImg,[approx],-1,(0,0,255),2)
# imgShow(r"result",dstApprox)


#邊界矩形  
# cv2.rectangle(cImg,(x,y),(x+w,y+h),(0,0,255),2) {(x,y):起點座標,(x+w,y+h):終點座標,(0,0,255):繪製顏色,2:繪製寬度}  
x,y,w,h = cv2.boundingRect(con)
rImg = cImg.copy()
rImg = cv2.rectangle(rImg,(x,y),(x+w,y+h),(0,0,255),2)
# imgShow(r"result",rImg)

##輪廓面積與邊界矩形比
x,y,w,h = cv2.boundingRect(con)
area = cv2.contourArea(con)
rate = float(area)/(w*h)
print(rate)


#外接圓  
# (x,y),radius = cv2.minEnclosingCircle(con) 獲取輪廓的外接圓
# cv2.circle(imgData,(x,y),radius,(0,0,255),2) 畫圓

(x,y),radius = cv2.minEnclosingCircle(con)  #獲取輪廓的外接圓
center = (int(x),int(y))
radius = int(radius)
cirImg = cImg.copy()
circle = cv2.circle(cirImg,center,radius,(0,0,255),2)
# imgShow(r"circle",circle)



#模板匹配  
# cv2.matchTemplate(imgData,template,methods)
# methods:匹配方式
# [
# TM_SQDIFF:計算平方不同,計算出來的值越小,越相關,
# TM_CCORR:計算相關性,計算出來的值越大,越相關,
# TM_CCOEFF:計算相關係數,計算出來的值越大,越相關,
# TM_SQDIFF_NORMED:計算歸一化平方不同,計算出來的值越接近0,越相關,
# TM_CCORR_NORMED:計算歸一化相關性,計算出來的值越接近1,越相關,
# TM_CCOEFF_NORMED:計算歸一化相關係數,計算出來的值越接近1,越相關
# ]

# minValue,maxValue,minLoc,maxLoc = cv2.minMaxLoc(rets);  獲取最小值,最大值以及對應的最小值最大值的位置
per = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll/lenna.jpg")
face = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll/face.jpg",cv2.IMREAD_GRAYSCALE)
pers = cv2.cvtColor(per,cv2.COLOR_BGR2GRAY)

methods = ['cv2.TM_SQDIFF','cv2.TM_CCORR','cv2.TM_CCOEFF','cv2.TM_SQDIFF_NORMED','cv2.TM_CCORR_NORMED','cv2.TM_CCOEFF_NORMED']
for meth in methods:
    method = eval(meth)
    res = cv2.matchTemplate(pers,face,method)
    minValue,maxValue,minLoc,maxLoc = cv2.minMaxLoc(res)  #獲取位置

    if meth =='cv2.TM_SQDIFF' or meth =='cv2.TM_SQDIFF_NORMED':
        top_loc = minLoc
    else:
        top_loc = maxLoc
    p1 = per.copy()
    cv2.rectangle(p1,top_loc,(top_loc[0]+face.shape[0],top_loc[1]+face.shape[1]),255,2)  #繪製矩形
    plt.subplot(121),plt.imshow(res,cmap='gray')
    plt.xticks([]),plt.yticks([])
    plt.subplot(122),plt.imshow(p1,cmap='gray')
    plt.xticks([]),plt.yticks([])
    plt.suptitle(meth)
    # plt.show()

##匹配多個物件 np.where()

ao = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll/ou.jpg")
dou = cv2.imread(r"C:\Users\Administrator\Pictures\Camera Roll/wen.jpg",cv2.IMREAD_GRAYSCALE)
aoG = cv2.cvtColor(ao,cv2.COLOR_BGR2GRAY)
res = cv2.matchTemplate(aoG,dou,cv2.TM_CCORR_NORMED)
thres = 0.98
loc = np.where(res>=thres)
print(np.array(loc).shape)
for pt in zip(*loc[::-1]):
    # minV,maxV,minL,maxL = cv2.minMaxLoc(pt)
    top_right = (pt[0]+dou.shape[0],pt[1]+dou.shape[1])
    cv2.rectangle(ao,pt,top_right,(0,0,255),1)
imgShow(r"result",ao)

在這裡插入圖片描述

相關文章