OpenCV延时相机

这次用的是电脑的摄像头。暑假夏令营的时候买了两个摄像头来参加面试,现在被我闲置了。摄像头也能拍照啊,于是乎我就用摄像头来做延时相机了。这次想法比较简单,但也是遇到了很多的问题,特别是GUI方面。值得注意的是,这次程序我用来很多类与对象的东西,这个东西太难了,一直以来我都是能不能就不用,但这次是硬着头皮上了!

学习OpenCV

param define
cv2.VideoCapture.get(0) 视频文件的当前位置(播放)以毫秒为单位 CV_CAP_PROP_POS_MSEC Current position of the video file in milliseconds or video capture timestamp.
cv2.VideoCapture.get(1) 基于以0开始的被捕获或解码的帧索引 CV_CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
cv2.VideoCapture.get(2) 视频文件的相对位置(播放):0=电影开始,1=影片的结尾。 CV_CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0 - start of the film, 1 - end of the film.
cv2.VideoCapture.get(3) 在视频流的帧的宽度 CV_CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
cv2.VideoCapture.get(4) 在视频流的帧的高度 CV_CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
cv2.VideoCapture.get(5) 帧速率 CV_CAP_PROP_FPS Frame rate.
cv2.VideoCapture.get(6) 编解码的4字-字符代码 CV_CAP_PROP_FOURCC 4-character code of codec.
cv2.VideoCapture.get(7) 视频文件中的帧数 CV_CAP_PROP_FRAME_COUNT Number of frames in the video file.
cv2.VideoCapture.get(8) 返回对象的格式 CV_CAP_PROP_FORMAT Format of the Mat objects returned by retrieve() .
cv2.VideoCapture.get(9) 返回后端特定的值,该值指示当前捕获模式 CV_CAP_PROP_MODE Backend-specific value indicating the current capture mode.
cv2.VideoCapture.get(10) 图像的亮度(仅适用于照相机) CV_CAP_PROP_BRIGHTNESS Brightness of the image (only for cameras).
cv2.VideoCapture.get(11) 图像的对比度(仅适用于照相机) CV_CAP_PROP_CONTRAST Contrast of the image (only for cameras).
cv2.VideoCapture.get(12) 图像的饱和度(仅适用于照相机) CV_CAP_PROP_SATURATION Saturation of the image (only for cameras).
cv2.VideoCapture.get(13) 色调图像(仅适用于照相机) CV_CAP_PROP_HUE Hue of the image (only for cameras).
cv2.VideoCapture.get(14) 图像增益(仅适用于照相机)(Gain在摄影中表示白平衡提升) CV_CAP_PROP_GAIN Gain of the image (only for cameras).
cv2.VideoCapture.get(15) 曝光(仅适用于照相机) CV_CAP_PROP_EXPOSURE Exposure (only for cameras).
cv2.VideoCapture.get(16) 指示是否应将图像转换为RGB布尔标志 CV_CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB.
cv2.VideoCapture.get(17) × 暂时不支持 CV_CAP_PROP_WHITE_BALANCE Currently not supported
cv2.VideoCapture.get(18) 立体摄像机的矫正标注(目前只有DC1394 v.2.x后端支持这个功能) CV_CAP_PROP_RECTIFICATION Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently)

Note: 如果查询的视频属性是VideoCapture类不支持的,将会返回0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import cv2

def VideoCapture_shuxing():
cap = cv2.VideoCapture(0)
print("CV_CAP_PROP_POS_MSEC:" + str(cap.get()))
print("CV_CAP_PROP_POS_MSEC:" + str(cap.get(0)))
print("CV_CAP_PROP_POS_FRAMES:" + str(cap.get(1)))
print("CV_CAP_PROP_POS_AVI_RATIO :" + str(cap.get(2)))
print("CV_CAP_PROP_FRAME_WIDTH :" + str(cap.get(3)))
print("CV_CAP_PROP_FRAME_HEIGHT :" + str(cap.get(4)))
print("CV_CAP_PROP_FPS :" + str(cap.get(5)))
print("CV_CAP_PROP_FOURCC :" + str(cap.get(6)))
print("CV_CAP_PROP_FRAME_COUNT :" + str(cap.get(7)))
print("CV_CAP_PROP_FORMAT :" + str(cap.get(8)))
print("CV_CAP_PROP_MODE :" + str(cap.get(9)))
print("CV_CAP_PROP_BRIGHTNESS :" + str(cap.get(10)))
print("CV_CAP_PROP_CONTRAST :" + str(cap.get(11)))
print("CV_CAP_PROP_SATURATION :" + str(cap.get(12)))
print("CV_CAP_PROP_HUE :" + str(cap.get(13)))
print("CV_CAP_PROP_GAIN :" + str(cap.get(14)))
print("CV_CAP_PROP_EXPOSURE :" + str(cap.get(15)))
print("CV_CAP_PROP_CONVERT_RGB :" + str(cap.get(16)))
print("CV_CAP_PROP_WHITE_BALANCE :" + str(cap.get(17)))
print("CV_CAP_PROP_RECTIFICATION :" + str(cap.get(18)))

cap.release()
cv2.destroyAllWindows()
return 0

if __name__=='__main__':
VideoCapture_shuxing()



=================================================
(base) PS D:\Develop_Python\Progect\CamTimeLapse> python .\VideoCapture.get_demo01.py
CV_CAP_PROP_POS_MSEC:0.0
CV_CAP_PROP_POS_FRAMES:0.0
CV_CAP_PROP_POS_AVI_RATIO :-1.0
CV_CAP_PROP_FRAME_WIDTH :640.0
CV_CAP_PROP_FRAME_HEIGHT :480.0
CV_CAP_PROP_FPS :30.0
CV_CAP_PROP_FOURCC :22.0
CV_CAP_PROP_FRAME_COUNT :-1.0
CV_CAP_PROP_FORMAT :-1.0
CV_CAP_PROP_MODE :1.0
CV_CAP_PROP_BRIGHTNESS :128.0
CV_CAP_PROP_CONTRAST :128.0
CV_CAP_PROP_SATURATION :135.0
CV_CAP_PROP_HUE :-1.0
CV_CAP_PROP_GAIN :128.0
CV_CAP_PROP_EXPOSURE :-1.0
CV_CAP_PROP_CONVERT_RGB :1.0
CV_CAP_PROP_WHITE_BALANCE :1.0
CV_CAP_PROP_RECTIFICATION :1.0
(base) PS D:\Develop_Python\Progect\CamTimeLapse>

v1.0

实现功能:调用相机捕获一帧照片,并用当前时间进行文件命名保存。

要点

  1. cv2.VideoCapture().set(propId, value)的使用

  2. retval = cv2.imwrite(filename, img [, paras])

    filename:要保存的文件的路径和名称,包括文件扩展名

    img:要保存的 OpenCV 图像,nparray 多维数组

    paras:不同编码格式的参数,可选项

    cv2.CV_IMWRITE_JPEG_QUALITY:设置 .jpeg/.jpg 格式的图片质量,取值为 0-100(默认值 95),数值越大则图片质量越高;
    cv2.CV_IMWRITE_WEBP_QUALITY:设置 .webp 格式的图片质量,取值为 0-100;
    cv2.CV_IMWRITE_PNG_COMPRESSION:设置 .png 格式图片的压缩比,取值为 0-9(默认值 3),数值越大则压缩比越大。

  3. ret, frame = cap.read()

    • ret 为True 或者False,代表有没有读取到图片
    • frame表示截取到一帧的图片

main.p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2

def takephoto():
cap = cv2.VideoCapture(0)
cap.set(3,1920)
cap.set(4,1080)
# print("CV_CAP_PROP_POS_AVI_RATIO :" + str(cap.get(3)))
# print("CV_CAP_PROP_FRAME_WIDTH :" + str(cap.get(4)))
ret, frame = cap.read()

# print(frame)
while ret:
# frame = cv2.resize(frame, (1920,1080)) # 尺寸更改
cv2.imwrite(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg', frame,[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')

time.sleep(10) # 10s进行一次图像获取
ret, frame = cap.read()

cap.release()
cv2.destroyAllWindows()
return 0

if __name__=='__main__':
print('开始')
takephoto()

v1.1

新功能:以日期为分类,建立文件夹

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2
from makeDir import makedir

def takephoto():
cap = cv2.VideoCapture(0)
cap.set(3,1920)
cap.set(4,1080)
# print("CV_CAP_PROP_POS_AVI_RATIO :" + str(cap.get(3)))
# print("CV_CAP_PROP_FRAME_WIDTH :" + str(cap.get(4)))
ret, frame = cap.read()

# print(frame)
while ret:
makedir() # 以日期为分类,建立文件夹
picName = os.getcwd() + '\\' + time.strftime('%Y_%m_%d') + '\\' + time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'
cv2.imwrite(picName, frame,[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')

time.sleep(10)
ret, frame = cap.read()

cap.release()
cv2.destroyAllWindows()
return 0

if __name__=='__main__':
print('开始')
takephoto()

makeDir.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
def makedir():
flag = False
for i in os.listdir():
if i == time.strftime('%Y_%m_%d'):
flag = True
if not flag:
os.mkdir(os.getcwd() + '\\' + time.strftime('%Y_%m_%d'))

v1.2

  • 修改了程序运行逻辑,使用函数的方式,对摄像头进行调用和释放,保证摄像头只在工作是时候处于激活状态.睡眠状态时,摄像头是关闭状态.

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2
from makeDir import makedir

def caminit():
print('=======init=======')
global cap
cap = cv2.VideoCapture(1)
cap.set(3,1920)
cap.set(4,1080)
# ret, frame = cap.read()
praList = list(cap.read())
# print(praList)
return praList

def camrelease():
print('=======rels=======')
cap.release()
cv2.destroyAllWindows()

def takephoto(praList):
while praList[0]:
makedir() # 以日期为分类,建立文件夹
picName = os.getcwd() + '\\' + time.strftime('%Y_%m_%d') + '\\' + time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'
cv2.imwrite(picName, praList[1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')
praList[0] = False
if __name__=='__main__':

while True:
takephoto(caminit())
time.sleep(1)
camrelease()
time.sleep(10)
print()

makeDir.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
def makedir():
flag = False
for i in os.listdir():
if i == time.strftime('%Y_%m_%d'):
flag = True
if not flag:
os.mkdir(os.getcwd() + '\\' + time.strftime('%Y_%m_%d'))

v2.0 - 程序运行有问题

  • 加入了GUI(图形用户接口),但是这个UI做的其实是有问题的,不能实时显示控制台信息!可能需要更改文本框的属性

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2

from makeDir import makedir

from GUI import Ui_Form
import sys
from PyQt5 import QtWidgets

class MyPyQT_Form(QtWidgets.QWidget,Ui_Form):

def __init__(self, number, option, interval, praList):
super(MyPyQT_Form, self).__init__()
self.setupUi(self)

self.number = number
self.option = option
self.interval = interval
self.praList = praList

def caminit(self):
self.textEdito.setPlainText('=======init=======')
print('=======init=======')
global cap
cap = cv2.VideoCapture(int(self.number))
cap.set(3,1920)
cap.set(4,1080)
# ret, frame = cap.read()
self.praList = list(cap.read())
# print(praList)
# return self.praList

def camrelease(self):
self.textEdito.setPlainText('=======rels=======')
print('=======rels=======')
cap.release()
cv2.destroyAllWindows()

def takephoto(self):
while self.praList[0]:
makedir() # 以日期为分类,建立文件夹
picName = os.getcwd() + '\\' + time.strftime('%Y_%m_%d') + '\\' + time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'
cv2.imwrite(picName, self.praList[1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')
self.textEdito.setPlainText(time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')
self.praList[0] = False

def camstart(self):

while True:
my_pyqt_form.caminit()
my_pyqt_form.takephoto()
time.sleep(1)
my_pyqt_form.camrelease()
time.sleep(int(self.interval))
print()

# for i in range(2):
# my_pyqt_form.caminit()
# my_pyqt_form.takephoto()
# time.sleep(1)
# my_pyqt_form.camrelease()
# time.sleep(int(self.interval))
# print()

# 获取窗口所输入的信息的函数
def pushButton1_click(self):

# 获取Windows界面输入的内容
self.number=self.lineEdit_1.text()
self.option=self.lineEdit_2.text()
self.interval=self.lineEdit_3.text()

# print(self.number)
# print(self.option)
# print(self.interval)

self.textEditi.setPlainText("当前信息:\n"+ "相机号:" + self.number
+'\n'+ "模式选择:" + self.option
+'\n'+ "间隔:" + self.interval +'\n')

my_pyqt_form.camstart()

if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
my_pyqt_form = MyPyQT_Form(0,0,0,[])

# 窗口的打开和关闭
my_pyqt_form.show()
sys.exit(app.exec_())

GUI.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

from PyQt5 import QtCore,QtWidgets
from PyQt5.QtGui import QIcon
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")

# from PyQt5.QtWidgets import QDesktopWidget,QMainWindow,QApplication

class Ui_Form(object):
def setupUi(self, Form):
# 建立Windows窗口,并设置合适的大小

Form.setObjectName("Form")
Form.resize(1300, 600)

Form.setWindowIcon(QIcon("ICON.ico"))

# QRect ( int x, int y, int width, int height )
# 构造一个以(x,y)为左上角、宽度和高度为width,height的矩形。
self.widget = QtWidgets.QWidget(Form)
self.widget.setGeometry(QtCore.QRect(130, 70, 1000, 400))
self.widget.setObjectName("widget")


self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")

# 界面标题
self.formtitle = QtWidgets.QLabel(self.widget)
self.formtitle.setObjectName("formtitle")
self.verticalLayout.addWidget(self.formtitle)

# 界面脚注
self.footer = QtWidgets.QLabel(self.widget)
self.footer.setObjectName("footer")
self.verticalLayout.addWidget(self.footer)

self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")


# int fromRow // 横坐标
# int fromColumn // 纵坐标
# int rowSpan // 横向跨越几个单元格
# int columnSpan // 纵向跨越几个单元格

# 建立三个单行文本输入框QLineEdit
self.lineEdit_1 = QtWidgets.QLineEdit(self.widget)
self.lineEdit_1.setObjectName("lineEdit_1")
self.gridLayout.addWidget(self.lineEdit_1, 0, 2, 1, 1)

self.lineEdit_2 = QtWidgets.QLineEdit(self.widget)
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout.addWidget(self.lineEdit_2, 1, 2, 1, 1)

self.lineEdit_3 = QtWidgets.QLineEdit(self.widget)
self.lineEdit_3.setObjectName("lineEdit_3")
self.gridLayout.addWidget(self.lineEdit_3, 2, 2, 1, 1)


# 建立三个文本标签框QLabel
self.number = QtWidgets.QLabel(self.widget)
self.number.setObjectName("number")
self.gridLayout.addWidget(self.number, 0, 0, 1, 2)

self.option = QtWidgets.QLabel(self.widget)
self.option.setObjectName("option")
self.gridLayout.addWidget(self.option, 1, 0, 1, 2)

self.interval = QtWidgets.QLabel(self.widget)
self.interval.setObjectName("interval")
self.gridLayout.addWidget(self.interval, 2, 0, 1, 2)


self.verticalLayout.addLayout(self.gridLayout)

# 建立一个用户交互按键QPushButton
self.pushButton1 = QtWidgets.QPushButton(self.widget)
self.pushButton1.setObjectName("pushButton1")
self.verticalLayout.addWidget(self.pushButton1) # 待解决:怎么更改这个按键的格式

# 更改格式保存
# self.verticalLayout.addWidget(self.pushButton1, 4, 2, 1, 1)
# TypeError: addWidget(self, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 3 has unexpected type 'int'

self.retranslateUi(Form)
self.pushButton1.clicked.connect(Form.pushButton1_click)

# 设置两个显示文本框
self.textEditi = QtWidgets.QTextEdit()
self.textEditi.setObjectName("lineEditi")
self.gridLayout.addWidget(self.textEditi, 0, 4, 1, 1)

self.textEdito = QtWidgets.QTextEdit()
self.textEditi.setObjectName("textEdito")
self.gridLayout.addWidget(self.textEdito, 2, 4, 1, 1)

QtCore.QMetaObject.connectSlotsByName(Form)

def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "CamTimeLapse")) #设置窗口标题

# 设置界面标题
self.formtitle.setText(_translate("Form", \
"<html>\
<head/>\
<body>\
<p align=\"center\">\
<span style=\" font-size:30pt; font-weight:600; font-family: Times New Roman;\">\
CamTimeLapse\
</span>\
</p>\
</body>\
</html>"))


self.footer.setText(_translate("Form", \
"<html>\
<head/>\
<body>\
<p align=\"center\">\
<span style=\" font-size:15pt; font-weight:300; font-family: Times New Roman;\">\
Designed by Murphy\
</span>\
</p>\
</body>\
</html>"))

self.number.setText(_translate("Form", "相机号(0/1/2)"))

self.option.setText(_translate("Form", "时间/数量选择(0/1)"))

self.interval.setText(_translate("Form", "间隔(s)"))

self.pushButton1.setText(_translate("Form", "开始"))



makeDir.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
def makedir():
flag = False
for i in os.listdir():
if i == time.strftime('%Y_%m_%d'):
flag = True
if not flag:
os.mkdir(os.getcwd() + '\\' + time.strftime('%Y_%m_%d'))

v2.1 - GUI还没改完

Hello World · PyQt5 中文教程 (gitbooks.io)

pyqt5实现—GUI界面实时显示控制台输出_跌跌撞撞进大坑的博客-CSDN博客_pyqt5 textbrowser实时输出

【Qt】控制台信息输出到GUI中(在TensorFlow、PySide6环境下,将训练信息实时输出在文本框中)_KyrieLiu52的博客-CSDN博客_qt输出文本框

v3.0

  • 无GUI
  • 实现了分别调用两个摄像头的功能
  • 出现了长时间运行内存会爆掉的问题!

v3.1

  • 定时重启,解决长时间运行,内存爆掉的问题(但为什么会出现爆内存的问题没解决)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2
from makeDir import makedir
import sys

import gc


def caminit():
print('=======侧面:init=======')
global cap
cap = cv2.VideoCapture(0)
cap.set(3,1920)
cap.set(4,1080)
# ret, frame = cap.read()
praList = list(cap.read())
# print(praList)
return praList

def camrelease():
print('=======侧面:rels=======')
cap.release()
cv2.destroyAllWindows()

def takephoto(praList):
while praList[0]:
makedir() # 以日期为分类,建立文件夹
picName = os.getcwd() + '\\' + time.strftime('%Y_%m_%d') + '\\' + 'cemian' + '\\' + time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'
cv2.imwrite(picName, praList[1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('侧面:'+'%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done')
praList[0] = False


def caminit2():
print('=======正面:init=======')
global cap2
cap2 = cv2.VideoCapture(2)
cap2.set(3,1920)
cap2.set(4,1080)
praList = list(cap2.read())
# print(praList)
return praList

def camrelease2():
print('=======正面:rels2=======')
cap2.release()
cv2.destroyAllWindows()

def takephoto2(praList):
while praList[0]:
makedir() # 以日期为分类,建立文件夹
picName = os.getcwd() + '\\' + time.strftime('%Y_%m_%d') + '\\' + 'zhengmian' + '\\' + time.strftime('%Y_%m_%d__%H_%M_%S')+'.jpg'
cv2.imwrite(picName, praList[1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print(time.strftime('正面:'+'%Y_%m_%d__%H_%M_%S')+'.jpg'+'-done-2')
praList[0] = False


if __name__=='__main__':
while True:

nowtime = time.strftime('%H_%M_%S')

print()

if nowtime[3:5] == '00':
time.sleep(60)
print("restart...")
os.execl(sys.executable,sys.executable,*sys.argv)
else:
# print("run")
# time.sleep(10)

print()
print('****************************************')
print(f'********************{nowtime}********************')
print('****************************************')
print()

takephoto(caminit())
time.sleep(1)
camrelease()

print()

takephoto2(caminit2())
time.sleep(1)
camrelease2()

del cap
del cap2
del nowtime
gc.collect()

time.sleep(30) # 实际约60s


v4.0

  • 把程序进行了重写,改写了程序运行逻辑,尽可能减少一次循环占用的内存资源

  • 比较复杂的功能都封装成了函数

  • 使用百度PaddlePaddle深度学习框架,调用一个现成的深度学习的模型实现了抠图功能

  • main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
import cv2
import sys
import gc

from makeDir import makedir
from camInit import caminit
from takePic import takepic



def restart(nowTime):
print(f"{nowTime} : 60s - restart...")
time.sleep(60)
print("restart...")
os.execl(sys.executable,sys.executable,*sys.argv)

def start(picname):
nowTime = picname[-24:-4]
# print(nowTime) # 2022_10_08__23_07_05
# print(nowTime[15:17])

# 创建存储文件夹
makedir(picname)

# 一小时内三次重启三次
if nowTime[15:17] == '00':
restart(nowTime[15:17])
elif nowTime[15:17] == '20':
restart(nowTime[15:17])
elif nowTime[15:17] == '40':
restart(nowTime[15:17])
else:
# 开始拍照
takepic(picname, caminit())



if __name__=='__main__':
while True:
# 设置文件名
# D:\Develop_Python\Progect\CamTimeLapse\v4.0\2022_10_08\sid\2022_10_08__20_30_46.jpg
pwd = os.getcwd()
dirName = time.strftime('%Y_%m_%d')
nowTime = time.strftime('%Y_%m_%d__%H_%M_%S')
picClass = 'sid'
fileClass = '.jpg'
picName = pwd + '\\' + dirName + '\\' + picClass + '\\' + nowTime + fileClass

# print(picName)

# print(picName[-24:-4]) # nowTime
# print(picName[-24:-14]) # dirName
# print(picName[:-29])
# print(picName[-28:-25])

# picName = picName.replace('sid', 'fro')
# print(picName[:-4])
# time.sleep(10)





# ==================kaishi===================

print()
print("**********{start}**********")
print()
start(picName)
print()
print("**********{finish}**********")
print()

time.sleep(30) # 实际约60s


  • makeDir.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import os
import time
def makedir(picname):
flag = False
for i in os.listdir():
# print(i)
if i == picname[-24:-14]:
flag = True
break
if not flag:
os.mkdir(picname[:-29])
os.mkdir(picname[:-24])
os.mkdir(picname[:-29] + '\\' + 'fro')
os.mkdir(picname[:-29] + '\\' + 'seg')
  • camInit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import cv2
import numpy as np

def caminit():
for i in range(2):
if i == 0:
print('=======side:init=======')
cap = cv2.VideoCapture(0)
else:
print('=======front:init=======')
cap = cv2.VideoCapture(2)

# 相机参数设置
cap.set(3,1920)
cap.set(4,1080)

if i == 0:
praListSide = list(cap.read())
# print(praListSide)
cap.release()
print('=======side:rels=======')
print()
else:
praListFront = list(cap.read())
# print(praListFront)
cap.release()
print('=======front:rels=======')
print()

praList = np.array([praListSide,praListFront])

return praList
# print(type(praList))
# print(praList)
  • takePic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======
import cv2
from handleFigure import handlefigure


def takepic(picname, praList):
# side:
# praList[0][0] ret
# praList[0][1] fra

# front
# praList[1][0] ret
# praList[1][1] fra

if praList[0][0] == True:
cv2.imwrite(picname, praList[0][1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print('sid:' + picname[-24:-4] + ' - done')
else:
print('sid:' + picname[-24:-4] + ' - wrong')


picname = picname.replace('sid', 'fro')
if praList[1][0] == True:
cv2.imwrite(picname, praList[1][1],[int(cv2.IMWRITE_JPEG_QUALITY), 100]) # 无损保存
print('fro:' + picname[-24:-4] + ' - done')
handlefigure(picname)
else:
print('fro:' + picname[-24:-4] + ' - wrong')

  • handleFigure.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

# pip install matplotlib
# pip install pillow
# pip install PaddlePaddle
# pip install paddlehub
# hub install deeplabv3p_xception65_humanseg


# paddle-bfloat 0.1.7
# paddle2onnx 1.0.1
# paddlefsl 1.1.0
# paddlehub 2.3.0
# paddlenlp 2.4.0
# paddlepaddle 2.3.2
# hub install deeplabv3p_xception65_humanseg==1.1.2



import os
import paddlehub as hub
import cv2

def handlefigure(picname):

# 加载模型
human_seg = hub.Module(name='deeplabv3p_xception65_humanseg')

img = cv2.imread(picname)

picname = picname.replace('fro', 'seg')

print('1) 正在提取人体轮廓...')
results = human_seg.segmentation(images = [], visualization=True, use_gpu=False, output_dir = picname[:-25])
print('2) 提取人体轮廓完成。')
for result in results:
# print(result['save_path'])
oldname = result['save_path']
os.renames(oldname, picname[:-4] + '_seg' + '.jpg')


# if __name__=='__main__':
# picname = r'D:\Develop_Python\Progect\CamTimeLapse\v4.0\2022_10_08\fro\2022_10_08__22_28_49.jpg'
# handlefigure(picname)







# 案例学习

# import paddlehub as hub
# import numpy as np
# import cv2
# import time
# from PIL import Image

# if __name__ == '__main__':
# #第一次运行会自动下载deeplabv3p_xception65_humanseg模型,会慢一点
# human_seg = hub.Module(name="deeplabv3p_xception65_humanseg")
# src_img = cv2.imread('/Users/luoye/Downloads/WechatIMG281.jpeg')
# #visualization默认是false,当设置为true时会生成分割后的图片并保存在humanseg_output目录下
# results = human_seg.segmentation(images=[src_img], visualization=True)
# for result in results:
# image_alpha = result['data'].astype(np.uint8)
# #这里我把背景换成了红色
# img_bg = Image.new('RGBA', (src_img.shape[1], src_img.shape[0]), (255, 0, 0, 255))
# image_temp = Image.fromarray(cv2.cvtColor(src_img, cv2.COLOR_BGR2RGBA))
# img_bg.paste(image_temp, (0, 0), Image.fromarray(image_alpha))

# path = "./" + str(int(time.time_ns() / 1000)) + ".png"
# img_bg.save(path)
# print("add successful path=" + path)






## 官方演示代码
# https://www.paddlepaddle.org.cn/hubdetail?name=deeplabv3p_xception65_humanseg&en_category=ImageSegmentation

# import paddlehub as hub
# import cv2

# human_seg = hub.Module(name="deeplabv3p_xception65_humanseg")
# result = human_seg.segmentation(images=[cv2.imread('/PATH/TO/IMAGE')])

## API
# def segmentation(images=None,
# paths=None,
# batch_size=1,
# use_gpu=False,
# visualization=False,
# output_dir='humanseg_output')


## 参数
# images (list[numpy.ndarray]): 图片数据,ndarray.shape 为 [H, W, C],BGR格式;
# paths (list[str]): 图片的路径;
# batch_size (int): batch 的大小;
# use_gpu (bool): 是否使用 GPU;
# visualization (bool): 是否将识别结果保存为图片文件;
# output_dir (str): 图片的保存路径。

##返回
# res (list[dict]): 识别结果的列表,列表中每一个元素为 dict,关键字有 'save_path', 'data',对应的取值为:
# save_path (str, optional): 可视化图片的保存路径(仅当visualization=True时存在);
# data (numpy.ndarray): 人像分割结果,仅包含Alpha通道,取值为0-255 (0为全透明,255为不透明),也即取值越大的像素点越可能为人体,取值越小的像素点越可能为背景。
  • findCamID.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# -*- coding : utf-8 -*-
# Author : MurphyHou
# =======Here We Go!=======

import cv2
import time

def findcamid():
cap = cv2.VideoCapture(0)
# cap = cv2.VideoCapture(1)
# cap = cv2.VideoCapture(2)

while True:
ret, frame = cap.read()
# frame = cv2.flip(frame,1) #镜像操作
cv2.imshow("video", frame)
key = cv2.waitKey(50)
#print(key)
if key == ord('q'):
break
cv2.destroyAllWindows()

if __name__=='__main__':
print('开始')
findcamid()

参考资料

OpenCV VideoCapture.get()参数详解 - 简书 (jianshu.com)

【OpenCV + Python】ret, frame = cap.read()返回值含义&视频读取_胖子工作室的博客-CSDN博客_cap.read

说明 · OpenCV-Python初学自码 · 看云 (kancloud.cn)

python-opencv 中文文档

OpenCV的VideoCapture类的get、set参数列表_EmbedDebugger的博客-CSDN博客_videocapture参数

【OpenCV 例程300篇】02. 图像的保存(cv2.imwrite)_YouCans的博客-CSDN博客_cv2.imwrite

python获取所有可用摄像头(id + 名称)可用于opencv_babybin的博客-CSDN博客_python 获取摄像头列表


OpenCV延时相机
https://cosmicdusty.cc/post/Ideas/OpenCVTimeLapseCamera/
作者
Murphy
发布于
2022年10月2日
许可协议