本文內容:
·空間顏色轉換
·物體跟蹤
·幾何變換
·圖像閥值
1、顏色空間轉換
內容:顏色空間轉換(BGR<->Gray、BGR<->HSV)/獲取圖形中特定顏色的物體/
函數:cv2.cvtColor(input_img,flag):flag:轉換類型:cv2.COLOR_BGR2GRAY,cv2.COLOR_BGR2HSV等有261多種
import cv2 as cv import numpy as np #打印出所有的轉換類型 flags = [item for item in dir(cv) if 'COLOR_' in item] print(flags)
|
HSV:色度、飽和度、亮度
Gray:灰度圖
BGR:B/G/R三通道圖
·2、物體跟蹤
算法:
- 由於HSV的顏色空間比BGR空間更容易表示特定的顏色,故我們將BGR空間轉換成HSV,
- 然后設置HSV的閥值到指定的顏色范圍,
- 然后獲取到指定顏色范圍的物體,
- 達到物體追蹤目的,進行操作,如畫圈
import cv2 as cv import numpy as np
cap = cv.VideoCapture(0)#打開攝像頭
while(1):#循環追蹤每一幀 ret,frame = cap.read()#獲取一幀 hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV)#BGR->HSV #設定指定的顏色閥值:藍色/或者其他,你要追蹤的目標的顏色 lower_blue = np.array([110,50,50]) uper_blue = np.array([130,255,255]) #根據閥值構建掩摸 mask = cv.inRange(hsv,lower_blue,uper_blue) #對比原圖和掩模進行位運算 res = cv.bitwise_and(frame,frame,mask = mask) #顯示圖片
cv.namedWindow('IMG-FRAME') cv.imshow('IMG-FRAME', frame)
cv.namedWindow('IMG-MASK') cv.imshow('IMG-RES', mask)
cv.namedWindow('IMG-RES') cv.imshow('IMG-RES', res)
key = cv.waitKey(0)&0xff if key == 27:break
cv.destroyAllWindows()
|
###如果沒有攝像頭,直接對一張圖片進行對指定顏色進行跟蹤定位 import cv2 as cv import numpy as np
#cap = cv.VideoCapture(0)#打開攝像頭
#while(1):#循環追蹤每一幀
frame = cv.imread('E:\\fruits.jpg')#cap.read()獲取一幀
hsv = cv.cvtColor(frame,cv.COLOR_BGR2HSV)#BGR->HSV #設定指定的顏色閥值:藍色/或者其他,你要追蹤的目標的顏色 lower_blue = np.array([110,50,50]) uper_blue = np.array([130,255,255]) #根據閥值構建掩摸 mask = cv.inRange(hsv,lower_blue,uper_blue) #對比原圖和掩模進行位運算 res = cv.bitwise_and(frame,frame,mask = mask) #顯示圖片
cv.namedWindow('IMG-FRAME') cv.imshow('IMG-FRAME', frame)
cv.namedWindow('IMG-MASK') cv.imshow('IMG-RES', mask)
cv.namedWindow('IMG-RES') cv.imshow('IMG-RES', res)
key = cv.waitKey(0)&0xff if key == 27:input()
cv.destroyAllWindows() |
![]()
|
問題1:追蹤的目標仍有些噪音,應該優化消減噪音
問題2:如何找到我要跟蹤的目標的HSV值呢?
解決方法:將你的目標圖的BGR值,通過顏色空間轉換即可。例如綠色
import numpy as np import cv2 as cv ##green = np.uint8([0,255,0])###轉換失敗,因為數據類型不一致 green = np.uint8([[[0,255,0]]]) hsv_green = cv.cvtColor(green,cv.COLOR_BGR2HSV)#BGR->HSV print(hsv_green) |
·3、幾何變換 Geometric Image Transformations
參考http://opencv.jp/opencv-2.2_org/py/imgproc_geometric_image_transformations.html
原理:: \texttt{dst} \rightarrow \texttt{src}" v:shapes="_x0000_i1031">
內容:移動、旋轉、仿射、擴展放縮
函數:cv2.getPerspectiveTransform 透視轉換
cv2.warpAffine 變形-仿射 參數為2X3矩陣
cv2.warpPerspective 變形-透視 參數為3X3矩陣
cv2. getRotationMatrix2D 旋轉
·放縮
import numpy as np import cv2 as cv
img = cv.imread('E:\\fruits.jpg')
height,width = img.shape[:2]
res = cv.resize(img,(1*width,1*height),interpolation=cv.INTER_AREA)
cv.imshow('res',res) ##cv.imshow('img',img)
cv.waitKey(0) cv.destroyAllWindows() |
·平移
import numpy as np import cv2 as cv
img = cv.imread('E:\\fruits.jpg')
rows,cols = img.shape[:2] M = np.float32([[1,0,100],[0,1,50]]) dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst) cv.waitKey(0) cv.destroyAllWindows() |
·旋轉
import numpy as np import cv2 as cv
img = cv.imread('E:\\fruits.jpg')
rows,cols = img.shape[:2]
M = cv.getRotationMatrix2D((rows/2,cols/2),90,1)
dst = cv.warpAffine(img,M,(rows,cols))
cv.imshow('res',dst) ##cv.imshow('img',img)
cv.waitKey(0) cv.destroyAllWindows() |
·仿射變換warpAffine
對指定的三點,重新給出變形后的位置,得出新圖像,原理:T = M X 求出X后應用到整個圖片
可以平移、旋轉、放大縮小等變形操作,只要給出變形前的三點與變形后的三點即可
參考:http://blog.csdn.net/qq_18343569/article/details/47953505
import numpy as np import cv2 as cv from matplotlib import pyplot as plt
img = cv.imread('E:\\fruits.jpg') rows,cols = img.shape[:2]
pts1 = np.float32([[50,50],[200,50],[50,200]]) pts2 = np.float32([[10,10],[50,5],[10,200]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(rows,cols))
cv.imshow('res',dst) ##cv.imshow('img',img)
cv.waitKey(0) cv.destroyAllWindows() |
·透視變換 warpPerspective
投影映射
參考http://blog.csdn.net/qq_18343569/article/details/47953843
import numpy as np import cv2 as cv from matplotlib import pyplot as plt
img = cv.imread('E:\\fruits.jpg') rows,cols = img.shape[:2]
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]]) pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2) dst = cv.warpPerspective(img,M,(300,300))
cv.imshow('res',dst) ##cv.imshow('img',img)
cv.waitKey(0) cv.destroyAllWindows()
|
·4圖像閥值
分類:簡單圖像閥值、自適應閥值,Otsu’s二值化
作用:分割,找出不同的物體、目標
·簡單圖像閥值(thresh 削峰閥值)
類型:
API
Threshold(src, dst, threshold, maxValue, thresholdType) → None Applies a fixed-level threshold to array elements. Parameters: src (CvArr) – Source array (single-channel, 8-bit or 32-bit floating point) dst (CvArr) – Destination array; must be either the same type as src or 8-bit threshold (float) – Threshold value maxValue (float) – Maximum value to use with CV_THRESH_BINARY and CV_THRESH_BINARY_INV thresholding types thresholdType (int) – Thresholding type (see the discussion) |
·自適應閥值
不同部分具有不同的亮度,可以使用自適應閥值
Adapter-Mothod有:
-cv.ADAPTIVE_THRESH_MEAN_C:閥值取自相鄰域的平均值
-cv.ADAPTIVE_THRESH_GAUSSIAN_C:閥值取自相鄰域的加權和,權重為一個高斯窗口
API:
AdaptiveThreshold(src, dst, maxValue, adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=CV_THRESH_BINARY, blockSize=3, param1=5) → None Applies an adaptive threshold to an array. Parameters: src (CvArr) – Source image dst (CvArr) – Destination image maxValue (float) – Maximum value that is used with CV_THRESH_BINARY and CV_THRESH_BINARY_INV adaptive_method (int) – Adaptive thresholding algorithm to use: CV_ADAPTIVE_THRESH_MEAN_C or CV_ADAPTIVE_THRESH_GAUSSIAN_C (see the discussion) thresholdType (int) – Thresholding type; must be one of CV_THRESH_BINARY xxx CV_THRESH_BINARY_INV xxx blockSize (int) – The size of a pixel neighborhood that is used to calculate a threshold value for the pixel: 3, 5, 7, and so on param1 (float) – The method-dependent parameter. For the methods CV_ADAPTIVE_THRESH_MEAN_C and CV_ADAPTIVE_THRESH_GAUSSIAN_C it is a constant subtracted from the mean or weighted mean (see the discussion), though it may be negative |
代碼樣例
import cv2 as cv import numpy as np from matplotlib import pyplot as plt
img = cv.imread('E:\\fruits.jpg',0) ##Threshold(src, dst, threshold, maxValue, thresholdType) ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY) ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV) ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC) ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO) ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV) ##AdaptiveThreshold(src, dst, maxValue, adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=CV_THRESH_BINARY, blockSize=3, param1=5) thresh6 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2) thresh7 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)
titles = ['原圖','二值化','轉置二值化','截斷化','超過閥值置0化','低於閥值置0化','C-均值自適應閥值','高斯權重-自適應閥值'] imgs = [img,thresh1,thresh2,thresh3,thresh4,thresh5,thresh6,thresh7] ##使用PLT顯示 for i in range(len(imgs)): plt.subplot(3,3,i+1),plt.imshow(imgs[i],cmap = 'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([])#隱藏坐標
##解決中文不顯示問題 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False
plt.show() |
![]()
|
對應不同的thresh方法,可采樣不同的threshold值,但是,怎么樣選取threshold值呢?不同的值得到的不同結果,而那個才是好壞,就要不停去嘗試。如果一幅雙峰圖像,如何選擇其中一個峰作為閥值?這時候就需要Otus二值化來自動根據直方圖計算出一個閥值
·OTSU 二值化閥值
原理參考:http://www.tuicool.com/articles/uUJFN3f
根據權重方差均值等找到一個閥值T,即所謂的自動二值化閥值
算法源碼:
例子
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('E:\\fruits.jpg',0) # global thresholding ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) # Otsu's thresholding ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # Otsu's thresholding after Gaussian filtering #(5,5)為高斯核的大小,0 為標准差 blur = cv2.GaussianBlur(img,(5,5),0) # 閾值一定要設為 0! ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # plot all the images and their histograms images = [img, 0, th1, img, 0, th2, blur, 0, th3] titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)', 'Original Noisy Image','Histogram',"Otsu's Thresholding", 'Gaussian filtered Image','Histogram',"Otsu's Thresholding"] # 這里使用了 pyplot 中畫直方圖的方法,plt.hist, 要注意的是它的參數是一維數組 # 所以這里使用了(numpy)ravel 方法,將多維數組轉換成一維,也可以使用 flatten 方法 #ndarray.flat 1-D iterator over an array. #ndarray.flatten 1-D array copy of the elements of an array in row-major order. for i in range(3): plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray') plt.title(titles[i*3]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256) plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([]) plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray') plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([]) plt.show() |
![]()
|