三 OpenCV 圖像處理-1 空間顏色轉換/物體跟蹤/幾何變換/圖像閥值


本文內容:

  ·空間顏色轉換

  ·物體跟蹤

  ·幾何變換

  ·圖像閥值

 

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、物體跟蹤

           算法:

  1. 由於HSV的顏色空間比BGR空間更容易表示特定的顏色,故我們將BGR空間轉換成HSV,
  2. 然后設置HSV的閥值到指定的顏色范圍,
  3. 然后獲取到指定顏色范圍的物體,
  4. 達到物體追蹤目的,進行操作,如畫圈

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()

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM