主頁 > 移動端開發 > Opencv影像處理基礎

Opencv影像處理基礎

2020-10-03 16:43:26 移動端開發

文章目錄

          • 一、 圖片讀取
          • 二、 圖片切分
          • 三、 修改圖片
          • 四、 移動圖片
          • 五、 旋轉圖片
          • 六、 重塑圖片
          • 七、 畫圖
          • 八、翻轉
          • 九、 加減法
          • 十、位運算
            • 1. 與操作
            • 2. 或運算
            • 3. 取反
            • 4. 位運算對圖片進行遮擋
          • 十一、 切分合并通道
          • 十二、 影像金字塔
            • 1. 高斯金字塔
          • 十三、 腐蝕和膨脹
            • 1. 利用腐蝕去除白色的點
            • 2. 利用膨脹操作去除黑色的點
            • 3. Gradient形態學梯度
          • 十四、開閉運算
            • 1. 開運算
            • 2. 閉運算
          • 十五、 白帽和黑帽
            • 1. 白帽
            • 2. 黑帽
          • 十六、 影像平滑
            • 1. 平均平滑
            • 2. 高斯模糊
            • 3. 中值模糊
            • 4. 雙邊濾波
          • 十七、顏色空間轉換
            • 1. RGB
          • 十八、影像二值化
            • 1. 二值化處理:
            • 2. 自適應閾值
            • 3. 不同區域選取不同閾值
          • 十九、Canny邊緣檢測
          • 二十、讀取攝像頭資料
          • 二十一、讀取視頻檔案
          • 二十二、視頻寫入

一、 圖片讀取
import matplotlib.pyplot as plt
import cv2


def main():
    image = cv2.imread('1.jpg')
    print('height:{} pixels'.format(image.shape[0])) # 第0行為高
    print('width:{} pixels'.format(image.s hape[1])) # 第1行為寬
    print('channels:{} pixels'.format(image.shape[2])) # 第2行為通道數
    plt.imshow(image) # 讀入影像,進行處理
    plt.axis('off')
    plt.show()


if __name__ == '__main__':
    main()

在這里插入圖片描述
可以看到我們用 cv2.imread() 讀取的圖片和原圖顏色不一樣,原因在于 opencv 讀取的格式是 BGR 的格式,而 matplotlib 顯示的又是 RGB 的格式,所以根據代碼中的變數image的像素值以 RGB 格式顯示的和原圖有差別,

解決辦法:RB 的像素點的值對換

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
二、 圖片切分
	image = cv2.imread('2.jpg')
    h, w, c = image.shape
    lu = image[0:h//2, 0:w//2]  # 切取左上部分圖片
    ru = image[0:h//2, w//2:w]  # 切取右上部分圖片
    ld = image[h//2:h, 0:w//2]  # 切取左下部分圖片
    rd = image[h//2:h, w//2:w]  # 切取右下部分圖片
三、 修改圖片
image[0:h//2, 0:w//2] = (0, 0, 255) # RGB,左上部分改成藍色
show(image)

在這里插入圖片描述

四、 移動圖片
def show(image):
    plt.imshow(image)
    plt.axis('off')
    plt.show()


def image_read(path):
    image = cv2.imread(path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    return image


def main():
    image = image_read('1.jpg')
    h, w = image.shape[:2]
    # 水平方向向右平移250個像素,豎直方向向上平移500個像素
    M = np.float32([[1,0,250],[0,1,500]])
    shift_image = cv2.warpAffine(image, M, (w,h))
    show(shift_image)

在這里插入圖片描述

五、 旋轉圖片
	image = image_read('1.jpg')
    h, w = image.shape[:2]
    cX, cY = w//2, h//2
    # (cX,cY)表示旋轉中心點
    # 45表示逆時針旋轉角度
    # 0.5 表示縮放比例
    M = cv2.getRotationMatrix2D((cX,cY), 45, 0.5)
    image = cv2.warpAffine(image, M, (w,h))
    show(image) # 自定義函式,見上面代碼

在這里插入圖片描述

六、 重塑圖片
	image = image_read('1.jpg')
    width = image.shape[1]
    height = image.shape[0]
    image = cv2.resize(image, (width//10, height//10))  # 將像素點的數量變為原來的1/100
    show(image)

在這里插入圖片描述

很明顯,像素點減少后,圖片變得很模糊

def detectFace():
    image = image_read('huge.jpg')
    detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    rects = detector.detectMultiScale(image, scaleFactor=1.1, minNeighbors=3, minSize=(10, 10),flags=cv2.CASCADE_SCALE_IMAGE)
    # 畫出綠色的矩形框
    for (x, y, w, h) in rects:
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
    show(image)

在這里插入圖片描述

haarcascade_frontalface_default.xml

七、 畫圖

畫線和矩形

	image = np.zeros((400, 300, 3), dtype='uint8') # 一張全黑圖片
    w = image.shape[1]
    h = image.shape[0]
    cv2.line(image, (0, 0), (w, h), (0,255,0), 2)  # 綠色線
    cv2.line(image, (w, 0), (w//2, h//2), (0,0,255), 4)  # 藍色線
    cv2.rectangle(image, (10,10), (60,60), (255,0,0), 6) # 紅色矩形
    cv2.rectangle(image, (w//2, h//2), (w-50, h-50), (0,255,0), -1) # 填充綠色
    

在這里插入圖片描述
畫圓

	image = np.zeros((400, 400, 3), dtype='uint8') # 一張全黑圖片
    w = image.shape[1]
    h = image.shape[0]
    for r in range(0, w//2, 15):
        color = np.random.randint(0,255,size=(3,)).tolist()
        cv2.circle(image, (w//2, h//2), r, color, 2)
    show(image)

在這里插入圖片描述
填充

	image = np.zeros((400, 400, 3), dtype='uint8') # 一張全黑圖片
    w = image.shape[1]
    h = image.shape[0]
    for i in range(1, 10):
        color = np.random.randint(0,255,size=(3,)).tolist()  # 可以不是元組
        center = tuple(np.random.randint(0,255,size=(2,)))  # 必須是元組
        radius = np.random.randint(5, 200) # 半徑隨機
        cv2.circle(image, center, radius, color, -1)  # 圓心 半徑 顏色 填充
    show(image)

在這里插入圖片描述

八、翻轉
	image = cv2.flip(image, 1) # 1 表示水平翻轉
    image = cv2.flip(image, 0)  # 0 表示豎直翻轉
    image = cv2.flip(image, -1)  # -1 表示水平 + 垂直翻轉
九、 加減法
	 # 影像加法
    print(cv2.add(np.uint8([200]), np.uint8([100])))  # 300超過255就顯示255
    # 普通加法
    print(np.uint8([200]) + np.uint8([100]))  # 44 因為255 + 1 = 0
    # 影像減法
    print(cv2.subtract(np.uint8([100]), np.uint8([200])))  # -100小于0就顯示0
    # 普通減法
    print(np.uint8([100]) - np.uint8([200]))  # 156 ,因為256-100 = 156
	image = image_read('huge.jpg')
    M = np.ones(image.shape, dtype='uint8')*100  # 生成和圖片形狀相同的并且全為100的資料
    image = cv2.add(image, M)  # 像素值變大,偏白
    image = cv2.subtract(image, M)  # 像素值變小,偏黑

在這里插入圖片描述

十、位運算
	rectangle = np.zeros((300, 300, 3), dtype='uint8')
    cv2.rectangle(rectangle, (25,25), (275,275), (255,255,255), -1)  # 左上 右下 顏色 填充
    circle = np.zeros((300, 300, 3), dtype='uint8')
    cv2.circle(circle, (150, 150), 150 , (255, 255, 255), -1) # 圓心 半徑 顏色 填充(線寬) 

在這里插入圖片描述

1. 與操作
	image = cv2.bitwise_and(rectangle, circle)  # 有0結果就是0,有黑就是黑

在這里插入圖片描述

2. 或運算
	image = cv2.bitwise_or(rectangle, circle)  # 有1結果就是1,有白就是白

在這里插入圖片描述

image = cv2.bitwise_xor(rectangle, circle)  # 同0異1,白白或黑黑變黑,黑白變白  

在這里插入圖片描述

3. 取反
image = cv2.bitwise_not(circle)  

在這里插入圖片描述

4. 位運算對圖片進行遮擋
	image = image_read('huge.jpg')
    mask = np.zeros(image.shape, dtype='uint8')
    white = (255,255,255)
    cv2.circle(mask, (image.shape[1]//2, image.shape[0]//2-20), 100, white, -1) # 圓心,半徑,顏色,填充
    # 對原始圖片進行遮擋
    # 和白色區域與運算結果不變,和黑色區域與運算結果為黑色
    masked = cv2.bitwise_and(image, mask)
    show(masked)

在這里插入圖片描述

十一、 切分合并通道
	image = image_read('huge.jpg')
    print(image.shape)
    R, G, B = cv2.split(image)  # 拿到三個通道的資料
    print(R.shape, G.shape, B.shape)  # shape和圖片大小一樣 
    cv2.imshow('R', R)  # 單通道顯示,顯示的黑白顏色
    cv2.imshow('G', G)
    cv2.imshow('B', B)
    merged = cv2.merge([R,G,B])  # 三個通道合并后就是原圖
    show(merged)  # 顯示原圖
十二、 影像金字塔

影像金字塔是影像多尺度表達的一種,是一種以多解析度來解釋影像的有效但概念簡單的結構,一幅影像的金字塔是一系列以金字塔形狀排列的解析度逐步降低,且來源于同一張原始圖的影像集合,我們將一層一層的影像比喻成金字塔,層級越高,則影像越小,解析度越低,

在這里插入圖片描述

1. 高斯金字塔

高斯金字塔的頂部通過將底部影像中 連續的行和列去除 得到,頂部影像的每個像素值相當于下一層影像中5個像素的高斯加權平均值,操作一次就會將一個M*N 的影像變成一個M/2 * N/2的影像,影像面積變為原來的1/4,在python中我們通過函式 cv2.pyrDown()cv2.pyrUp() 構建影像金字塔

cv2.pyrDown() 對影像的向下取樣操作,即縮小影像

  • 對影像進行高斯內核卷積,進行高斯模糊;

  • 將所有偶數行和列去除,

cv2.pyrUp() 對影像的向上取樣,即放大影像

  • 將影像在每個方向擴大為原來的兩倍,新增的行和列以0填充

  • 使用先前同樣的內核(乘以4)與放大后的影像卷積,獲得 “新增像素”的近似值

	image = image_read('huge.jpg')
    print('原始大小:{}'.format(image.shape))
    for i in range(4):
        image = cv2.pyrDown(image)
        print(image.shape)
    show(image)

在這里插入圖片描述

在這里插入圖片描述
縮小為原圖的1/16 后,已經全部都是馬賽克了

十三、 腐蝕和膨脹

原理: 通過卷積的方式,在原圖的小區域內取得區域最小值,會使得一些黑色的點向外擴張,這個卷積核也叫結構元素,結構元素可以是矩形、橢圓、十字形,可用 c v 2. g e t S t r u c t u r i n g E l e m e n t ( ) cv2.getStructuringElement() cv2.getStructuringElement() 生成不同形狀的結構元素(卷積核)

	# 矩形卷積核
	rec_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))  
    # 橢圓卷積核
    ellipse_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
    # 十字形卷積核
    cross_kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5,5))
1. 利用腐蝕去除白色的點
	image = image_read('night.jpg')
	erosion = cv2.erode(image, rec_kernel)
    show(erosion)

在這里插入圖片描述

: 由于卷積核選取區域最小的像素值形成新的圖片,像素值減小了,整體顏色會偏暗,也會去除白色的點

2. 利用膨脹操作去除黑色的點
	dilation = cv2.dilate(image, rec_kernel)
    show(dilation)

在這里插入圖片描述

:因為膨脹操作是選取區域像素 最大的,故會把圖片整體變白,白色的點也會變成白色方塊

3. Gradient形態學梯度

膨脹圖 - 腐蝕圖,可提取物體輪廓

gradient = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, rec_kernel)
show(gradient)

在這里插入圖片描述

十四、開閉運算
1. 開運算

先腐蝕后膨脹,可去除圖片中的白點

opened = cv2.morphologyEx(image, cv2.MORPH_OPEN, rec_kernel)
2. 閉運算

先膨脹后腐蝕,可去除圖片中的黑點

closed = cv2.morphologyEx(image, cv2.MORPH_CLOSE, rec_kernel)
十五、 白帽和黑帽
1. 白帽

原圖 - 開運算,src - opened,可顯示被去掉的白色部分

	whiteHat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, rec_kernel)
    show(whiteHat)

在這里插入圖片描述

2. 黑帽

閉運算 - 原圖,closed - src,可顯示被去掉的黑色部分

	blackHat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, rec_kernel)
    show(blackHat)
十六、 影像平滑
1. 平均平滑

計算卷積框覆寫區域所有像素的平均值得到卷積的結果,此時的卷積核為N*N的矩陣

	image = image_read('lixian.jpg')
    kernel_sizes = [(3,3), (9,9), (15,15)]
    plt.figure(figsize=(15, 15))
    for i, kernel in enumerate(kernel_sizes):
        plt.subplot(1,3, i+1)
        blur = cv2.blur(image, kernel)  # 平均平滑,卷積視窗越大,圖片越模糊
        plt.axis('off')
        plt.title('Blurred' + str(kernel))
        plt.imshow(blur)
    plt.show()

在這里插入圖片描述

2. 高斯模糊

卷積核內的值是符合高斯分布的,方框中心的值最大,其余方框根據距離中心的距離遞減,構成一個高斯小山包,原來的 求平均數 現在變成 求加權平均數,權就是方框里的值

	image = image_read('lixian.jpg')
    kernel_sizes = [(3,3), (9,9), (15,15)]
    plt.figure(figsize=(15, 15))
    for i, kernel in enumerate(kernel_sizes):
        plt.subplot(1,3, i+1)
        blur = cv2.GaussianBlur(image, kernel, 0)  # 0是標準差
        plt.axis('off')
        plt.title('Blurred' + str(kernel))
        plt.imshow(blur)
    plt.show()

在這里插入圖片描述

3. 中值模糊

可對方框中的像素點取中值,會使得顏色鮮明的點被周圍顏色的點 “同化”

	image = image_read('night.jpg')
    kernel_sizes = (3,9,15)
    plt.figure(figsize=(15, 15))
    for i, kernel in enumerate(kernel_sizes):
        plt.subplot(1,3, i+1)
        blur = cv2.medianBlur(image, kernel) 
        plt.axis('off')
        plt.title('Blurred' + str(kernel))
        plt.imshow(blur)
    plt.show()

在這里插入圖片描述
可以看到,當卷積核比較大時,白色的點都被周圍的黑色 “同化” 了

4. 雙邊濾波

作用:能在保持邊界清晰的情況下有效去除噪音,

我們已經知道高斯濾波器是求中心點臨近區域像素的 高斯加權平均值 ,這種高斯濾波器 只考慮像素之間的空間關系 ,而不會考慮像素值之間的關系(像素的相似度),故這種方法會導致 邊界模糊 ,而這不是我們想要的,

雙邊濾波同時使用 高斯加權平均值灰度值相似性高斯權重

  1. 空間高斯函式確保只有臨近區域的像素對中心點有影響
  2. 灰度值相似性高斯函式確保只有 與中心像素灰度值相近的 才會用來做模糊運算

由于 邊界處灰度值變化比較大,所以這種方法不會使得邊界模糊,

	image = image_read('man.jpg')
    params = [(11,21,7), (11,41,21), (30,75,75)]
    plt.figure(figsize=(15, 15))
    # 鄰域直徑
    # 灰度值相似性高斯函式標準差
    # 空間高斯函式標準差
    for i, (diameter, sigmaColor, sigmaSpace) in enumerate(params):
        plt.subplot(1,3, i+1)
        blur = cv2.bilateralFilter(image, diameter, sigmaColor, sigmaSpace)
        plt.axis('off')
        plt.title('Blurred' + str((diameter, sigmaColor, sigmaSpace)))
        plt.imshow(blur)
    plt.show()
十七、顏色空間轉換
1. RGB
	image = image_read('lixian.jpg')
    (R, G, B) = cv2.split(image)
    zeros = np.zeros(image.shape[:2], dtype='uint8')
    for i in range(3):
        plt.subplot(1, 3, i + 1)
        plt.axis('off')
        if i == 0:
            plt.imshow(cv2.merge([R, zeros, zeros]))
        elif i == 1:
            plt.imshow(cv2.merge([zeros, G, zeros]))
        else:
            plt.imshow(cv2.merge([zeros, zeros, B]))
    plt.show()

在這里插入圖片描述

十八、影像二值化
  • 灰度值:影像灰度化就是讓像素點矩陣中的每一個像素點都滿足下面的關系:R=G=B,此時的這個值叫做 灰度值

  • 灰度圖:灰度圖只有一個通道,有256個灰度等級,255代表全白,0表示全黑,在python中 彩色 圖片每個像素點包含三個值(分別表示BGR三種顏色),而 灰度圖 每個像素點只有一個值

  • 二值化:就是讓影像的像素點矩陣中的每個像素點的灰度值為0(黑色)或者255(白色),也就是讓整個影像呈現只有黑和白的效果,在灰度化的影像中灰度值的范圍為0~255,在二值化后的影像中的灰度值范圍是0或者255

1. 二值化處理:
thresh, ret = cv2.threshold (src, thresh, maxval, type)
引數含義
thresh閾值,同形參
ret處理后的圖片
src源圖片,必須是單通道
thresh閾值,取值范圍0~255
maxval填充色,取值范圍0~255
type閾值型別
type含義
THRESH_BINARY二進制閾值化,非黑即白
THRESH_BINARY_INV反二進制閾值化,非白即黑
THRESH_TRUNC截斷閾值化 ,大于閾值設為閾值
THRESH_TOZERO閾值化為0 ,小于閾值設為0
THRESH_TOZERO_INV反閾值化為0 ,大于閾值設為0

在這里插入圖片描述

	image = image_read('coin.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)  # 轉成灰度圖
    thresh1, ret1 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)  # 進行二值化,127為閾值,255為最大值
    thresh2, ret2 = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)  # ret為圖片處理的結果,thresh為閾值
    thresh3, ret3 = cv2.threshold(gray, 200, 255, cv2.THRESH_TRUNC)
    thresh4, ret4 = cv2.threshold(gray, 200, 255, cv2.THRESH_TOZERO)
    thresh5, ret5 = cv2.threshold(gray, 200, 255, cv2.THRESH_TOZERO_INV)
    titles = ['gray', 'BINARY', 'BINARY_INV', 'TRUNC','TOZERO','TOZERO_INV']
    images = [gray, ret1, ret2, ret3, ret4, ret5]
    plt.figure(figsize=(15, 5))
    for i in range(len(images)):
        plt.subplot(2,3,i+1)
        plt.imshow(images[i], 'gray')
        plt.axis('off')
        plt.title(titles[i])
    plt.show()

在這里插入圖片描述

2. 自適應閾值
thresh1, ret1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 進行二值化,127為閾值,255為最大值
thresh2, ret2 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)

在這里插入圖片描述

3. 不同區域選取不同閾值
dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, BlockSize, C)
引數含義
dst輸出圖
src輸入圖,只能輸入單通道影像,通常來說為灰度圖
maxval當像素值超過了閾值(或者小于閾值,根據type來決定),所賦予的值
thresh_type閾值的計算方法,包含以下2種型別:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C
type二值化操作的型別,與固定閾值函式相同,包含以下5種型別: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV.
BlockSize鄰域大小,用于計算閾值區域的大小
C是一個常數,計算公式為【閾值 = 平均值(加權平均值)- C】
	image = image_read('license.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)  # 轉成灰度圖
    _, ret1 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # 普通二值化
    ret2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 3)  # 閾值取自相鄰區域的平均值
    ret3 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 3)  # 閾值取自相鄰區域的加權和,權重為一個高斯視窗
    titles = ['Origin', 'Global Threshold', 'Adaptive Mean Threshold', 'Adaptive Gaussian Threshold']
    images = [gray, ret1, ret2, ret3]
    plt.figure(figsize=(15, 5))
    for i in range(len(images)):
        plt.subplot(2,2,i+1)
        plt.imshow(images[i], 'gray')
        plt.axis('off')
        plt.title(titles[i])
    plt.show()

在這里插入圖片描述

  1. 原圖中由于左側較亮,像素值較大,普通二值化時直接將像素點的值置為255,故沒有保留下來
  2. 而自適應閾值可以根據圖片不同區域的亮度,對每個區域選取不同的閾值
十九、Canny邊緣檢測
  1. 噪聲去除:我們知道梯度算子可以用于增強影像,本質上是通過增強邊緣輪廓來實作的,也就是說是可以檢測到邊緣的,但是,它們受噪聲的影響都很大,那么,我們第一步要先去除噪聲,因為噪聲就是灰度變化很大的地方,所以容易被識別為偽邊緣

  2. 計算影像梯度:計算影像梯度能夠得到影像的邊緣,因為梯度是灰度變化明顯的地方,而邊緣也是灰度變化明顯的地方,當然這一步只能得到可能的邊緣,因為灰度變化的地方可能是邊緣,也可能不是邊緣,這一步就有了所有可能是邊緣的集合,

  3. 非極大值抑制:非極大值抑制,通常灰度變化的地方都比較集中,將區域范圍內的梯度方向上,灰度變化最大的保留下來,其它的不保留,這樣可以剔除掉一大部分的點,將有多個像素寬的邊緣變成一個單像素寬的邊緣,即“胖邊緣”變成“瘦邊緣”,如下所示:
    在這里插入圖片描述
    上圖中的數字代表了像素點的梯度強度,箭頭方向代表了梯度方向,以第二排第三個像素點為例,由于梯度方向向上,則將這一點的強度(7)與其上下兩個像素點的強度(5和4)比較,由于這一點強度最大,則保留,

  4. 雙閾值篩選:通過非極大值抑制后,仍然有很多的可能邊緣點,進一步的設定一個雙閾值,即低閾值(minVal),高閾值(maxVal),灰度變化大于maxVal的,設定為強邊緣像素,低于minVal的,剔除,在minVal和maxVal之間的設定為弱邊緣,進一步判斷,如果其領域內有強邊緣像素,保留,如果沒有,剔除,

在這里插入圖片描述

  • A 高于閾值 maxVal 所以是真正的邊界點
  • B 雖然低于 maxVal 但高于minVal 并且與 A 相連,所以也被認為是真正的邊界點
  • C 就會被拋棄,因為他不僅低于 maxVal 而且不與真正的邊界點相連
  • D 也會被拋棄,因為低于minVal

所以選擇合適的 maxVal和 minVal 對于能否得到好的結果非常重要,在這一步一些小的噪聲點也會被除去,因為我們假設邊界都是一些長的線段,

	image = image_read('coin.jpg')
    image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    image = cv2.GaussianBlur(image, (3, 3), 0)
    Value = [(10, 150), (100, 200), (180, 230)]
    plt.figure(figsize=(20, 5))
    for i, (minVal, maxVal) in enumerate(Value):
        plt.subplot(1, 3, i + 1)
        edges = cv2.Canny(image, minVal, maxVal)
        edges = cv2.GaussianBlur(edges, (3, 3), 0)  # 卷積核 標準差
        plt.imshow(edges, 'gray')
        plt.title('maxVal={}\nminVal={}'.format(maxVal, minVal))
        plt.axis('off')
    plt.show()

在這里插入圖片描述

二十、讀取攝像頭資料
  • cap.read() 回傳一個布林值(True/False),如果幀讀取的是正確的,就是 True,所以最后你可以通過檢查他的回傳值來查看視頻檔案是否已經到了結尾,有時 cap 可能不能成功的初始化攝像頭設備,這種情況下上面的代碼會報錯
  • cap.isOpened(),來檢查是否成功初始化了,如果回傳值是True,那就沒有問題
  • cap.get(propId) 來獲得視頻的一些引數資訊,這里propId 可以是 0 到 18 之間的任何整數,每一個數代表視頻的一個屬性

在這里插入圖片描述
其中的一些值可以使用 cap.set(propId,value) 來修改, value 就是你想要設定成的新值

例如,我可以使用 cap.get(3) 和 cap.get(4) 來查看每一幀的寬和高,默認情況下得到的值是 640X480,但是我們可以使用 ret=cap.set(3,320)和 ret=cap.set(4,240) 來把寬和高改成 320X240

	# 從攝像頭獲取影像資料
    cap = cv2.VideoCapture(0)
    # 查看是否成功獲取攝像頭
    if not cap.isOpened():
        exit('there is no camera exists')
    while (True):
        # ret 讀取成功True或失敗False
        # frame讀取到的影像的內容
        # 讀取一幀資料
        ret, frame = cap.read()
        # 將讀取的該幀轉為灰度圖
        # gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        cv2.imshow('frame', frame)
        # waitKey功能是不斷重繪影像,單位ms,回傳值是當前鍵盤按鍵值
        # ord回傳對應的ASCII數值
        if cv2.waitKey(1) == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
二十一、讀取視頻檔案
	# 從檔案讀取視頻內容
    cap = cv2.VideoCapture('cats.mp4')
    # 視頻每秒傳輸幀數
    fps = cap.get(cv2.CAP_PROP_FPS)
    # 視頻影像的寬度,get回傳float型別
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    # 視頻影像的長度
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    while (True):
        # ret 讀取成功True或失敗False
        # frame讀取到的影像的內容
        # 讀取一幀資料
        ret, frame = cap.read()
        if ret != True:
            break
        cv2.imshow('frame', frame)
        # waitKey功能是不斷重繪影像,單位ms,回傳值是當前鍵盤按鍵值
        # 如果waitkey的用于掩飾的引數太小,會導致視頻播放的很快,因為程式讀取一幀影像很快
        # ord回傳對應的ASCII數值
        if cv2.waitKey(25) == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
二十二、視頻寫入

我們要創建一個 VideoWriter 的物件,應該確定一個輸出檔案的名字,接下來指定 FourCC 編碼、播放頻率、幀的大小

FourCC 就是一個 4 位元組碼,用來確定視頻的編碼格式,可用的編碼一般為:DIVX, XVID, MJPG, X264, WMV1, WMV2

主要操作:讀取一幀,翻轉一幀,寫入一幀

	# 從檔案讀取視頻內容
    cap = cv2.VideoCapture('cats.mp4')
    # 視頻每秒傳輸幀數
    fps = cap.get(cv2.CAP_PROP_FPS)
    # 視頻影像的寬度
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    # 視頻影像的長度
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    # 寫入視頻的編碼方式
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    # 設定寫入視頻的編碼、每秒幀數、每一幀的長寬,回傳寫入物件
    out = cv2.VideoWriter('output.avi', fourcc, fps, (frame_width, frame_height))
    while True:
        ret, frame = cap.read()
        if ret is True:
            # 0:豎直翻轉,1:水平翻轉,-1:表示水平 + 垂直翻轉
            frame = cv2.flip(frame, 0)
            out.write(frame)
            cv2.imshow('frame', frame)
            if cv2.waitKey(1) == ord('q'):
                break
        else:
            break
    out.release()
    cap.release()
    cv2.destroyAllWindows()

這樣我們就完成了一個視頻的豎直翻轉

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/151953.html

標籤:其他

上一篇:七天學會JavaScript~Day1

下一篇:python 類關聯關系

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more