OpenCV —— 圖像基本操作

前文

OpenCV —— 概述與環境搭建

使用 Maplotlib 集合 Numpy 繪製 2D 圖形

加載圖像

  • imread 功能是加載圖像文件成爲一個 Mat 對象,其中第一個參數表示圖像文件名稱,第二個參數表示加載的圖像是什麼類型,支持常見的三個參數值
  • IMREAD_UNCHANDED(<0) 表示加載原圖,不做任何改變
  • IMREAD_GRAYSCALE(0) 表示吧原圖作爲灰度圖像加載進來
  • IMREAD_COLOR(>0) 表示把原圖作爲 RGB 圖像加載進來

注意:OpenCV 支持 JPG、PNG、TIFF 等常見格式圖像文件加載(默認讀取的格式是 BGR)

# 導入 OpenCV 庫
import cv2 as cv

# 加載圖像
img = cv.imread("./1.jpg")
# 打印圖像類型
print(type(img))
print(img)

輸出:
在這裏插入圖片描述
可以發現這是個 numpy 數據類型的,而且是三個維度的,比如 [H,W,C]

圖像顯示

# 導入 OpenCV 庫
import cv2 as cv

# 加載圖像
img = cv.imread("./1.jpg")

# 圖像的顯示,也可以創建多個窗口
cv.imshow("image",img)

# 等待時間,毫秒級,0 表示任意鍵終止
cv.waitKey(0)
cv.destroyAllWindows()

輸出:(按下任意鍵關閉該窗口)
在這裏插入圖片描述

數據讀取 - 圖像

# 導入 OpenCV 庫
import cv2 as cv

# 灰色顯示
img = cv.imread("./1.jpg",cv.IMREAD_GRAYSCALE)

# 打印信息
print(img)

輸出:
在這裏插入圖片描述
這裏打印的結果就不像上面那樣有三個維度了,因爲是灰色的,也就是沒有彩色的,所以這裏表示的只有 H 和 W


當然,這裏的代碼只是打印信息而已,還不能顯示到窗口,顯示到窗口還需要增加幾句代碼,如下:

# 導入 OpenCV 庫
import cv2 as cv

img = cv.imread("./1.jpg",cv.IMREAD_GRAYSCALE)
cv.imshow("image",img)
cv.waitKey(0)
cv.destroyAllWindows()

輸出:(可以發現,圖片是以灰色顯示了的)
在這裏插入圖片描述

截取部分圖像數據

# 導入 OpenCV 庫
import cv2 as cv

# 加載圖像
img = cv.imread("./1.jpg",)

# 截取部分圖像
cat = img[0:200, 0:200]

# 顯示截取的圖像
cv.imshow("cat",cat)
cv.waitKey(0)
cv.destroyAllWindows()

輸出
在這裏插入圖片描述

顏色通道提取

通過 cv2 的 split() 方法可以進行顏色的通道提取

# 導入 OpenCV 庫
import cv2 as cv

img = cv.imread("./1.jpg",)
b,g,r = cv.split(img)

print(b)

輸出:
在這裏插入圖片描述

只保留 R

上面說過 OpenCV 默認讀取的格式是 BGR

# 導入 OpenCV 庫
import cv2 as cv

img = cv.imread("./1.jpg",)
cur_img = img.copy()

# 注意參數的變化
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv.imshow('R',cur_img)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述
R 是 Red 的縮寫,這裏顯示的是紅色

只保留 G

# 導入 OpenCV 庫
import cv2 as cv

img = cv.imread("./1.jpg",)
cur_img = img.copy()

# 注意參數的變化
cur_img[:,:,0] = 0
cur_img[:,:,2] = 0
cv.imshow('G',cur_img)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述
G 是 Green 的縮寫,這裏顯示的是綠色

只保留 B

# 導入 OpenCV 庫
import cv2 as cv

img = cv.imread("./1.jpg",)
cur_img = img.copy()

# 注意參數的變化
cur_img[:,:,1] = 0
cur_img[:,:,2] = 0
cv.imshow('B',cur_img)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述
B 是 Blue 的縮寫,這裏顯示的是藍色

邊界填充

# 導入 OpenCV 庫
import cv2 as cv
# 導入 maplotlib
import matplotlib.pyplot as plt

img = cv.imread("./1.jpg",)

# 定義圖片顯示大小
top_size,buttom_size,left_size,right_size = (50,50,50,50)

# 複製法,也就是複製最邊緣像素
replicate = cv.copyMakeBorder(img,top_size,buttom_size,left_size,right_size,borderType=cv.BORDER_REPLICATE)

# 反射法,對感興趣的圖像中的像素在兩邊進行復制例如:fedcbajabcdefghjhgfedcb
reflect = cv.copyMakeBorder(img,top_size,buttom_size,left_size,right_size,borderType=cv.BORDER_REFLECT)

# 反射法,也就是以最邊緣像素爲軸、對稱、gfedcbjabcdefghigfedcba
reflect01 = cv.copyMakeBorder(img,top_size,buttom_size,left_size,right_size,borderType=cv.BORDER_REFLECT_101)

# 外包裝法 cdeifghjabcdefghjabcdefg
wrap = cv.copyMakeBorder(img,top_size,buttom_size,left_size,right_size,borderType=cv.BORDER_WRAP)

# 常量法,常數值填充
constant = cv.copyMakeBorder(img,top_size,buttom_size,left_size,right_size,borderType=cv.BORDER_CONSTANT)

# 設置圖像位置
plt.subplot(231)
# 設置圖像顯示
plt.imshow(img,'gray')
# 設置標題
plt.title('ORIGINAL')

plt.subplot(232)
plt.imshow(replicate,'gray')
plt.title("REPLICATE")

plt.subplot(233)
plt.imshow(reflect,'gray')
plt.title("REFLECT")

plt.subplot(234)
plt.imshow(reflect01,'gray')
plt.title("REPLICATE01")

plt.subplot(235)
plt.imshow(wrap,'gray')
plt.title("WRAP")

plt.subplot(236)
plt.imshow(constant,'gray')
plt.title("CONSTANT")

# 圖像顯示
plt.show()

在這裏插入圖片描述
第一幅圖是原始的圖片,其它的都是進行過處理的

  • BORDER_REPLICATE : 複製法,也就是複製最邊緣像素
  • BORDER_REFLECT :反射法,對感興趣的圖像中的像素在兩邊進行復制例如:fedcbajabcdefghjhgfedcb(這裏我也不是很明白,會的朋友請在評論區解釋下,感謝)
  • BORDER_REFLECT_101 : 反射法,也就是以最邊緣像素爲軸、對稱、gfedcbjabcdefghigfedcba
  • BORDER_WRAP : 外包裝法 cdeifghjabcdefghjabcdefg
  • BORDER_CONSTANT : 常量法,常數值填充

數值計算

import cv2 as cv

img = cv.imread("./1.jpg")

img2 = img + 10
img[:5,:,0]

print(img)
print("--------------------------")
print(img2)

我們來看下這段代碼的輸出結果:(由於輸出結果有點長,這裏只截取部分結果)

這是 img 的輸出,注意觀察它的值
在這裏插入圖片描述

這是 img2 的輸出,可以發現,img2 中的每個值都加了 10 ,如果值超出 255 ,

則得到結果如:253 + 10 = 263,263 - 255 = 7,那麼計算結果就爲 7
在這裏插入圖片描述

圖像融合

需要融合的兩張圖像如下:
在這裏插入圖片描述

import cv2 as cv

img = cv.imread("./1.jpg")
img_cat = cv.imread("./2.jpg")

result = img + img_cat
print(result)

輸出:
在這裏插入圖片描述
說明 img 和 img_cat 的值是不相同的,所以需要轉換一下

import cv2 as cv

img = cv.imread("./1.jpg")
img_cat = cv.imread("./2.jpg")

print(img.shape)
print(img_cat.shape)

在這裏插入圖片描述
可以發現,兩張圖像的 H 和 W 值確實是不相等的,所以無法進行數值相加


正確計算數值

import cv2 as cv

img = cv.imread("./1.jpg")
img_cat = cv.imread("./2.jpg")
print(img.shape)
# 設置與 img 一樣的數值
img_cat = cv.resize(img_cat,(721,300))
print(img_cat.shape)

在這裏插入圖片描述
現在兩張的數值是相等的了,可以進行圖像融合了,這裏其實就是使用了 resize() 方法將其擴大了


完整代碼:

import cv2 as cv
import matplotlib.pyplot as plt

img = cv.imread("./1.jpg")
img_cat = cv.imread("./2.jpg")
# 設置與 img 一樣的數值
img_cat = cv.resize(img_cat,(721,300))

# 設置寬度值
res = cv.addWeighted(img,0.4,img_cat,0.6,0)

# 圖像顯示
plt.imshow(res)
plt.show()

輸出:(prefect)
在這裏插入圖片描述

圖像保存

圖像的保存非常簡單,只需要使用 imwrite() 方法即可將圖像保存起來

# 導入 OpenCV 庫
import cv2 as cv

# 讀取圖像
img = cv.imread("./1.jpg",cv.IMREAD_GRAYSCALE)
# 圖像保存
# 第一個參數是圖像要保存的路徑,第二個圖像是要保存的圖像
cv.imwrite("./demo.jpg",img)

執行上面的代碼就會在當前路徑下生成一整 demo.jpg 的圖像
在這裏插入圖片描述

數據讀取 - 視頻

  • cv2.VideoCapture 可以捕獲攝像頭,用數字來控制不同的設備,例如 0,1
  • 如果是視頻文件,直接指定好路徑即可

舉例:

(1)讀取視頻

video = cv2.VideoCapture("demo.mp4")

(2)檢查視頻是否打開正確

# 檢查是否打開正確
if video.isOpened():
	# 我們都知道視頻和遊戲其實都是由圖像組成的,通過訪問圖像的幀數連貫形成的,這裏也是一樣
	# video.read() 一幀一幀地讀取
	# open 得到的是一個布爾值,就是 True 或者 False
	# frame 得到當前這一幀的圖像
    open, frame = video.read()
else:
    open = False

(3)遍歷每一幀圖像

while open:
    ret, frame = video.read()
    # 如果讀到的幀數不爲空,那麼就繼續讀取,如果爲空,就退出
    if frame is None:
        break
    if ret == True:
    	# 轉換爲灰度圖
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow("video",gray)
        # 這裏使用 waitKey 可以控制視頻的播放速度,數值越小,播放速度越快
        # 這裏等於 27 也即是說按下 ESC 鍵即可退出該窗口
        if cv2.waitKey(10) & 0xFF == 27:
            break
video.release()
cv2.destroyAllWindows()

完整代碼如下:

import cv2

video = cv2.VideoCapture("./demo.mp4")

# 檢查是否打開正確
if video.isOpened():
    # 我們都知道視頻和遊戲其實都是由圖像組成的,通過訪問圖像的幀數連貫形成的,這裏也是一樣
    # video.read() 一幀一幀地讀取
    # open 得到的是一個布爾值,就是 True 或者 False
    # frame 得到當前這一幀的圖像
    open, frame = video.read()
else:
    open = False

while open:
    ret, frame = video.read()
    # 如果讀到的幀數不爲空,那麼就繼續讀取,如果爲空,就退出
    if frame is None:
        break
    if ret == True:
        # 轉換爲灰度圖
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow("video",gray)
        # 這裏使用 waitKey 可以控制視頻的播放速度,數值越小,播放速度越快
        # 這裏等於 27 也即是說按下 ESC 鍵即可退出該窗口
        if cv2.waitKey(10) & 0xFF == 27:
            break
video.release()
cv2.destroyAllWindows()

運行該程序就會去讀取當前路徑下的 demo.mp4 文件,將視頻顯示在名爲 video 的窗口上,如下:

在這裏插入圖片描述


當然,上面的程序是將原視頻設置爲灰色的,想要顯示的是原視頻,只需要修改上述代碼中的兩個部分就行了

  • 註釋掉設置灰色的部分
  • 將原視頻顯示在窗口上
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章