Python+OpenCV4:讀寫輸入和輸出的簡單實踐(圖片、視頻、攝像頭)


典型的文件處理流程如下:

利用命令行參數

sys.argv

命令行參數是讀取文件時常用的方式。

命令行參數保存在 sys.argv 的列表中,列表的第一個元素是腳本名稱,后面的元素是命令行參數

 

通過以下腳本 sys_argv.py 可以熟悉命令行參數的獲取:

1 import sys
2 
3 print(f'運行的腳本名是:{sys.argv[0]}')
4 print(f'sys.argv 列表的長度是:{len(sys.argv)}')
5 print(f'該腳本的參數是:{sys.argv[1:]}')

運行命令  python sys_argv.py 666 yu  可以得到以下輸出:

運行的腳本名是:sys_argv.py
sys.argv 列表的長度是:3
該腳本的參數是:['666', 'yu']

argparse

當程序比較復雜時,我們一般不會直接使用 sys.argv,而應該使用 Python 的標准庫 argparse

argparse 做了一些封裝。使用 argparse,程序可以識別需要哪些參數,如何解析參數,以及提供幫助信息和使用信息,也提供自動化的錯誤信息。

下面是使用 argparse 的示例:

 1 import argparse
 2 
 3 # 創建 ArgumentParser 對象,參數會自動保存到該對象中
 4 # description 在使用 -h/--help 的時候會顯示這個文本
 5 parser = argparse.ArgumentParser(description='某圖像處理')
 6 
 7 # 添加參數
 8 # 第一個參數是給 parser 添加的變量
 9 # type 指定類型
10 # help 解釋參數
11 parser.add_argument('image', type=str, help='圖像路徑')
12 
13 # 調用 parse_args() 可以獲取參數
14 args = parser.parse_args()
15 print(args.image)

運行命令  python argparse_demo.py '../data/yiquan.jpeg' ,可以輸入:

../data/yiquan.jpeg

更多關於 argparse 的用法參考:argparse — Parser for command-line options, arguments and sub-commands

讀寫圖片

讀入圖片

一個利用參數讀取圖片的例子:

 1 """
 2 讀取圖片
 3 """
 4 import argparse
 5 import cv2
 6 
 7 # 創建 ArgumentParser 對象
 8 parser = argparse.ArgumentParser()
 9 
10 # 添加參數,默認類型是字符串
11 parser.add_argument('path_image', help='圖像路徑')
12 
13 # 解析參數
14 args = parser.parse_args()
15 
16 # 根據圖像路徑加載輸入圖像
17 image = cv2.imread(args.path_image)
18 cv2.imshow('loaded image', image)
19 cv2.waitKey(0)
20 cv2.destroyAllWindows()

輸入命令  python argparse_load_image.py ../data/yiquan.jpeg ,可以顯示圖片。

 

讀入/處理/寫入圖片

標准的圖像處理流程有讀取、處理、保存,以下是一個該流程的簡單示例:

 1 """
 2 讀入/處理/寫入圖片
 3 運行腳本 python argparse_load_processing_save_image.py [path_image_input] [path_image_output]
 4 """
 5 import argparse
 6 import cv2
 7 
 8 parser = argparse.ArgumentParser()
 9 
10 parser.add_argument('path_image_input', help='圖像輸入的路徑')
11 
12 parser.add_argument('path_image_output', help='圖像輸出的路徑')
13 
14 args = parser.parse_args()
15 
16 image_input = cv2.imread(args.path_image_input)
17 
18 # 把彩色圖片變為灰度圖片
19 gray_image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY)
20 
21 cv2.imshow('gray image', gray_image)
22 
23 # 保存處理后的文件
24 cv2.imwrite(args.path_image_output, gray_image)
25 
26 cv2.waitKey(0)
27 
28 cv2.destroyAllWindows()

運行腳本后的效果如下:

 

並且在參數指定的目錄保存一張 result.jpeg 圖片。

讀取攝像頭數據和視頻文件

讀取+處理

OpenCV 的 cv2.VieoCapture 可以根據不同源(如圖像序列、視頻文件、攝像頭),進行視頻捕捉。

 1 """
 2 讀取攝像頭數據
 3 處理數據並且展示數據
 4 """
 5 import argparse
 6 import cv2
 7 
 8 parser = argparse.ArgumentParser()
 9 
10 parser.add_argument('index_camera', type=int, help='攝像頭編號')
11 
12 args = parser.parse_args()
13 
14 capture = cv2.VideoCapture(args.index_camera)
15 
16 # 獲取 capture 的一些屬性
17 frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
18 frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
19 fps = capture.get(cv2.CAP_PROP_FPS)
20 print(frame_width, frame_height, fps)
21 
22 if capture.isOpened() is False:
23     print('Error openning the camera')
24 
25 while capture.isOpened():
26     ret, frame = capture.read()
27 
28     if ret:
29         # 顯示攝像頭捕獲的幀
30         cv2.imshow('Input frame from the camera', frame)
31 
32         # 把攝像頭捕捉到的幀轉換為灰度
33         gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
34 
35         # 顯示處理后的幀
36         cv2.imshow('Grayscale input camera', gray_frame)
37 
38         # cv2.waitKey()這個函數是在一個給定的時間內(單位ms)等待用戶按鍵觸發
39         # 如果用戶沒有按下按鍵,則繼續等待(循環)
40         if (cv2.waitKey(10) & 0xFF) == ord('q'):
41             break
42     else:
43         break
44 
45 capture.release()
46 cv2.destroyAllWindows()

注意運行腳本的時候不要在 IDE 下運行,盡量在終端上直接運行。比如我在 PyCharm 里運行,就出現了以下錯誤:

Abort trap: 6

在終端上運行腳本可以解決該問題。注意需要設置攝像頭參數(比如 0): python read_camera.py 0 。

(cv2.waitKey(10) & 0xFF) == ord('q')  這條命令的含義可以參考 What's 0xFF for in cv2.waitKey(1)? 中的回答。

成功運行腳本之后,可以出現兩個窗口,一個是捕捉攝像頭的窗口,另一個是處理成灰度圖像的窗口。點擊 q 鍵可以退出應用。

保存某一幀到硬盤

稍加修改,可以在按 c 鍵的時候,把某時刻的幀保存在硬盤上。

 1 """
 2 讀取攝像頭數據
 3 處理數據並且展示數據
 4 """
 5 import argparse
 6 import cv2
 7 
 8 parser = argparse.ArgumentParser()
 9 
10 parser.add_argument('index_camera', type=int, help='攝像頭編號')
11 
12 args = parser.parse_args()
13 
14 capture = cv2.VideoCapture(args.index_camera)
15 
16 # 獲取 capture 的一些屬性
17 frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
18 frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
19 fps = capture.get(cv2.CAP_PROP_FPS)
20 print(frame_width, frame_height, fps)
21 
22 if capture.isOpened() is False:
23     print('Error openning the camera')
24 
25 frame_index = 0
26 while capture.isOpened():
27     ret, frame = capture.read()
28 
29     if ret:
30         # 顯示攝像頭捕獲的幀
31         cv2.imshow('Input frame from the camera', frame)
32 
33         # 把攝像頭捕捉到的幀轉換為灰度
34         gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
35 
36         # 顯示處理后的幀
37         cv2.imshow('Grayscale input camera', gray_frame)
38 
39         # cv2.waitKey()這個函數是在一個給定的時間內(單位ms)等待用戶按鍵觸發
40         # 如果用戶沒有按下按鍵,則繼續等待(循環)
41         if (cv2.waitKey(10) & 0xFF) == ord('q'):
42             break
43         if (cv2.waitKey(10) & 0xFF) == ord('c'):
44             frame_name = f'camera_frame_{frame_index}.png'
45             gray_frame_name = f'grayscale_camera_frame_{frame_index}.png'
46             cv2.imwrite(frame_name, frame)
47             cv2.imwrite(gray_frame_name, gray_frame)
48             frame_index += 1
49     else:
50         break
51 
52 capture.release()
53 cv2.destroyAllWindows()

讀取視頻文件

讀取視頻文件和讀取圖片文件類似。

在 http://samples.mplayerhq.hu/ 里面找到合適的視頻文件。

 1 """
 2 讀取視頻數據
 3 """
 4 import argparse
 5 import cv2
 6 
 7 parser = argparse.ArgumentParser()
 8 
 9 parser.add_argument('video_path', help='視頻文件路徑')
10 
11 args = parser.parse_args()
12 
13 capture = cv2.VideoCapture(args.video_path)
14 
15 if capture.isOpened() is False:
16     print('Error openning the video')
17 
18 while capture.isOpened():
19 
20     ret, frame = capture.read()
21     if ret:
22         # 顯示攝像頭捕獲的幀
23         cv2.imshow('Original frame from the video file', frame)
24 
25         # 把攝像頭捕捉到的幀轉換為灰度
26         gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
27 
28         # 顯示處理后的幀
29         cv2.imshow('Grayscale frame', gray_frame)
30 
31         # cv2.waitKey()這個函數是在一個給定的時間內(單位ms)等待用戶按鍵觸發
32         # 如果用戶沒有按下按鍵,則繼續等待(循環)
33         if (cv2.waitKey(10) & 0xFF) == ord('q'):
34             break
35     else:
36         break
37 
38 capture.release()
39 cv2.destroyAllWindows()

運行腳本: python read_video_file.py ../data/DSCF1928_fish.AVI 。

我所使用的測試視頻文件在這里下載。

 

保存一個視頻文件

使用 cv2.VideoWriter 可以寫入視頻文件。

FPS 是一個很重要的指標,它表示每秒處理多少個幀。FPS 越大往往視頻的流暢度就越高。

視頻編碼(video code)用於壓縮和解壓一個數字視頻。壓縮視頻格式往往遵循成為視頻壓縮標准或者視頻編碼格式的標准。

OpenCV 提供了 FOURCC,用於指定視頻編碼。此外,視頻文件格式用於存儲數字視頻數據,常見的格式有 AVI(*.avi)、MP4(*.mp4)、QuickTime(*.mov)。

下圖顯示了使用 cv2.VideoWriter 需要考慮的一些因素。

 

以下是使用本地攝像頭作為輸入,轉換為灰度后保存為本地視頻文件。

 1 """
 2 接收攝像頭參數
 3 然后寫入視頻文件
 4 """
 5 
 6 import cv2
 7 import argparse
 8 
 9 parser = argparse.ArgumentParser()
10 
11 parser.add_argument("output_video_path", help="path to the video file to write")
12 args = parser.parse_args()
13 
14 capture = cv2.VideoCapture(0)
15 
16 frame_width = capture.get(cv2.CAP_PROP_FRAME_WIDTH)
17 frame_height = capture.get(cv2.CAP_PROP_FRAME_HEIGHT)
18 fps = capture.get(cv2.CAP_PROP_FPS)
19 print(f'CV_CAP_PROP_FRAME_WIDTH: {frame_width}')
20 print(f'CV_CAP_PROP_FRAME_HEIGHT: {frame_height}')
21 print(f'CAP_PROP_FPS: {fps}')
22 
23 fourcc = cv2.VideoWriter_fourcc(*'XVID')
24 
25 # 最后一個參數指是否使用彩色圖像
26 out_gray = cv2.VideoWriter(args.output_video_path, fourcc, int(fps), (int(frame_width), int(frame_height)), False)
27 
28 while capture.isOpened():
29 
30     ret, frame = capture.read()
31     if ret is True:
32 
33         gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
34 
35         out_gray.write(gray_frame)
36 
37         cv2.imshow('gray', gray_frame)
38         if cv2.waitKey(1) & 0xFF == ord('q'):
39             break
40     else:
41         break
42 
43 capture.release()
44 out_gray.release()
45 cv2.destroyAllWindows()

輸入命令  python write_video_file.py ./my_video.mp4 ,會出現一個窗口,點擊 q 退出,最后保存一個 my_video.mp4 文件。

原文作者:雨先生
原文鏈接:https://www.cnblogs.com/noluye/p/11446146.html 
許可協議:知識共享署名-非商業性使用 4.0 國際許可協議

參考

 


免責聲明!

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



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