[opencv][python] 学习手册2:练习代码3
32_打开摄像头.py
33_视频分解图像.py
34_人脸识别案例.py
35_摄像头人脸识别.py
36_判断当前是白天还是黑夜.py
文章目录
32_打开摄像头.py
代码
"""
需求:
1. 打开摄像头
2. 检查摄像头是否打开成功
3. 获取摄像头信息
4. 循环读取摄像头中图片信息
1. 读取摄像头图片信息
2. 检查读取图片是否成功,成功-显示图像
3. 等待按键
"""
import logging
import cv2 as cv
"""------------------------- 函数区 -------------------------"""
def frame_equalization(in_frame):
# global c3_eq
# 2. 拆分图像 split
channels = cv.split(in_frame)
# 3. 对每个通道进行均衡化 equalizeHist api
cb_eq = cv.equalizeHist(channels[0])
cg_eq = cv.equalizeHist(channels[1])
cr_eq = cv.equalizeHist(channels[2])
# 4. 再将均衡化的单通道进行融合 merge api
return cv.merge([cb_eq, cg_eq, cr_eq])
"""------------------------- 调试区 -------------------------"""
logging.basicConfig(level=logging.INFO)
# 1. 打开摄像头
video = cv.VideoCapture(0, cv.CAP_DSHOW) # cv.CAP_DSHOW 消除 [ WARN:0] terminating async callback
# 2. 检查摄像头是否打开成功
flag = video.isOpened()
# print("摄像头状态:[{0}]".format(flag))
logging.info("摄像头状态:[{0}]".format(flag))
# 3. 获取摄像头信息
height = video.get(cv.CAP_PROP_FRAME_HEIGHT)
width = video.get(cv.CAP_PROP_FRAME_WIDTH)
fps = video.get(cv.CAP_PROP_FPS)
# print("height::[{0}], width::[{1}], fps::[{2}]".format(height, width, fps))
logging.info("height::[{0}], width::[{1}], fps::[{2}]".format(height, width, fps))
# 4. 循环读取摄像头中图片信息
while True:
# 1. 读取摄像头图片信息
flag, frame = video.read()
# 2. 检查读取图片是否成功,成功-显示图像
if flag:
# 添加视频帧处理功能
c3_eq = frame_equalization(frame)
cv.imshow("frame", frame)
cv.imshow("c3_eq", c3_eq)
# 3. 等待按键, 30fps
key = cv.waitKey(30)
if key == 27 or key == ord('q'):
cv.destroyAllWindows()
break
注1:
cv.VideoCapture(0, cv.CAP_DSHOW)
参数2使用 DSHOW,不然会报错: cv.CAP_DSHOW 消除 [ WARN:0] terminating async callback
运行结果(略)
33_视频分解图像(连续视频帧保存).py
需求
实现视频帧的连续保存,按下 s 键,开始保存视频图像,再次按下 s 键,停止保存。
代码
"""
需求:
1. 打开摄像头
2. 检查摄像头是否打开成功
3. 获取摄像头信息
4. 循环读取摄像头中图片信息
1. 读取摄像头图片信息
2. 检查读取图片是否成功,成功-显示图像
3. 等待按键
"""
import os
import cv2 as cv
# 1. 打开摄像头
video = cv.VideoCapture(0, cv.CAP_DSHOW) # cv.CAP_DSHOW 消除 [ WARN:0] terminating async callback
# 2. 检查摄像头是否打开成功
flag = video.isOpened()
print("摄像头状态:[{0}]".format(flag))
# 3. 获取摄像头信息
height = video.get(cv.CAP_PROP_FRAME_HEIGHT)
width = video.get(cv.CAP_PROP_FRAME_WIDTH)
fps = video.get(cv.CAP_PROP_FPS)
print("height::[{0}], width::[{1}], fps::[{2}]".format(height, width, fps))
def frame_equalization(in_frame):
# global c3_eq
# 2. 拆分图像 split
channels = cv.split(in_frame)
# 3. 对每个通道进行均衡化 equalizeHist api
cb_eq = cv.equalizeHist(channels[0])
cg_eq = cv.equalizeHist(channels[1])
cr_eq = cv.equalizeHist(channels[2])
# 4. 再将均衡化的单通道进行融合 merge api
return cv.merge([cb_eq, cg_eq, cr_eq])
def save_frame(in_frame, i, save_enable=False):
save_path = r"../save"
if save_enable:
try:
os.mkdir(save_path)
except:
pass
cv.imwrite(save_path + "/img_{}.png".format(i), in_frame)
print("save img ", i)
else:
pass
# 4. 循环读取摄像头中图片信息
save_enable = False
index = 0
while True:
# 1. 读取摄像头图片信息
flag, frame = video.read()
# 2. 检查读取图片是否成功,成功-显示图像
if flag:
# 图像均衡化
c3_eq = frame_equalization(frame)
# 显示原图像+均衡图像
cv.imshow("frame", frame)
cv.imshow("c3_eq", c3_eq)
# 保存原图像
save_frame(frame, index, save_enable)
# 3. 等待按键, 30fps
key = cv.waitKey(30)
# 视频图像连续保存
if key == ord('s'):
# if not save_enable:
# save_enable = True
# else:
# save_enable = False
save_enable = not save_enable # 开关机制
print("save_enable ::", save_enable)
# 退出视频
if key == 27 or key == ord('q'):
cv.destroyAllWindows()
break
index += 1
运行结果(略)
34_人脸识别案例.py
代码
"""
需求:
1. 读取图像
2. 转化成灰度图
3. 加载人脸识别特征文件
4. 加载人眼识别特征文件
5. 检测人脸
6. 对每一个检测到的人脸进行处理
1. 用矩形框出人脸
2. 截取人脸 ROI
3. 对人脸 ROI 进行人眼检测
4. 对每一个检测到的人眼进行处理
1. 用矩形框出人眼
7. 显示图像,等待按键
问题解决
加载训练模型出问题:Process finished with exit code -1073741515 (0xC0000135)
链接:https://stackoverflow.com/questions/33582766/process-finished-with-exit-code-1073741515-0xc0000135
解决:内存被占用,重启编译器
"""
# import cvlog as log
import logging
import cv2 as cv
# 0. 配置 python 日志
logging.basicConfig(level=logging.INFO)
# 1. 读取图像
filename = r"../img/lena.jpg"
# filename = r"../save/img_1192.png"
src = cv.imread(filename, cv.IMREAD_COLOR)
# 2. 转化成灰度图
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 3. 加载人脸识别特征文件
face_detector = cv.CascadeClassifier(r"../img/haarcascade_frontalface_default.xml")
# 4. 加载人眼识别特征文件
eye_detector = cv.CascadeClassifier(r"../img/haarcascade_eye.xml")
# 5. 检测人脸
faces = face_detector.detectMultiScale(gray, 1.3, 1, minSize=(10, 10))
logging.info("人脸数量:[{0}]".format(len(faces)))
logging.info("人脸向量:\n[{0}]".format(faces))
# 6. 对每一个检测到的人脸进进行处理
for face in faces:
f_x = face[0]
f_y = face[1]
f_h = face[2]
f_w = face[3]
# 1. 用矩形框出人脸
cv.rectangle(src, (f_x, f_y), (f_x + f_w, f_y + f_h), (0, 255, 0), 2)
# 2. 截取人脸 ROI
face_roi = src[f_y:f_y + f_h, f_x:f_x + f_w]
# 3. 对人脸 ROI 进行人眼检测
eyes = eye_detector.detectMultiScale(face_roi, 1.3, 5)
logging.info("人眼数量:[{0}]".format(len(eyes)))
logging.info("人眼向量:\n[{0}]".format(eyes))
# 4. 对每一个检测到的人眼进行处理
for eye in eyes:
e_x = eye[0]
e_y = eye[1]
e_h = eye[2]
e_w = eye[3]
# 1. 用矩形框出人眼
cv.rectangle(face_roi, (e_x, e_y), (e_x + e_w, e_y + e_h), (0, 0, 255), 2)
cv.imshow("face_roi", face_roi)
# 7. 显示图像,等待按键
cv.imshow("src", src)
key = cv.waitKey(0)
print("key = ", key)
# logging.error("key = ", key)
运行结果
35_摄像头人脸识别.py
代码
"""
需求:
1. 打开摄像头
2. 检查摄像头是否打开成功
3. 获取摄像头信息
4. 循环读取摄像头中图片信息
1. 读取摄像头图片信息
2. 检查读取图片是否成功,成功-显示图像
3. 等待按键
"""
import logging
import cv2 as cv
"""------------------------- 函数区 -------------------------"""
"""
需求:
1. 打开摄像头
2. 检查摄像头是否打开成功
3. 获取摄像头信息
4. 循环读取摄像头中图片信息
1. 读取摄像头图片信息
2. 检查读取图片是否成功,成功-显示图像
3. 等待按键
问题解决:
1. 如何调整参数:detectMultiScale:https://stackoverflow.com/questions/20801015/recommended-values-for-opencv-detectmultiscale-parameters
"""
import logging
import cv2 as cv
"""------------------------- 函数区 -------------------------"""
def frame_equalization(in_frame):
# global c3_eq
# 2. 拆分图像 split
channels = cv.split(in_frame)
# 3. 对每个通道进行均衡化 equalizeHist api
cb_eq = cv.equalizeHist(channels[0])
cg_eq = cv.equalizeHist(channels[1])
cr_eq = cv.equalizeHist(channels[2])
# 4. 再将均衡化的单通道进行融合 merge api
return cv.merge([cb_eq, cg_eq, cr_eq])
def detect_init():
# global face_detector, eye_detector
f_detector = cv.CascadeClassifier(r"../img/haarcascade_frontalface_default.xml")
e_detector = cv.CascadeClassifier(r"../img/haarcascade_eye.xml")
return f_detector, e_detector
def detect_face_eye(in_frame):
gray = cv.cvtColor(in_frame, cv.COLOR_BGR2GRAY)
faces = face_detector.detectMultiScale(gray, 1.5, 2, minSize=(30, 30))
for face in faces:
f_x = face[0]
f_y = face[1]
f_h = face[2]
f_w = face[3]
# 1. 用矩形框出人脸
cv.rectangle(in_frame, (f_x, f_y), (f_x + f_w, f_y + f_h), (0, 255, 0), 2)
# 2. 截取人脸 ROI
f_roi = in_frame[f_y:f_y + f_h, f_x:f_x + f_w]
# 3. 对人脸 ROI 进行人眼检测
eyes = eye_detector.detectMultiScale(f_roi, 1.7, 7, minSize=(40, 40))
# 4. 对每一个检测到的人眼进行处理
for eye in eyes:
e_x = eye[0]
e_y = eye[1]
e_h = eye[2]
e_w = eye[3]
# 1. 用矩形框出人眼
cv.rectangle(f_roi, (e_x, e_y), (e_x + e_w, e_y + e_h), (0, 0, 255), 2)
# cv.imshow("face_roi", face_roi)
return f_roi
"""------------------------- 调试区 -------------------------"""
# 0. 配置 python 日志
logging.basicConfig(level=logging.INFO)
# 1. 打开摄像头
video = cv.VideoCapture(0, cv.CAP_DSHOW) # cv.CAP_DSHOW 消除 [ WARN:0] terminating async callback
# 2. 检查摄像头是否打开成功
flag = video.isOpened()
logging.info("摄像头状态:[{0}]".format(flag))
# 3. 获取摄像头信息
height = video.get(cv.CAP_PROP_FRAME_HEIGHT)
width = video.get(cv.CAP_PROP_FRAME_WIDTH)
fps = video.get(cv.CAP_PROP_FPS)
logging.info("height::[{0}], width::[{1}], fps::[{2}]".format(height, width, fps))
# # 加载特征识别文件
face_detector, eye_detector = detect_init()
# 4. 循环读取摄像头中图片信息
while True:
# 1. 读取摄像头图片信息
flag, frame = video.read()
# 2. 检查读取图片是否成功,成功-显示图像
if flag:
# # 功能 1:视频帧均衡化
c3_eq = frame_equalization(frame)
# # 功能 2:人脸、人眼识别
face_roi = detect_face_eye(frame)
try:
cv.imshow("frame", frame)
cv.imshow("c3_eq", c3_eq)
cv.imshow("face_roi", face_roi)
except:
pass
# 3. 等待按键, 30fps
key = cv.waitKey(30)
if key == 27 or key == ord('q'):
cv.destroyAllWindows()
break
logging.info("相机退出")
运行结果(略)
36_判断当前是白天还是黑夜.py
原理
- 将图像从 RGB(BGR) 空间 转化到 HSV 空间,色调(H),饱和度(S),明度(V)。
- 色调H:
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°- 饱和度S:
饱和度S表示颜色接近光谱色的程度。通常取值范围为0%~100%,值越大,颜色越饱和。- 明度V:
明度表示颜色明亮的程度,通常取值范围为0%(黑)到100%(白)。
- 注意: 在opencv中,H、S、V值范围分别是[0,180],[0,255],[0,255],而非[0,360],[0,1],[0,1];
代码
"""
需求:
1. 读取图像
2. 将图像从 RGB 空间转换成 HSV 空间(色调(H),饱和度(S),明度(V))
3. 获取 V 通道信息
4. 求 V 通道的平均值
5. 显示图像,等待按键
解决问题:TypeError: not all arguments converted during string formatting:https://stackoverflow.com/questions/18053500/typeerror-not-all-arguments-converted-during-string-formatting-python
"""
import logging
import cv2 as cv
import numpy as np
"""------------------------- 功能函数 -------------------------"""
def get_brightness(in_img):
# 2. 将图像从 RGB 空间转换成 HSV 空间(色调(H),饱和度(S),明度(V))
hsv = cv.cvtColor(in_img, cv.COLOR_BGR2HSV)
# 3. 获取 V 通道信息
channels = cv.split(hsv)
# 4. 求 V 通道的平均值
v_channel = channels[2]
h, w = in_img.shape[0], in_img.shape[1]
total_v = np.sum(v_channel)
avg_v = total_v / (h * w)
return avg_v
"""------------------------- 调试代码 -------------------------"""
logging.basicConfig(level=logging.INFO)
# 1. 读取图像
filename_day = r"../img/day_shanghai.jpg"
filename_night = r"../img/night_shanghai.jpg"
day = cv.imread(filename_day, cv.IMREAD_COLOR)
night = cv.imread(filename_night, cv.IMREAD_COLOR)
day_brightness = get_brightness(day)
night_brightness = get_brightness(night)
logging.info("day 的平均亮度:{}".format(day_brightness))
logging.info("night 的平均亮度:{}".format(night_brightness))
# 5. 显示图像,等待按键
cv.imshow("day", day)
cv.imshow("night", night)
key = cv.waitKey(0)
print("key = ", key)
运行结果
E:\Software\A_anaconda\envs\python3\python.exe E:/WorkSpace/WS_CV_2D/day02/36_判断当前是白天还是黑夜.py
INFO:root:day 的平均亮度:170.97303571428571
INFO:root:night 的平均亮度:52.73478390461997
通过设定 HSV 中 V 的阈值判断白天或黑夜
todo:图片合成视频
参考
问题解决
1. 加载训练模型出问题:Process finished with exit code -1073741515 (0xC0000135)
链接:https://stackoverflow.com/questions/33582766/process-finished-with-exit-code-1073741515-0xc0000135