Opencv常用函數合集【持續更新】

1.輸入、顯示和保存圖像

關鍵函數:

  • 讀取:imread()
  • 顯示:imshow()
  • 保存:imwrite()
  • 窗口:namedWindow()
import cv2 #引用模塊
'''輸入圖像'''
img = cv2.imread('xxx.jpg',1)
'''顯示圖像'''
cv2.namedWindow('img_win',cv2.WINDOW_NORMAL)#設置一個名爲img_win的窗口,窗口屬性爲NORMAL
cv2.imshow('img_win',img)
k = cv2.waitKey(0)
if k==27:                    #ESC
   cv2.destroyAllWindows()
elif k==ord('s') :           #按下s
    cv2.imwrite('xxx.jpg',img)    '''保存圖像'''
    cv2.destroyAllWindows()

2.讀取、顯示、保存和處理視頻

關鍵函數:

  • VideoCapture(),參數爲0爲讀取攝像頭,參數爲文件名讀取對應視頻文件
import cv2
'''讀取攝像頭'''
def CapFromCamera():
    cap = cv2.VideoCapture(0)
    while(True):
        ret, frame = cap.read()                        #讀取幀
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #灰度化展示(簡單對其進行處理)
        cv2.imshow('frame',gray)
        if cv2.waitKey(1) & 0xFF == ord('q'):          #按‘q’退出
            break
    #釋放資源並關閉窗口
    cap.release()
    cv2.destroyAllWindows()
'''讀取視頻'''
def CapFromVedio():
    cap = cv2.VideoCapture('xxx.mp4')
    while(cap.isOpened()):
        ret, frame = cap.read()
        cv2.imshow('frame',frame)
        if cv2.waitKey(50) & 0xFF == 27:				#按ESC退出
            break
    cap.release()
    cv2.destroyAllWindows()

3.畫線,畫圓,畫矩形,畫多邊形,顯示文字

關鍵函數:

  • 線:line()
  • 矩形:rectangle()
  • 圓:circle()
  • 多邊形:polylines()
  • 顯示文字:putText()
import cv2
import numpy as np
img=cv2.imread('fish.png',1)

# 從img的(1,1)位置,直線畫到(100,100)位置,顏色BGR爲(255,0,0),粗細爲5
cv2.line(img,(1,1),(100,100),color=(255,0,0),thickness=5)							'''1.畫線'''
cv2.rectangle(img,(10,9),(281,127),(0,255,0),5)										'''2.畫矩形'''

#圓的話只需要指定半徑和圓心
cv2.circle(img,(50,50),50,(0,0,255),5)												'''3.畫圓'''

#畫多邊形
pts=np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts=pts.reshape((-1,1,2))
cv2.polylines(img,[pts],True,(255,255,0),3)											'''4.多邊形'''

#寫字
cv2.putText(img,"Hello world",(100,100),cv2.FONT_HERSHEY_SIMPLEX,4,(255,0,255),3)	'''5.顯示文字'''

cv2.imshow('img',img)
cv2.waitKey(0)

4.框住並得到目標位置(獲取鼠標消息)

  • setMouseCallback():回調函數,第一個參數爲窗口名,需要自己設計;第二個參數爲自己寫的函數,在這裏我寫了一個可以對目標進行框定和位置獲取的函數。
import cv2
# 查看鼠標支持的操作
events=[i for i in dir(cv2) if 'EVENT'in i]
print(events)

img = cv2.imread('car.png')
cv2.namedWindow('image')

#畫筆
drawing_flag=True
s_x,s_y=0,0
def draw(event,x,y,flags,param):
    global s_x,s_y,drawing_flag,img,img_t
    if event==cv2.EVENT_MOUSEMOVE: #如果是:移動鼠標
        if drawing_flag==True:
            img = cv2.imread('car.png')
            cv2.line(img, (x, 0), (x, img.shape[1]), color=(0, 255, 0), thickness=1)
            cv2.line(img, (0, y), (img.shape[1], y), color=(0, 255, 0), thickness=1)

    if event==cv2.EVENT_LBUTTONDOWN:#如果是:按下左鍵
        s_x=x
        s_y=y
        print("第一個座標:"+str(x)+","+str(y))

    elif event==cv2.EVENT_MOUSEMOVE  and flags==cv2.EVENT_FLAG_LBUTTON:#如果是:移動同時左鍵按下
        img = cv2.imread('car.png')
        cv2.rectangle(img, (s_x, s_y), (x, y), (255, 0, 0), 3)

    elif event==cv2.EVENT_LBUTTONUP:#如果左鍵鬆開
        print("第二個座標:" + str(x) + "," + str(y))
        cv2.rectangle(img, (s_x, s_y), (x, y), (255, 0, 0), 3)
        drawing_flag=False
cv2.setMouseCallback('image',draw)

while(1):
    cv2.imshow('image',img)
    if cv2.waitKey(10)&0xff==ord('q'):
        break
cv2.destroyAllWindows()

在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

5.滑動條作調色板

  • createTrackbar():創建一個滑動條
  • getTrackbarPos():獲取滑動條的值
import cv2
import numpy as np

drawing_flag=True
s_x,s_y=0,0

def draw_circle_2(event,x,y,flags,param):
    global s_x,s_y,drawing_flag,img
    r = cv2.getTrackbarPos('R', 'image')
    g = cv2.getTrackbarPos('G', 'image')
    b = cv2.getTrackbarPos('B', 'image')
    color = [b, g, r]
    if event==cv2.EVENT_LBUTTONDOWN:#如果是:按下左鍵
        s_x=x
        s_y=y
    elif event==cv2.EVENT_MOUSEMOVE  and flags==cv2.EVENT_FLAG_LBUTTON:#如果是:移動同時左鍵按下
        if drawing_flag==True:
            None
    elif event==cv2.EVENT_LBUTTONUP:#如果左鍵鬆開
        drawing_flag=False
        cv2.rectangle(img, (s_x, s_y), (x, y), color, 3)
    elif event==cv2.EVENT_RBUTTONDOWN:
        img = np.ones((300, 500, 3), np.uint8)

def None1():
    pass

img = np.ones((300,500,3),np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('R','image',0,255,None1)
cv2.createTrackbar('G','image',0,255,None1)
cv2.createTrackbar('B','image',0,255,None1)
switch='off\non'
cv2.createTrackbar(switch,'image',0,1,None1)

cv2.setMouseCallback('image', draw_circle_2)

while(1):
    cv2.imshow('image',img)
    k=cv2.waitKey(1)&0xFF
    if k==27:
        break

cv2.destroyAllWindows()

在這裏插入圖片描述

6.圖像基礎操作:像素、屬性、ROI、通道、填充

  • 像素:直接對原圖數值進行更改
  • 屬性:size、dtype、shape
  • ROI:感興趣區域
  • 通道:img的第三維的數值
  • 填充:四周填充copyMakeBorder()
from cv2 import *
from matplotlib import pyplot as plt

img = imread('xxx.jpg',1)

# A.對老虎圖片像素進行修改
#print(img) 像素
img[140:150,200:270,0:3]=0
#img[:,:,:2]=0                  #使得圖像爲紅色
putText(img,"Hello World",(150,80),FONT_HERSHEY_SIMPLEX,2,(0,255,255),4)
imshow('img',img)

# B.獲取圖像屬性
print("像素總數:"+str(img.size)+"\n圖像數據類型:"+str(img.dtype)+"\n圖像大小"+str(img.shape))

# C.圖像ROI
eye = img[140:150,200:270,0:3]

# D.拆分及合併圖像通道
b=img[:,:,0]
g=img[:,:,1]
r=img[:,:,2]
#或
b_,g_,r_=split(img)
#img=merge(b_,g_,r_)

#E.圖像填充
BLUE=[255,0,0]
img1=imread('xxx.jpg')
replicate = copyMakeBorder(img1,10,10,10,10,BORDER_REPLICATE)
reflect = copyMakeBorder(img1,10,10,10,10,BORDER_REFLECT)
reflect101 = copyMakeBorder(img1,10,10,10,10,BORDER_REFLECT_101)
wrap = copyMakeBorder(img1,10,10,10,10,BORDER_WRAP)
constant= copyMakeBorder(img1,10,10,10,10,BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()

waitKey(0)

7.圖像運算:加法、混合

關鍵函數:

  • 相加:add()
  • 混合:addWeighted(),參數4和參數3表示參數3和參數1的混合比例
import cv2
import numpy as np
# 1.加法
img=np.zeros((500,500,1),np.uint8)
color = np.ones((500,500,1),np.uint8)
print(cv2.add(img,color))

# 2.混合
img1=cv2.imread('building01.jpg')
img = cv2.imread('xxx.jpg')
img  =cv2.resize(img,(384,288))
dst=cv2.addWeighted(img1,0.7,img,0.5,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)

8.性能檢測和優化

關鍵函數:

  • 獲取時間點:getTickCount()
  • 設置優化:setUseOptimized()
from cv2 import *

# 檢測時間
e1=getTickCount()
'''
Code
'''
e2=getTickCount()
time=(e2-e1)/getTickFrequency()
print(time)

# 檢測優化、開啓優化
print(useOptimized())
setUseOptimized(False)
print(useOptimized())
setUseOptimized(True)
print(useOptimized())

'''
優化建議:
1. 儘量避免使用循環,尤其雙層三層循環,它們天生就是非常慢的。
2. 算法中儘量使用向量操作,因爲 Numpy 和 OpenCV 都對向量操作進行
了優化。
3. 利用高速緩存一致性。
4. 沒有必要的話就不要複製數組。使用視圖來代替複製。數組複製是非常浪
費資源的。
'''

9.顏色空間轉換

關鍵函數:

  • 顏色空間轉換:cvtColor()
  • 判斷像素值是否在某區間:inrange()
import cv2

img = cv2.imread('xxx.png')
# 參數1:img_name	參數2:flag(還有其他類型的轉換)
cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)		#將BGR顏色空間轉換爲GRAY(灰度化)
# hsv,mask_1
lower_ = np.array([0, 0,100])
upper_ = np.array([120 , 50, 240])
hsv = cv2.cvtColor(final, cv2.COLOR_BGR2HSV)#轉換爲HSV
mask_1 = cv2.inRange(hsv, lower_, upper_)	#HSV在lower_到upper_的爲255,否則設置爲0

備註:可以利用這個方法,找到自己感興趣的物體,從而進行跟蹤

10.圖像幾何變換:擴展縮放、平移、旋轉、仿射變換、透視變換

關鍵函數:

  • 擴展縮放:resize()
  • 仿射變換:warpAffine()
  • 旋轉輔助函數:getRotationMatrix2D()
  • 透視變換:getPerspectiveTransform(),warpPerspective()
import cv2
import numpy as np
img = cv2.imread('xxx.jpg')


#縮放,推薦cv2.INTER_AREA,擴展推薦v2.INTER_CUBIC,cv2.INTER_LINEAR,默認cv2.INTER_LINEAR
'''resize函數'''
res=cv2.resize(img,None,fx=0.5,fy=0.5,interpolation=cv2.INTER_LINEAR)

#平移
'''warpAffine函數,接收2x3矩陣,前兩列固定,後兩列是平移長度'''
Mat = np.float32([[1,0,100],[0,1,50]])
res2=cv2.warpAffine(img,Mat,(300,300))

#旋轉
# 這裏的第一個參數爲旋轉中心,第二個爲旋轉角度,第三個爲旋轉後的縮放因子
# 可以通過設置旋轉中心,縮放因子,以及窗口大小來防止旋轉後超出邊界的問題
'''getRotationMatrix2D函數,接收3x3矩陣'''
rows,cols=img.shape[:2]
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,0.6)
res3=cv2.warpAffine(img,M,(300,300))

#仿射變換
'''getAffineTransform()函數,圖像前的三個點,圖像後的三個點,形成仿射變換'''
pts1=np.float32([[50,50],[150,50],[50,200]])
pts2=np.float32([[10,100],[50,50],[50,250]])
M1=cv2.getAffineTransform(pts1,pts2)
res4=cv2.warpAffine(img,M1,(cols,rows))

#透視變換
'''getPerspectiveTransform()函數,需要2個參數,圖像前4個點,圖像後4個點,一般用來矯正圖像'''
img2=cv2.imread('xxx.jpg')
res5=cv2.resize(img2,None,fx=0.2,fy=0.2)
rows,cols,ch=img2.shape
pts3 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts4 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M2=cv2.getPerspectiveTransform(pts3,pts4)
res5=cv2.warpPerspective(res5,M2,(800,800))

while(1):
    cv2.imshow('src', img)
    cv2.imshow('res1',res)
    cv2.imshow('res2',res2)
    cv2.imshow('res3',res3)
    cv2.imshow('res4',res4)
    cv2.imshow('res5',res5)
    if cv2.waitKey(1) & 0xFF==27:
        break

11.圖像二值化:簡單閾值,自適應閾值,Otsu閾值

關鍵函數:

  • 閾值分割:threshold()
  • 自適應閾值:adaptiveThreshold()
import cv2
img = cv2.imread('xxx.png',0)

# 簡單閾值
# 第四個參數可更改
ret,thread=cv2.threshold(img,126,245,cv2.THRESH_BINARY)
'''自適應閾值'''
img = cv2.medianBlur(img,5)
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
#11 爲 Block size, 2 爲 C 值
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY,11,2)
'''OTSU閾值'''
ret3,th3 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
while(1):
    cv2.imshow('src',img)
    cv2.imshow('img_th1',thread)
    cv2.imshow('img_th2',th2)
    cv2.imshow('img_th3',th3)
    if cv2.waitKey(1)& 0xFF==27:
        break

12.圖像平滑:平均、高斯、中值、雙邊濾波

關鍵函數:

  • 濾波:blur()
  • 高斯濾波:GaussianBlur()
  • 中值濾波:medianBlur()
  • 雙邊濾波:bilateralFilter()
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('xxx.jpg')

#均值
blur= cv2.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('src'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('blur'),plt.xticks([]),plt.yticks([])

#高斯
Gaussi=cv2.GaussianBlur(img,(5,5),0)
plt.subplot(122),plt.imshow(Gaussi),plt.title('Gaussian'),plt.xticks([]),plt.yticks([])

#中值濾波
median = cv2.medianBlur(img,5)
plt.subplot(122),plt.imshow(median),plt.title('median'),plt.xticks([]),plt.yticks([])

#雙邊濾波
bilateralFilter = cv2.bilateralFilter(img,9,75,75)
plt.subplot(122),plt.imshow(bilateralFilter),plt.title('bilateralFilter'),plt.xticks([]),plt.yticks([])

plt.show()

13.圖像形態學轉換

關鍵函數:

  • 腐蝕、膨脹、開閉、梯度、禮帽黑帽詳見代碼
import cv2
import numpy as np

img = cv2.imread('xxx.png',0)
kernel = np.ones((17,17),np.uint8)
# 腐蝕
test1 = cv2.erode(img,kernel=kernel)
# 膨脹
test2 = cv2.dilate(img,kernel=kernel)
# 開運算
test3 = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel=kernel)
# 閉運算
test4 = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel=kernel)
# 形態學梯度 膨脹-腐蝕
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# 禮帽 原始圖像與進行開運算之後得到的圖像的差。
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# 黑帽 進行閉運算之後得到的圖像與原始圖像的差
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
while(1):
    cv2.imshow('src',img)
    cv2.imshow('test1',test1)
    cv2.imshow('test2',test2)
    cv2.imshow('test3', test3)
    cv2.imshow('test4',test4)
    cv2.imshow('gradient',gradient)
    cv2.imshow('test6',tophat)
    cv2.imshow('test7',blackhat)
    if cv2.waitKey(0) & 0xFF==27:
        break

14.圖像梯度:各種算子

常見算子:

  • 拉普拉斯: Laplacian()
  • Sobel算子:Sobel()
  • Canny算子:Canny()
import cv2
img=cv2.imread('XT.png',0)
#cv2.CV_64F 輸出圖像的深度(數據類型),可以使用-1, 與原圖像保持一致 np.uint8
laplacian=cv2.Laplacian(img,cv2.CV_64F)
# 參數 1,0 爲只在 x 方向求一階導數,最大可以求 2 階導數。
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) # 參數 0,1 爲只在 y 方向求一階導數,最大可以求 2 階導數。
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
Canny = cv2.Canny(img,100,240)
while(1):
    cv2.imshow('src',img)
    cv2.imshow('laplacian',laplacian)
    cv2.imshow('sobelx',sobelx)
    cv2.imshow('sobely', sobely)
    cv2.imshow('Canny',Canny)
    if cv2.waitKey(0) & 0xFF==27:
        break

15.圖像金字塔

關鍵函數:

  • pyrDown()
  • pyrUp()
import cv2
img = cv2.imread('xxx.jpg')
lower_reso = cv2.pyrDown(img)
high_reso = cv2.pyrUp(lower_reso)
cv2.imshow('img',high_reso)
cv2.waitKey(0)

16.圖像輪廓

主要函數:

  • 找輪廓 findContours
  • 畫輪廓 drawContours
    其他:重心、周長、面積、輪廓近似、凸包、矩陣、最小外接圓、橢圓和直線擬合
from cv2 import *

img = imread('dog2.jpg',0)
imshow('img',img)

#繪製輪廓
ret,threah = threshold(img,127,255,0)
image, contours, hierarchy = findContours(threah,RETR_TREE,CHAIN_APPROX_NONE)
res= drawContours(img,contours,-1,(255,100,0),3)

imshow('threah',threah)
imshow('res',res)

cnt = contours[2]
M = moments(cnt)
#print(M)
#重心
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
# print(cx,cy)
#面積
area = contourArea(cnt)
# print(area)
#周長
perimeter = arcLength(cnt,True)
#print(perimeter)
#輪廓近似
epsilon = 0.1*arcLength(cnt,True)
approx = approxPolyDP(cnt,epsilon,True)
#凸包
hull = convexHull(cnt)
#凸性檢測
k = isContourConvex(cnt)#False說明不是凸性
#print(k)

#直矩陣
x,y,w,h = boundingRect(cnt)
img = rectangle(img,(x,y),(x+w,y+h),(100,255,0),3)
imshow('img_b',img)
#旋轉矩陣
x,y,w,h = boundingRect(cnt)
img = rectangle(img,(x,y),(x+w,y+h),(100,255,0),2)
#imshow('img_c',img)
#最小外接圓
(x,y),radius = minEnclosingCircle(cnt)
center = (int(x),int(y))#cv2.namedWindow('image')
radius = int(radius)
img = circle(img,center,radius,(100,240,0),2)
#imshow('img_r',img)
# 橢圓擬合
ellipse = fitEllipse(cnt)
img = ellipse(img,ellipse,(0,255,0),2)
# imshow('img_i',img)
#直線擬合
cols=img.shape[1]
[vx,vy,x,y] = fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
img = line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

#print(hull)
waitKey(0)

17.直方圖計算繪製、均衡化、反向投影、2D投影

關鍵函數:

  • 計算直方圖:calcHist()
  • 繪製直方圖(pyplot):hist()
  • 直方圖均衡化:equalizeHist()
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('xxx.jpg',0)
cv2.imshow('xxx',img)

'''1.計算直方圖'''
# 輸入表示:原圖、通道、Mask、BIN數目,範圍
'''返回的參數hist是一個1x256的一維數組'''
hist = cv2.calcHist([img],[0],None,[256],[0,256])
print(hist)
#或者是np中的histogram來進行直方圖的運算
#hist,bins = np.histogram(img.ravel(),256,[0,256])

'''2.繪製直方圖'''
#這裏可以使用matplotlib方式進行繪製,比較簡單
plt.hist(img.ravel(),256,[0,256])
plt.show()

'''小實驗A,繪製三通道彩色圖'''
img = cv2.imread('xxx.jpg')
bgr=['b','g','r']
for i,color in enumerate(bgr):
    hist = cv2.calcHist([img],[i],None,[256],[0,256])
    plt.plot(hist,color=color)
    plt.xlim([0,256])
cv2.imshow('img',img)
plt.show()

'''小實驗B,利用numpy進行掩膜運算得到直方圖'''
mask = np.zeros(img.shape[:2],np.uint8)
mask[100:200,300:400]=255
mask_img = cv2.bitwise_and(img,img,mask)
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(mask_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()

'''3.直方圖均衡化'''
# img_3= cv2.imread('xxx.jpg')
# hist , bins= np.histogram(img_3.flatten(),256,[0,256])#flagtten函數可以將img_3轉爲一維
# #計算累計直方圖
# cdf = hist.cumsum()
# cdf_normalized = cdf * hist.max()/ cdf.max()
# plt.plot(cdf_normalized, color = 'b')
# plt.hist(img.flatten(),256,[0,256], color = 'r')
# plt.xlim([0,256])
# plt.legend(('cdf','histogram'), loc = 'upper left')
# plt.show()
# # 構建 Numpy 掩模數組,cdf 爲原數組,當數組元素爲 0 時,掩蓋(計算時被忽略)。
# cdf_m = np.ma.masked_equal(cdf,0)
# cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
# # 對被掩蓋的元素賦值,這裏賦值爲 0
# cdf = np.ma.filled(cdf_m,0).astype('uint8')
# img_3_1=cdf[img_3]
img = cv2.imread('xxx.jpg',0)
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ))
cv2.imshow('res.png',res)

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
res2 = np.hstack((img,cl1))
cv2.imshow('res1.png',res2)

'''4.2D直方圖'''
#如果要繪製顏色直方圖,需要將圖像的顏色空間從BGR轉換到HSV
#計算以爲直方圖,要從BGR轉爲HSV
img = cv2.imread('xxx.jpg')
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#channels爲H、S兩個通道,H通道爲180,S通道爲256
#取值範圍H通道從0到180,S通道爲0到256
hist =  cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
#numpy中也有相關函數,histogram2d
#繪製直方圖
plt.imshow(hist,interpolation='nearest')
plt.show()

'''5.直方圖反向投影'''
# 直方圖反向投影經常與圖像分割密切聯繫
roi = cv2.imread('xxx_roi.png')
hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)
target = cv2.imread('xxx.jpg')
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)
roihist = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
# 歸一化:原始圖像,結果圖像,映射到結果圖像中的最小值,最大值,歸一化類型
#cv2.NORM_MINMAX 對數組的所有值進行轉化,使它們線性映射到最小值和最大值之間
# 歸一化之後的直方圖便於顯示,歸一化之後就成了 0 到 255 之間的數了。
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1) # Now convolute with circular disc
# 此處卷積可以把分散的點連在一起
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
dst=cv2.filter2D(dst,-1,disc)
# threshold and binary AND
ret,thresh = cv2.threshold(dst,50,255,0) # 別忘了是三通道圖像,因此這裏使用 merge 變成 3 通道
thresh = cv2.merge((thresh,thresh,thresh))
# 按位操作
res = cv2.bitwise_and(target,thresh)
res = np.hstack((target,thresh,res))
# 顯示圖像
cv2.imshow('1',res)
cv2.waitKey(0)

18.圖像變換:傅里葉變換

  • 快速傅里葉變換(np):fft()
  • 傅里葉變換(opencv):dft()
'''邊界和噪聲是圖像中的高頻分量'''
'''可以通過高頻分量的分佈來消除噪聲點等'''
'''振幅譜是一個波或波列的振幅隨頻率的變化關係'''
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('xxx.jpg',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 這裏構建振幅圖的公式沒學過
magnitude_spectrum = 20*np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
# 振幅譜
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

rows, cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)
print(crow,ccol)
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
# 取絕對值
img_back = np.abs(img_back)
plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(img_back, cmap = 'gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

#opencv中的傅里葉變換
img = cv2.imread('xxx.jpg',0)
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
# 高通濾波,如拉普拉斯算子
rows, cols = img.shape
crow,ccol = int(rows/2) , int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

19.圖像模板匹配

關鍵函數:

  • 模板匹配:matchTemplate()
import cv2
import numpy as np
from matplotlib import pyplot as plt

#單目標
img = cv2.imread('xxx.jpg',0)
img2 = img.copy()
template = cv2.imread('xxx_roi.png',0)
w, h = template.shape[::-1]
# 6中匹配的方式
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
for meth in methods:
    img = img2.copy()
    method = eval(meth)
    res = cv2.matchTemplate(img,template,method)
    #cv2.imshow('imshow',res)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    #print(min_val,max_val,min_loc,max_loc)
# 使用不同的比較方法,對結果的解釋不同
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)

    cv2.rectangle(img,top_left, bottom_right, 255, 2)
    plt.subplot(121),plt.imshow(res,cmap = 'gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(img,cmap = 'gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()

#多目標
img_rgb = cv2.imread('cut.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('3_.png',0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv2.imshow('res.png',img_rgb)
cv2.waitKey(0)

多目標匹配:掃雷中“3”的個數
在這裏插入圖片描述

20.Hough直線變換

關鍵函數:
HoughLines():詳見代碼

import cv2
import numpy as np
img = cv2.imread('xxx.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)

'''方式1'''
#第二、三個值是p和setae的精確度
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for i in range(0,lines.shape[0]):
    for rho,theta in lines[i]:
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
        cv2.imshow('houghlines.jpg',img)
        cv2.waitKey(0)

'''方式2'''
#Probabilistic Hough Transform局部化霍夫變換
img = cv2.imread('xxx.jpg')
#img = cv2.resize(img,None,fx=0.2,fy=0.2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
for i in range(0,lines.shape[0]):
    for x1,y1,x2,y2 in lines[i]:
        cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
        cv2.imshow('img',img)
        cv2.waitKey(0)

21.Hough 圓環變換

關鍵函數:
HoughCircles():詳見代碼

import cv2
import numpy as np
img = cv2.imread('circle.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
print(circles.shape)
for i in circles[0,:]:
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

22.GrabCut算法進行交互式前景提取

關鍵函數:
grabCut():詳見函數

import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('fish.png')
cv2.imshow('img',img)

mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (1,1,283,129) # 函數的返回值是更新的 mask, bgdModel, fgdModel
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
'''或者使用mask方法,這樣可以使之優化'''
cv2.waitKey(0)

原圖:
在這裏插入圖片描述
提取後:
在這裏插入圖片描述

23.角點檢測

關鍵函數:

  • 角點檢測:cornerHarris()
  • 獲得n個最佳角點:goodFeaturesToTrack()
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('xxx.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 輸入圖像必須是 float32,點大小,點偏離,
dst = cv2.cornerHarris(gray,2,3,0.05)
dst = cv2.dilate(dst,None)
img[dst>0.01*dst.max()]=[0,0,255]
cv2.imshow('dst',img)
cv2.waitKey(0)

#亞像素級精確度的角點

#得到N個最佳角點
img = cv2.imread('xxx.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#質量水平在0到1之間,4表示4個點
corners = cv2.goodFeaturesToTrack(gray,4,0.01,10) # 返回的結果是 [[ 311., 250.]] 兩層括號的數組。
print(corners)
corners = np.int0(corners)
print(corners)
for i in corners:
    x,y = i.ravel()
    cv2.circle(img,(x,y),3,255,-1)
plt.imshow(img)
plt.show()

在這裏插入圖片描述

24.SIFT算法

使用函數要版權,所以可能用不了,另外,SURF,FAST也是需要版權的,我們只需要知道它的大致原理,還有其使用場景,SIFT算法利用了尺度不變性來進行圖像關鍵點的提取,細節原理可參考其他資料

'''SIFT算法'''
import cv2
import numpy as np
# img = cv2.imread('rice.jpg')
# gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# sift = cv2.SIFT()
# kp = sift.detect(gray,None)
# img=cv2.drawKeypoints(gray,kp)
# cv2.imwrite('sift_keypoints.jpg',img)
'''
*****步驟******
尺度空間極值檢測
關鍵點(極值點)定位
爲關鍵點(極值點)指定方向參數 
關鍵點描述符
關鍵點匹配
**************
'''

25.ORB算法

ORB是開源的,另外,利用SIFT,ORB算法等一般進行特徵匹配

import cv2
from matplotlib import pyplot as plt
img = cv2.imread('XT.png',0)
# Initiate STAR detector
orb = cv2.ORB_create()
# find the keypoints with ORB
kp = orb.detect(img,None)
# compute the descriptors with ORB
kp, des = orb.compute(img, kp)
img2 = img.copy()
# draw only keypoints location,not size and orientation
img2 = cv2.drawKeypoints(img,kp,img2,color=(0,255,0), flags=0)
plt.imshow(img2),plt.show()

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章