與OpenCV的愛恨情仇

一. 配置opencv

1.最近在用Python學習OpenCV,因爲本人之前一直用的Pycharm編譯器,後來瞭解到了Anaconda這個神器,就通過Anaconda來下載各種安裝包,再和Pycharm連接就可以完成相應的配置。

2.Anaconda的NAVIGATOR軟件相當於圖形化操作界面,從直接的命令好操作轉化爲了圖形化操作,我新建了一個VirtualEnvironment虛擬環境,python版本設置的爲3.6(因爲好像opencv和python3.7不兼容),然後點擊Installed,將其選爲Uninstalled,再search Packages裏面尋找需要下載的安裝包就可以了。
在這裏插入圖片描述
3.下載好之後進入Pycharm,點擊Files,選擇settings,再Project Interpreter中選擇Add,再選擇Anaconda文件夾下的envs文件夾裏的python.exe
在這裏插入圖片描述
在這裏插入圖片描述
4.配置好之後輸入下面一段代碼進行測試:

import cv2

img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg", 1)

cv2.imshow("1", img)

cv2.waitKey()

得到如下結果
在這裏插入圖片描述

2.Opencv的一些模塊

1.【core】核心模塊
OpenCV基本數據結構
動態數據結構
繪圖函數
數組操作相關函數
輔助功能與系統函數和宏
與OpenGL的互操作

2.【imgproc】Imaging與Processing兩個單詞的縮寫的組合。圖像處理模塊。
線性和非線性的圖像濾波
圖像的幾何變換
其他(Miscellaneous)圖像轉換
直方圖相關
結構分析和形狀描述
運動分析和對象跟蹤
特徵檢測
目標檢測等內容

3.【features2d】2D功能框架
特徵檢測和描述
特徵檢測器(Feature Detectors)通用接口
描述符檢測器(Descriptor Extrators)通用接口
描述匹配器(Descriptor Matches)通用接口
通用描述符(Generic Descriptor)匹配器通用接口
關鍵點繪製函數和匹配功能繪製函數

4.【FLANN】—— Fast Library for Approximate Nearest Neighbors,高維的近似近鄰快速搜索算法庫,包含兩個部分:
快速近似最近鄰搜索
聚類

5.【gpu】——運用GPU加速的計算機視覺模塊

6.【legacy】——一些已經廢棄的代碼庫,保留下來作爲向下兼容,包含如下相關的內容:
運動分析
期望最大化
直方圖
平面細分(C API)
特徵檢測和描述(Feature Detection and Description)
描述符提取器(Descriptor Extractors)的通用接口
通用描述符(Generic Descriptor Matchers)的常用接口
匹配器

7.【ML】——Machine Learning,機器學習模塊, 基本上是統計模型和分類算法,包含如下內容:
統計模型 (Statistical Models)
一般貝葉斯分類器 (Normal Bayes Classifier)
K-近鄰 (K-NearestNeighbors)
支持向量機 (Support Vector Machines)
決策樹 (Decision Trees)
提升(Boosting)
梯度提高樹(Gradient Boosted Trees)
隨機樹 (Random Trees)
超隨機樹 (Extremely randomized trees)
期望最大化 (Expectation Maximization)
神經網絡 (Neural Networks)
MLData

8.【nonfree】,也就是一些具有專利的算法模塊 ,包含特徵檢測和GPU相關的內容。最好不要商用,可能會被告哦。其中SIFT特徵點的檢測和處理都在此模塊中。
9.【objdetect】——目標檢測模塊,包含Cascade Classification(級聯分類)和Latent SVM這兩個部分。

10.【ocl】——即OpenCL-accelerated Computer Vision,運用OpenCL加速的計算機視覺組件模塊

11.【photo】——也就是Computational Photography,包含圖像修復和圖像去噪兩部分

12.【stitching】——images stitching,圖像拼接模塊,包含如下部分:
拼接流水線
特點尋找和匹配圖像
估計旋轉
自動校準
圖片歪斜
接縫估測
曝光補償
圖片混合

13.【video】——視頻分析組件,該模塊包括運動估計,背景分離,對象跟蹤等視頻處理相關內容。

注:具體內容可參考以下文章:
https://blog.csdn.net/zmdsjtu/article/details/54924727

3.使用opencv讀寫圖像及視頻

A.理論基礎

參考文章:http://www.cnblogs.com/ivan-count/
https://blog.csdn.net/qq_18995069/article/details/82772944
https://blog.csdn.net/wsp_1138886114/article/details/84798977
一、Mat imread(const string& filename,int flags=1),用於讀取圖片
1、參數介紹
filename:載入的圖片的路徑名。支持如下類型文件的載入
JPEG文件 - *.jpeg, *.jpg, *.jpe
JPEG 2000文件- *.jp2
PNG圖片 - *.png
便攜文件格式- *.pbm, *.pgm, *.ppm
Sun rasters光柵文件 - *.sr, *.ras
TIFF 文件 - *.tiff, *.tif
Windows位圖 - .bmp,.dib
flags:int類型的flags,爲載入標識,它指定一個加載圖像的顏色類型。可以看到它自帶缺省值1.所以有時候這個參數在調用時我們可以忽略。如果在調用時忽略這個參數,就表示載入三通道的彩色圖像。
常用標誌符:
CV_LOAD_IMAGE_COLOR——等價取值爲1,將圖像轉化爲彩色
CV_LOAD_IMAGE_UNCHANGED——等價取值爲-1
CV_LOAD_IMAGE_GRAYSCALE——等價取值爲0,將圖像轉化爲灰度
CV_LOAD_IMAGE_ANYDEPTH——等價取值爲2,當載入圖像深度爲16位或32位,返回對應深度的圖像,否則轉化爲8位圖像返回
CV_LOAD_IMAGE_ANYCOLOR——等價取值爲4,無損的源圖像

當輸入有衝突時,採用較小數字值。CV_LOAD_IMAGE_COLOR|CV_LOAD_IMAGE_ANYCOLOR將載入三通道圖;CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR將載入最真實無損的源圖像。

若以數值表示,則:
flags>0返回一個3通道的彩色圖像
flags=0返回灰度圖像
flags<0返回包含Alpha通道的加載圖像

當以彩色載入時,通道順序爲BGR(藍、綠、紅),而非RGB。

二、void imshow(const string& winname,InputArray mat),用於顯示一副圖像
1、參數介紹
winname:const string&類型的winname,填需要顯示的窗口標識名稱。
mat:InputArray 類型的mat,填需要顯示的圖像。

2、注意事項
如果窗口用CV_WINDOW_AUTOSIZE(默認值)創建的,那麼imshow將顯示圖像原始大小,否則將進行縮放以適應窗口:

如果載入的圖像是8位無符號類型(8-bit unsigned),就顯示圖像本來的樣子。
如果圖像是16位無符號類型(16-bit unsigned)或32位整型(32-bit integer),便用像素值除以256。也就是說,值的範圍是[0,255 x 256]映射到[0,255]。
如果圖像是32位浮點型(32-bit floating-point),像素值便要乘以255。也就是說,該值的範圍是[0,1]映射到[0,255]。

三、void namedWindow(const string& winname, int flags=WINDOW_AUTOSIZE),用於創建窗口
1、參數介紹
name:const string&型的name,即填被用作窗口的標識符的窗口名稱。
flags:int 類型的flags ,窗口的標識,可以填如下的值:

WINDOW_NORMAL,可改變窗口大小
WINDOW_AUTOSIZE(值爲1),窗口大小會自動調整以適應所要顯示的圖像,且用戶無法手動調整
WINDOW_OPENGL 如果設置了這個值的話,窗口創建的時候便會支持OpenGL。

2、其他
一般情況下,該函數有默認值WINDOW_AUTOSIZE,一般情況下,這個函數我們填一個變量就行了。
namedWindow函數的作用是,通過指定的名字,創建一個可以作爲圖像和進度條的容器窗口。如果具有相同名稱的窗口已經存在,則函數不做任何事情。

可以自行手動關閉窗口並釋放空間:destroyWindow()或destroyAllWindows()。但是程序退出時,所有窗口將被系統自動關閉。

四、bool imwrite(const string& filename, InputArray img,const vector&params=vector()),用於輸出圖像到文件
1、參數介紹
filename:const string&類型的filename,填寫要寫入的文件名,需帶上後綴,即文件類型名。
img:InputArray類型的img,需要輸出的圖像,一般爲Mat類型。
params:const vector&類型的params,表示爲特定格式保存的參數編碼,它有默認值vector(),所以一般情況下不需要填寫。

對於JPEG格式,參數從0到100,表示圖片質量(CV_IMWRITE_JPEG_QUALITY)
對於PNG格式,表示壓縮級別(CV_IMWRITE_PNG_COMPRESSION)從0~9.較高的值意味着更小的尺寸和更長的壓縮時間,默認爲3.
對於PPM、PGM或PBM格式,表示一個二進制格式標識(CV_IMWRITE_PXM_BINARY),取值爲0或1,默認爲1.

五.OpenCV提供的接口VideoCapture,用於視頻的讀取

  • < VideoCaputrue object > = cv2.VideoCapture(filename)------功能:打開視頻文件,參數filename:視頻文件名。
  • < VideoCaputrue object > = cv2.VideoCapture(index)------功能:打開相機設備,參數index:相機設備ID,當只有一個相機時,給0即可。
  • retval =cv2.VideoCapture. isOpened()------功能:判斷視頻捕獲是否初始化成功。初始化成功返回true。之前調用過VideoCapture的構造函數或者VideoCapture::open()函數成功,就會返回true。
  • retval=cv2.VideoCapture.open(filename)/cv2.VideoCapture.open(index)------功能:打開視頻文件或者相機設備進行視頻捕獲。
  • retval = cv2.VideoCapture.get(propId)------功能:得到相機/視頻文件的各種屬性。propId常見取值如下:
cv2.CAP_PROP_POS_MSEC:視頻文件的當前位置(ms)

cv2.CAP_PROP_POS_FRAMES:從0開始索引幀,幀位置。

cv2.CAP_PROP_POS_AVI_RATIO:視頻文件的相對位置(0表示開始,1表示結束)

cv2.CAP_PROP_FRAME_WIDTH:視頻流的幀寬度。

cv2.CAP_PROP_FRAME_HEIGHT:視頻流的幀高度。

cv2.CAP_PROP_FPS:幀率

cv2.CAP_PROP_FOURCC:編解碼器四字符代碼

cv2.CAP_PROP_FRAME_COUNT:視頻文件的幀數

cv2.CAP_PROP_FORMAT: retrieve()返回的Mat對象的格式。

cv2.CAP_PROP_MODE:後端專用的值,指示當前捕獲模式

cv2.CAP_PROP_BRIGHTNESS:圖像的亮度,僅適用於支持的相機

cv2.CAP_PROP_CONTRAST:圖像對比度,僅適用於相機

cv2.CAP_PROP_SATURATION:圖像飽和度,僅適用於相機

cv2.CAP_PROP_HUE:圖像色調,僅適用於相機

cv2.CAP_PROP_GAIN:圖像增益,僅適用於支持的相機

cv2.CAP_PROP_EXPOSURE:曝光,僅適用於支持的相機

cv2.CAP_PROP_CONVERT_RGB:布爾標誌,指示是否應將圖像轉換爲RGB。
  • retval = cv2.VideoCapture.set(propId,value)------功能:設置屬性,第一個參數是選擇屬性類型,第二個參數是值。其中一些值可以使用 cap.set(propId,value) 進行修改,value是修改後的值。
    例如:通過cap.get(3)和cap.get(4)來檢查幀的寬度和高度,默認的值是640x480。現修改爲320x240,使用ret = cap.set(3, 320)和ret = cap.set(4, 240)。
  • retval,image= cv2.VideoCapture.read([,image])-------功能:抓取,解碼並返回下一個視頻幀。返回值爲true表明抓取成功。該函數是組合了grab()和retrieve(),這是最方便的方法。如果沒有幀,該函數返回false,並輸出空圖像。
  • retval, image = cv2.VideoCapture.retrieve([, image[, flag]])-------功能:解碼並返回抓取的視頻幀。
  • retval = cv2.VideoCapture.grab()------功能:從視頻文件或相機中抓取下一幀。true爲抓取成功。該函數主要用於多攝像頭時。
  • none = cv2.VideoCapture.release()------功能:關閉視頻文件或相機設備

六.OpenCV提供的接口VideoWriter,用於視頻的保存

  • < VideoWriter object > = cv.VideoWriter( filename, fourcc, fps, frameSize[, isColor] )
    參數:
    filename:給要保存的視頻起個名字
    fourcc:指定視頻編解碼器的4字節代碼
    fps:幀率
    frameSize:幀大小
    isColor:如果爲true,則視頻爲彩色,否則爲灰度視頻,默認爲true

B.實現示例

1.opencv讀取圖像

import cv2
# 讀取這個路徑的圖片,注意這裏的路徑必須全是英文,不能有中文
img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg")

# namedWindow函數,用於創建一個窗口,默認值爲WINDOW_AUTOSIZE,一般輸入情況我們只需要輸入第一個變量
# 其實這一行代碼沒有也可以正常顯示的(下面imshow會顯示)
cv2.namedWindow("Cat")

# 在指定的窗口中顯示一幅圖像
# 若同時使用namedWindow和imshow函數,則兩個函數的第一個參數名字必須相同。
cv2.imshow("Cat", img)

# 參數=0: (也可以是小於0的數值)一直顯示,不會有返回值,若在鍵盤上按下一個鍵即會消失 ,則會返回一個按鍵對應的ascii碼值
# 參數>0:顯示多少毫秒,超過這個指定時間則返回-1
cv2.waitKey(0)

# 刪除建立的全部窗口,釋放資源
cv2.destroyAllWindows()

2.opencv打印圖片屬性並另存

import cv2
import numpy as np

# 輸出圖片屬性

def get_image_info(image):  # 定義一個函數來輸出圖片的一些屬性

    print(type(image))  # 顯示圖片類型 numpy類型的數組

    # 圖像矩陣的shape屬性表示圖像的大小,shape會返回tuple元組,
    # 第一個元素表示矩陣行數,第二個元組表示矩陣列數,第三個元素是3,表示像素值由光的三原色組成

    print(image.shape)

    print(image.size)  # 圖像大小

    print(image.dtype)  # 圖像類型

    pixel_data = np.array(image)

    print(pixel_data)  # 圖片矩陣

img = cv2.imread("C:\\Users\\Tony.Hsu\\Desktop\\cat.jpg")

cv2.namedWindow("cat1", cv2.WINDOW_NORMAL)

cv2.imshow("cat1", img)

get_image_info(img)

cv2.imwrite("C:\\Users\\Tony.Hsu\\Desktop\\cat1.jpg", img)  # 圖片另存爲其他地址,不要存到c盤,要權限

cv2.waitKey(0)

cv2.destroyAllWindows()

3.opencv讀取視頻

A.從攝像頭中獲取視頻
創建一個VideoCapture對象。它的參數可以是設備索引或視頻文件的名稱(下面會講到)。設備索引只是指定哪臺攝像機的號碼。0代表第一臺攝像機、1代表第二臺攝像機。之後,可以逐幀捕捉視頻。最後釋放捕獲。

import cv2

# 獲取攝像頭0(本電腦攝像頭)
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()

B.讀取視頻文件
從文件中播放視頻,更改相機索引與視頻文件名。 在顯示幀時,選擇適當的cv2.waitKey()時間,如果該值太小,視頻會非常快,如果它太大,視頻會很慢(這可以用來慢動作顯示視頻)。 正常情況下,25-50毫秒即可。

import cv2

cap = cv2.VideoCapture('C:\\Users\\Tony.Hsu\\Pictures\\Camera Roll\\1.mp4')

while cap.isOpened():
    ret, frame = cap.read()
    cv2.imshow('frame', frame)
    if cv2.waitKey(50) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

4.opencv視頻文件的保存

要想保存視頻,首先是進行捕獲視頻,本次實現保存相機中捕獲的視頻。將視頻保存,思路是首先創建VideoWriter類對象,需要指定一些參數,在windows下fourcc取值爲DIVX,幀率一般給20,幀大小一般給640*480,創建對象後,採用write()函數保存幀,保存完後記得關閉VideoWriter類對象。

# cv2.VideoWriter_fourcc("I", "4", "2", "0")  .avi的未壓縮的YUV顏色編碼,文件較大
# cv2.VideoWriter_fourcc("P", "I", "M", "1")  .avi的MPEG-1編碼類型
# cv2.VideoWriter_fourcc("X", "V", "I", "D")  .avi的MPEG-4編碼類型
# cv2.VideoWriter_fourcc("T", "H", "E", "O")  .ogv的Ogg Vorbis
# cv2.VideoWriter_fourcc("F", "L", "V", "1")  .flv的flash視頻

import cv2

cap = cv2.VideoCapture(0)               # 打開相機

# 創建VideoWriter類對象,
# 生成的視頻格式設置爲.avi(OpenCV只支持avi的格式,而且生成的視頻文件不能大於2GB,而且不能添加音頻)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# cv2.VideoWriter(視頻名, 格式, 碼率(fps), 幀的尺寸等參數)
out = cv2.VideoWriter('C:\\Users\\Tony.Hsu\\Desktop\\output.avi', fourcc, 20.0, (640, 480))

while cap.isOpened():
    ret, frame = cap.read()             # 捕獲一幀圖像
    if ret:                             # Python推薦簡化此表達式 if ret == True:
        frame = cv2.flip(frame, 0)      # 沿x軸翻轉,進行圖像翻轉, 1水平翻轉、 0垂直翻轉、-1水平垂直翻轉
        out.write(frame)                # 保存幀

        cv2.imshow('frame', frame)       # 顯示幀
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

cap.release()  # 關閉相機
out.release()
cv2.destroyAllWindows()

該行代碼fourcc = cv2.VideoWriter_fourcc(* ’XVID’)可以改爲fourcc = cv2.VideoWriter_fourcc(’X’,’V’,’I’,’D’),二者是等效的

4.計算總幀數

import cv2

video_cap = cv2.VideoCapture('C:\\Users\\Tony.Hsu\\Desktop\\output.avi')

frame_count = 0

all_frames = []

while True:

    ret, frame = video_cap.read()

    if ret is False:
        break

    all_frames.append(frame)

    frame_count = frame_count + 1

# The value below are both the number of frames

print(frame_count)

print(len(all_frames))

5.讀取FPS

import cv2

if __name__ == '__main__':

    video = cv2.VideoCapture("C:\\Users\\Tony.Hsu\\Desktop\\output.avi")

    # Find OpenCV version

    (major_ver, minor_ver, subminor_ver) = cv2.__version__.split('.')

    if int(major_ver) < 3:

        fps = video.get(cv2.cv.CV_CAP_PROP_FPS)

        print("Frames per second using video.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))

    else:

        fps = video.get(cv2.CAP_PROP_FPS)

        print("Frames per second using video.get(cv2.CAP_PROP_FPS) : {0}".format(fps))

    video.release()

整體代碼:

import cv2


def read_video(file_path):
    video_cap = cv2.VideoCapture(file_path)

    ### 獲取視頻的幀數 ###

    video_frameNum = 0

    # all_frames = []

    while (True):

        ret, frame = video_cap.read()

        if ret is False:
            break

        # all_frames.append(frame)

        video_frameNum = video_frameNum + 1

    ### 獲取視頻的FPS ###

    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')  # Find OpenCV version

    if int(major_ver) < 3:

        video_FPS = video_cap.get(cv2.cv.CV_CAP_PROP_FPS)

    # print("Frames per second using video_cap.get(cv2.cv.CV_CAP_PROP_FPS): {0}".format(fps))

    else:

        video_FPS = video_cap.get(cv2.CAP_PROP_FPS)

    # print("Frames per second using video_cap.get(cv2.CAP_PROP_FPS) : {0}".format(fps))

    video_cap.release()

    return video_frameNum, video_FPS


video_path = 'C:\\Users\\Tony.Hsu\\Desktop\\output.avi'

video_frameNum, video_FPS = read_video(video_path)  # 獲取視頻幀數

print(video_frameNum)

print(video_FPS)

參考博客:https://blog.csdn.net/yyy430/article/details/87866603

發佈了24 篇原創文章 · 獲贊 6 · 訪問量 3694
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章