目錄
- 1.輸入、顯示和保存圖像
- 2.讀取、顯示、保存和處理視頻
- 3.畫線,畫圓,畫矩形,畫多邊形,顯示文字
- 4.框住並得到目標位置(獲取鼠標消息)
- 5.滑動條作調色板
- 6.圖像基礎操作:像素、屬性、ROI、通道、填充
- 7.圖像運算:加法、混合
- 8.性能檢測和優化
- 9.顏色空間轉換
- 10.圖像幾何變換:擴展縮放、平移、旋轉、仿射變換、透視變換
- 11.圖像二值化:簡單閾值,自適應閾值,Otsu閾值
- 12.圖像平滑:平均、高斯、中值、雙邊濾波
- 13.圖像形態學轉換
- 14.圖像梯度:各種算子
- 15.圖像金字塔
- 16.圖像輪廓
- 17.直方圖計算繪製、均衡化、反向投影、2D投影
- 18.圖像變換:傅里葉變換
- 19.圖像模板匹配
- 20.Hough直線變換
- 21.Hough 圓環變換
- 22.GrabCut算法進行交互式前景提取
- 23.角點檢測
- 24.SIFT算法
- 25.ORB算法
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()