圖像處理之opencv庫使用小結

        OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法(百度定義)。只要你接觸到圖像處理這塊,肯定會用到這個庫,詳情可查看https://opencv.org/,至於下載使用的話,在windows下可以藉助vs+OpenCV來實現,而在linux下直接pip install python-opencv即可。本文在這裏就常用的一些操作結合自己日常的使用進行如下總結:

(1)基本操作(讀取、保存、濾波、resize等常見操作)

       在日常的使用過程中,我們對圖像最基本的操作包括,讀取,裁剪,改變大小、濾波,保存修改等操作,具體操作代碼如下:

import os
import cv2

img=cv2.imread("path1")  ###path1表示讀取圖片路徑,第二個參數可以指定RGB還是灰度圖
img2=cv2.resize(img,(400,400)) ###改變大小
img3=img[50:300,50:300]  ###crop小圖
cv2.rectangle(img,(0,0),(100,100),(255,0,0),2) ###圖上畫框
cv2.putText(img,"panda",(100,200),cv2.FONT_HERSHEY_SIMPLEX,2,(0,255,0), 3)  ###圖上加文字標籤 參數(圖片,添加的文字,左上角座標,字體,字體大小,顏色,字體粗細)
img4=cv2.blur(img,(3,3))  ###均值濾波(blur),方框濾波(boxfilter),高斯濾波(Guassianblur),中值濾波(.medianBlur)
cv2.imwrite("dst.jpg",img)  ##保存圖片
cv2.imshow("1",img) ##顯示圖片
cv2.waitKey()

注意:

  • 圖片格式

由於利用cv2.imread()讀取圖片時,讀取的順序的GBR,這和常見的RGB有點區別,有時候會出現圖像顏色變綠等情況,與Image.open()方式不同,這時候需要將圖像的通道順序進行調整即可,常見的操作爲img=img.transpose((2,0,1))或img=img[...,-1::-1]。

  • 圖像金字塔

圖像金字塔指的是通過對圖像進行放大縮小形成一序列的圖像,如下圖所示,堆疊起來像一座金字塔,Opencv中可以通過函數cv2.pyrDown()和cv2.pyrUp()來構建金字塔,常用來實現對多尺度目標的檢測。

(2) 閾值化

       閾值化,即設定閾值,根據是否滿足閾值條件分別進行不同的處理,常見的就是對圖像進行二值化,OpenCV裏提供的方式有簡單閾值、自適應閾值、Otsu’s二值化等幾種。具體代碼如下

import os
import cv2
import matplotlib.pyplot as plt

img=cv2.imread(path1,0) ###以灰度圖的方式讀入path1的圖片
_,dst1=cv2.threshold(img,120,255,cv2.THRESH_BINARY)  ##以固定閾值進行二值化,當方法設爲cv2.THRESH_OTSU即爲otsu
dst2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2) ##自適應閾值二值化
dst=[img,dst1,dst2,dst3]
plt.figure()
for i in range(4):
    plt.subplot(1,4,i+1),plt.imshow(dst[i],'gray')
plt.show()

效果圖如下所示,依次是原圖灰度圖,固定閾值,自適應閾值,OTSU效果圖:

(3)形態學處理

        膨脹、腐蝕、開運算和閉運算是數學形態學的四個基本運算,是針對二值化圖像進行的,常見於mask的使用之中。基於這些運算還可推導和組合成各種數學形態學實用算法,用它們可以進行圖像形狀和結構的分析和處理,包括圖像分割、特徵提取、邊緣檢測、圖像濾波、圖像增強和恢復等。

  • 腐蝕:腐蝕會把物體的邊界腐蝕掉,卷積核沿着圖象滑動,如果卷積覈對應的原圖的所有像素值爲1,那麼中心元素就保持原來的值,否則變爲零。主要應用在去除白噪聲,也可以斷開連在一起的物體。
  • 膨脹:卷積核所對應的原圖像的像素值只要有一個是1,中心像素值就是1。一般在除噪是,先腐蝕再膨脹,因爲腐蝕在去除白噪聲的時候也會使圖像縮小,所以我們之後要進行膨脹。當然也可以用來將兩者物體分開。
  • 開運算:先腐蝕後膨脹,用於移除由圖像噪音形成的斑點。
  • 閉運算:先膨脹後腐蝕,用來連接被誤分爲許多小塊的對象;

具體操作代碼如下:

import cv2

src=cv2.imread("1.jpg",0)
_,img=cv2.threshold(src,120,255,cv2.THRESH_BINARY)
#OpenCV定義的結構矩形元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
eroded = cv2.erode(img,kernel)        #腐蝕圖像
dilated = cv2.dilate(img,kernel)      #膨脹圖像
closed1 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=1)    #閉運算1
closed2 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=3)    #閉運算2
opened1 = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=1)     #開運算1
opened2 = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=3)     #開運算2
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)             #梯度
plt.figure()
dst=[img,eroded,dilated,closed1,closed2,opened1,opened2,gradient]
for i in range(len(dst)):
    plt.subplot(2,4,i+1)
    plt.imshow(dst[i],'gray')
plt.show()

具體效果圖如下

(4)圖像變換檢測

邊緣檢測:

      想要提取圖像物體邊緣信息,OpenCV提供了封裝的邊緣提取算子,常見的有canny算子,sobel算子,Laplacian算子,scharr濾波器等。

import cv2

img=cv2.imread("1.jpg")
dst1=cv2.Canny(img,100,200) ##canny方法
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)  ##水平方向梯度
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)  ##垂直方向梯度
dst2=cv2.Laplacian(img,cv2.CV_64F)  ##laplacian方法
scharrx=cv2.Scharr(o,cv2.CV_64F,1,0)
scharrx=cv2.convertScaleAbs(scharrx) ##水平方向梯度
scharry=cv2.Scharr(o,cv2.CV_64F,0,1)
scharry=cv2.convertScaleAbs(scharry) ##垂直方向梯度
scharrxy=cv2.addWeighted(scharrx,0.5,scharry,0.5,0) ###融合水平和垂直方向信息

直線(圓)檢測:

        在數字圖像中,往往存在着一些特殊形狀的幾何圖形,像檢測馬路邊一條直線,檢測人眼的圓形等等,有時我們需要把這些特定圖形檢測出來,hough變換就是這樣一種檢測的工具。

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

img = cv2.imread('room.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度圖像 
edges = cv2.Canny(gray,50,200)
plt.subplot(121),plt.imshow(edges,'gray')
plt.xticks([]),plt.yticks([])

#hough transform
lines = cv2.HoughLinesP(edges,1,np.pi/180,30,minLineLength=60,maxLineGap=10)
lines1 = lines[:,0,:]#提取爲二維
for x1,y1,x2,y2 in lines1[:]: 
    cv2.line(img,(x1,y1),(x2,y2),(255,0,0),1)

plt.subplot(122),plt.imshow(img,)
plt.xticks([]),plt.yticks([])

效果圖,

è¿éåå¾çæè¿°

輪廓檢測:

      將圖像上的目標的輪廓用點將其描繪出來就是輪廓檢測,在OpenCV裏提供了findContours來實現這一功能。爲獲得更好的準確性,請使用二值圖,在找到輪廓之前,應用閾值法或canny邊緣檢測。具體操作如下:

# 輪廓檢測
import cv2
import numpy as np

img = np.zeros((200, 200), dtype=np.uint8)
img[50:150, 50:150] = 200
cv2.imshow("before", img)

ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow("thresh", thresh)

image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  ###找到輪廓

color = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
cv2.drawContours(color, contours, -1, (0, 255, 0), 2)  ##畫出輪廓
cv2.imshow("contours", color)
cv2.waitKey()
cv2.destroyAllWindows()

(5)特徵點檢測與匹配

        特徵點又稱興趣點、關鍵點,它是在圖像中突出且具有代表意義的一些點,通過這些點我們可以用來識別圖像、進行圖像配準、進行3D重建等,OpenCV提供了幾種常見的特徵點提取算法,

Harris角點:角點是圖像中最基本的一種關鍵點,它是由圖像中一些幾何結構的關節點構成,很多都是線條之間產生的交點。Harris角點是一類比較經典的角點類型,它的基本原理是計算圖像中每點與周圍點變化率的平均值。

FAST特徵點:harris特徵在算法複雜性上比較高,在大的複雜的目標識別或匹配應用上效率不能滿足要求,OpenCV提供了一個快速檢測角點的類FastFeatureDetector,而實際上FAST並不是快的意思,而是Features from Accelerated Segment Test,但這個算法效率確實比較高。

SIFT特徵:也叫尺度不變特徵變換算法,Sift特徵是圖像的局部特徵 對平移、旋轉、尺度縮放、亮度變化、遮擋和噪聲等具有良好的不變性,對視覺變化、仿射變換也保持一定程度的穩定性。獨特性好 信息量豐富,適用於在海量特徵數據庫中進行快速、準確的匹配。具有多量性;速度相對較快 ;可擴展性強 。

尺度不變的SURF特徵:surf特徵是類似於SIFT特徵的一種尺度不變的特徵點,它的優點在於比SIFT效率要高,在實際運算中可以達到實時性的要求。

       通過提取圖像特徵點,接下來可以利用特徵點對兩張圖像進行匹配,具體操作如下:

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

img1 = cv2.imread('xiaoyuanka.jpg',0)# queryImage
img2 = cv2.imread('xiaoyuanka_sence.jpg',0) # trainImage

# Initiate SIFT detector
sift = cv2.xfeatures2d.SIFT_create()   ###slam中用orb = cv2.ORB_create()


# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)# or pass empty dictionary

flann = cv2.FlannBasedMatcher(index_params,search_params)

matches = flann.knnMatch(des1,des2,k=2)

'''
####case 2
# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
'''

# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))]

# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):
    if m.distance < 0.7*n.distance:
        matchesMask[i]=[1,0]

draw_params = dict(matchColor = (0,255,0),
    singlePointColor = (255,0,0),
    matchesMask = matchesMask,
    flags = 0)

img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)
plt.imshow(img3),plt.show()
cv2.imshow('drawMatches',img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

匹配結果如下圖

png

補:

》OpenCV應用很廣,在對視頻處理抽幀時可以通過調用opencv的VideoCapture、imgwrite 來提取實現

import cv2
vc = cv2.VideoCapture('SampleVideo_1280x720_1mb.mp4')  # 讀入視頻文件
c=1
if vc.isOpened():  # 判斷是否正常打開
    rval, frame = vc.read()
else:
    rval = False
 
timeF = 5  # 視頻幀計數間隔頻率
 
while rval:
    # 循環讀取視頻幀
    rval, frame = vc.read()
    #gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    try:
        cv2.imshow('frame', frame)
    except:
        pass
    
    if (c % timeF == 0):  # 每隔timeF幀進行存儲操作    
            cv2.imwrite('crop/image' + str(c) + '.jpg', frame)  # 存儲爲圖像
    c = c + 1
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
vc.release()
cv2.destroyAllWindows()

(6)OpenCV之深度學習

       作爲一個常用的圖像處理庫,OpenCV可以嵌入到任何圖像處理的場景中,當然也包括人工智能這塊。這裏就目標跟蹤這一塊進行一個小小的總結,共八種基於OpenCV的目標跟蹤算法,

  • BOOSTING Tracker:和Haar cascades(AdaBoost)背後所用的機器學習算法相同,但是距其誕生已有十多年了。這一追蹤器速度較慢,並且表現不好,但是作爲元老還是有必要提及的。(最低支持OpenCV 3.0.0)
  • MIL Tracker:比上一個追蹤器更精確,但是失敗率比較高。(最低支持OpenCV 3.0.0)
  • KCF Tracker:比BOOSTING和MIL都快,但是在有遮擋的情況下表現不佳。(最低支持OpenCV 3.1.0)
  • CSRT Tracker:比KCF稍精確,但速度不如後者。(最低支持OpenCV 3.4.2)
  • MedianFlow Tracker:在報錯方面表現得很好,但是對於快速跳動或快速移動的物體,模型會失效。(最低支持OpenCV 3.0.0)
  • TLD Tracker:我不確定是不是OpenCV和TLD有什麼不兼容的問題,但是TLD的誤報非常多,所以不推薦。(最低支持OpenCV 3.0.0)
  • MOSSE Tracker:速度真心快,但是不如CSRT和KCF的準確率那麼高,如果追求速度選它準沒錯。(最低支持OpenCV 3.4.1)
  • GOTURN Tracker:這是OpenCV中唯一一深度學習爲基礎的目標檢測器。它需要額外的模型才能運行,本文不詳細講解。(最低支持OpenCV 3.2.0)

       個人建議如果追求高準確度,又能忍受慢一些的速度,那麼就用CSRT;如果對準確度的要求不苛刻,想追求速度,那麼就選KCF;純粹想節省時間就用MOSSE。

#pip3 install opencv-contrib-python
import numpy as np
import cv2
import sys
 
 
class TRACKER(object):
    def __init__(self):
        self.trackerTypes = ['BOOSTING', 'MIL', 'KCF','TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
        self.trackerNum=2
        self.tracker = cv2.MultiTracker_create()
 
    def createTrackerByName(self,num):
        # 通過跟蹤器的名字創建跟蹤器
        trackerType=self.trackerTypes[num]
        if trackerType == self.trackerTypes[0]:
            tracker = cv2.TrackerBoosting_create()
        elif trackerType == self.trackerTypes[1]: 
            tracker = cv2.TrackerMIL_create()
        elif trackerType == self.trackerTypes[2]:
            tracker = cv2.TrackerKCF_create()
        elif trackerType == self.trackerTypes[3]:
            tracker = cv2.TrackerTLD_create()
        elif trackerType == self.trackerTypes[4]:
            tracker = cv2.TrackerMedianFlow_create()
        elif trackerType == self.trackerTypes[5]:
            tracker = cv2.TrackerGOTURN_create()
        elif trackerType == self.trackerTypes[6]:
            tracker = cv2.TrackerMOSSE_create()
        elif trackerType == self.trackerTypes[7]:
            tracker = cv2.TrackerCSRT_create()
        else:
            tracker = None
            print('Incorrect tracker name')
            print('Available tracker name')
            
            for t in self.trackerTypes:
                print(t)
        return tracker
 
 
    def add(self,image, bbox):
        ok = self.tracker.add(self.createTrackerByName(self.trackerNum), image, bbox)
        return ok
 
    def clear(self,image,bbox):
        print(help(self.tracker.clear))
        print(help(self.tracker.empty))
        print(dir(self.tracker))
        ok = self.tracker.clear()
        ok = self.tracker.empty()
        return ok
 
    def update(self,image):
        ok, boxes = self.tracker.update(image)
        return ok,boxes
 
if __name__=="__main__":
    cv2.namedWindow("tracking")
    camera = cv2.VideoCapture("../siz.mp4")
 
 
    tracker = TRACKER()
 
 
 
 
    init_once = False
 
    ok, image=camera.read()
    if not ok:
        print('Failed to read video')
        exit()
 
    bbox1 = cv2.selectROI('tracking', image)
    bbox2 = cv2.selectROI('tracking', image)
 
    while camera.isOpened():
        ok, image=camera.read()
        if not ok:
            print ('no image to read')
            break
 
        if not init_once:
            ok = tracker.add( image, bbox1)
            ok = tracker.add( image, bbox2)
            init_once = True
 
        ok, boxes = tracker.update(image)
        print (ok, boxes)
 
        for newbox in boxes:
            p1 = (int(newbox[0]), int(newbox[1]))
            p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))
            cv2.rectangle(image, p1, p2, (255,0,0))
 
        cv2.imshow('tracking', image)
        k = cv2.waitKey(1)
        if k == 27 : 
            break # esc pressed

      未完待續!

 

參考鏈接:

https://blog.csdn.net/poem_qianmo(毛星雲博客)

https://blog.csdn.net/hjxu2016/article/details/77833336(利用cv2.findContours()函數來查找檢測物體的輪廓)

https://blog.csdn.net/weixin_41115751/article/details/84137783(繪圖函數)

https://blog.csdn.net/qq_35608277/article/details/89210194(計算任意區域形心)

https://blog.csdn.net/huayunhualuo/article/details/81478037(基於OpenCV的邊緣檢測)

https://blog.csdn.net/TingHW/article/details/84612624(python opencv 特徵匹配)

http://m.elecfans.com/article/722414.html(OpenCV上八種不同的目標追蹤算法)

https://blog.csdn.net/qq_14845119/article/details/92143957(opencv跟蹤)

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