OpenCV入门教程最佳实例:从图片读取到人脸识别(附代码)
·
简介
由于给部门进行opencv的培训,整理了一些基础教程及代码,由此整理至此。
下文中的代码只是做简单总结,对于其中涉及的知识点,数学知识等需要自行再去学习研究,在此只是提供代码示例,以便你可以使用代码快速的上手或者打断点了解其数据构成。
ps:基本上必要的代码我都做了注释了
源码地址:https://github.com/zpskt/computer-vision
环境介绍
python 3.10.x
IDE: pycharm
基础操作
这里的基础操作主要是图片的读取,查看相关属性(像素点,通道),彩色图和灰度图的转换,图片的像素变化。
import cv2
import matplotlib.pyplot as plt
'''
彩色图片操作示例
'''
def read_color_picture():
# 读取图片
img = cv2.imread('images/color-img.png')
# 获取图片形状 (返回长row、宽heights、通道channels)
shape = img.shape
print("图片形状为: ", shape)
print(img.shape)
# 获取图片大小(返回row*heights*channels)
size = img.size
print("图片大小为: ", size)
# 图片类型
dtype = img.dtype
print(dtype)
# opencv中,图片的排序为(B,G,R)
# 拿到某个像素点的bgr
(b, g, r) = img[6, 40]
print(b, g, r)
# 单独取某个像素点的蓝色
b = img[6, 40, 0]
print(b)
# 重新给像素点复制,更换颜色
img[6, 40] = (0, 0, 255) # 变成红色
# 显示图片
cv2.imshow('img', img)
# 等待
cv2.waitKey(0)
# 关闭图片
cv2.destroyAllWindows()
'''
灰色图片操作示例
'''
def read_gray_picture():
# 读取图片
img = cv2.imread('images/gray-img.png', cv2.IMREAD_GRAYSCALE)
# 获取图片形状 (返回长row、宽heights、通道channels)
shape = img.shape
print("图片形状为: ", shape)
print(img.shape)
# 获取图片大小(返回row*heights*channels)
size = img.size
print("图片大小为: ", size)
# 图片类型
dtype = img.dtype
print(dtype)
# opencv中,图片的排序为(B,G,R)
# 拿到某个像素点
print(img[6, 40])
# 显示图片
cv2.imshow('img', img)
# 等待
cv2.waitKey(0)
# 关闭图片
cv2.destroyAllWindows()
def read_bgr():
import cv2
import matplotlib.pyplot as plt
import os
# 获取当前脚本所在的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(current_dir, 'images', 'color-img.png')
try:
# 尝试读取图片
img = cv2.imread(image_path)
if img is None:
raise FileNotFoundError(f"Image file not found at {image_path}")
# 转换 BGR 到 RGB
image_new = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
print(img.shape)
# 创建子图
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
# 显示原始图片
axes[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
axes[0].set_title('Original Image')
axes[0].axis('off')
# 显示转换后的图片
axes[1].imshow(image_new)
axes[1].set_title('Converted Image')
axes[1].axis('off')
# 展示图片
plt.show()
plt.close()
except FileNotFoundError as e:
print(e)
except Exception as e:
print(f"An error occurred: {e}")
# 对图片进行像素扩大化:小图变大图
def enlarge_image():
# 读取图像
image = cv2.imread('images/pengge.jpg')
# 获取图像的原始尺寸
height, width = image.shape[:2]
# 设置新的尺寸,例如将图像放大到原来的2倍
new_width = int(width * 10)
new_height = int(height * 10)
# 使用cv2.resize()进行图像缩放
# 第三个参数是插值方法,这里使用cv2.INTER_LINEAR
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
# # 显示结果=
# cv2.imshow('Resized Image', resized_image)
# cv2.waitKey(0)
cv2.imwrite('images/penggeBig.jpg', resized_image)
cv2.destroyAllWindows()
if __name__ == "__main__":
enlarge_image()
从摄像头读取视频
import argparse
import cv2
parser = argparse.ArgumentParser()
parser.add_argument('camera_id', type=int, default=0, help='camera ID')
args = parser.parse_args()
print(args.camera_id)
# 获取摄像头的视频流
capture = cv2.VideoCapture(args.camera_id)
# 获取帧宽度、高度、fps
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
# 打印出来这些数据查看
print(f'width: {width}, height: {height}, fps: {fps}')
# 判断摄像头是否打开
if not capture.isOpened():
print('Error opening video stream or file')
exit()
# 从摄像头读取视频,直到关闭
while capture.isOpened():
# 通过摄像头捕获帧
ret, frame = capture.read()
if not ret:
print('Can\'t receive frame (stream end?). Exiting ...')
break
# 把捕获的帧变成灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 显示原来视频流
cv2.imshow('frame', frame)
# 显示灰度的视频流
cv2.imshow('frame', gray)
# 键盘敲击q,退出
if cv2.waitKey(1) == ord('q'):
break
# 释放所有资源,并关闭窗口
capture.release()
cv2.destroyAllWindows()
从视频文件读取视频
import argparse
import cv2
parser = argparse.ArgumentParser()
parser.add_argument('video_path', help='视频文件路径')
args = parser.parse_args()
print(args.video_path)
# 加载视频文件
capture = cv2.VideoCapture(args.video_path)
# 获取摄像头的视频流q
capture = cv2.VideoCapture(args.video_path)
# 获取帧宽度、高度、fps
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
# 从摄像头读取帧
ret, frame = capture.read()
while ret:
cv2.imshow('frame', frame)
# 再次读取帧
ret, frame = capture.read()
# 键盘敲击q,退出
if cv2.waitKey(1) == ord('q'):
break
# 释放所有资源,并关闭窗口
capture.release()
cv2.destroyAllWindows()
读取摄像头并保存视频
import argparse
import cv2
parser = argparse.ArgumentParser()
parser.add_argument('camera_id', type=int, default=0, help='camera ID')
parser.add_argument('output_file', type=str, default='output.avi', help='output file')
args = parser.parse_args()
# 获取摄像头的视频流
capture = cv2.VideoCapture(args.camera_id)
# 判断摄像头是否打开
if not capture.isOpened():
print('Error opening video stream or file')
exit()
# 获取帧的属性
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
# 对视频进行编码
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 初始化视频写入对象
# 参数1: 输出文件的路径和名称
# 参数2: 视频编解码器,例如 'XVID' 或 'MJPG'
# 参数3: 视频的帧率
# 参数4: 视频帧的大小,为一个元组,包含宽度和高度
video_writer = cv2.VideoWriter('output.avi', fourcc, fps, (width, height))
# 读取摄像头
while capture.isOpened():
# 通过摄像头捕获帧
ret, frame = capture.read()
if not ret:
print('Can\'t receive frame (stream end?). Exiting ...')
break
# 把捕获的帧变成灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 显示原来视频流
cv2.imshow('frame', frame)
# 显示灰度的视频流
cv2.imshow('frame', gray)
video_writer.write(gray)
# 键盘敲击q,退出
if cv2.waitKey(1) == ord('q'):
break
# 释放所有资源,并关闭窗口
capture.release()
video_writer.release()
cv2.destroyAllWindows()
查看灰度直方图
灰度直方图在计算机视觉的占有很多地位,建议去查一下了解一下。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def show_image(img,title,position):
# 顺序转换:BGR -> RGB
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 显示标题
plt.subplot(position)
plt.title(title)
plt.imshow(img_rgb)
# 显示直方图
def show_histogram(img,title,position,color):
# 计算图像的直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
# 绘制直方图
plt.subplot(position)
plt.title(title)
plt.xlabel('xlabel')
plt.ylabel('ylabel')
# 范围
plt.xlim([0, 256])
plt.plot(hist, color=color)
def main():
# 创建画布
plt.figure(figsize=(10, 5))
plt.suptitle('Histogram', fontsize=16, fontweight='bold')
# 加载图片
img = cv2.imread('images/color-img.png')
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示图片
show_image(img, 'Original Image', 121)
# 显示灰度图
show_image(gray, 'Gray Image', 122)
# 显示直方图
show_histogram(gray, 'Gray Histogram', 221, 'r')
if __name__ == '__main__':
main()
plt.show()
图片上画文字
import cv2
import matplotlib.pyplot as plt
import numpy as np
# 设置字体颜色常量字典
colors = {
'red': (0, 0, 255),
'green': (0, 255, 0),
'blue': (255, 0, 0),
'yellow': (0, 255, 255),
'cyan': (255, 0, 255),
'magenta': (255, 255, 0),
'white': (255, 255, 255),
'black': (0, 0, 0)
}
def show_image(img, title):
# 顺序转换:BGR -> RGB
img_rgb = img[:, :, ::-1]
# 显示标题
plt.title(title)
plt.imshow(img_rgb)
plt.show()
# 创建一个400x400像素的黑色画布,用于后续绘制操作。该画布是一个三维数组,每个像素有三个通道(RGB),数据类型为8位无符号整数。
canvas = np.zeros((400, 400, 3), np.uint8)
# 将画布填充为白色。canvas.fill(255) 中的参数 255 表示使用白色(在灰度模式下,255 表示最亮的白色)填充整个画布。
canvas.fill(255)
'''
在坐标(100, 100)处绘制文本“Hello World”
使用字体cv2.FONT_HERSHEY_SIMPLEX,字体大小为1
文本颜色为红色,线条粗细为2像素
'''
cv2.putText(canvas, 'Hello World', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, colors['red'], 2)
if __name__ == '__main__':
# 调用方法展示
show_image(canvas, 'Text on Black Canvas')
haar识别人脸
import cv2
import matplotlib.pyplot as plt
# 显示图片
def show_image(img, title, position):
# bgr -> rgb
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.title(title)
plt.subplot(2, 2, position)
plt.imshow(img_rgb)
plt.axis('off')
# 绘制人脸
def plot_face(img, faces):
if not faces.any() :
print("未检测到人脸")
return img
print("检测到人脸{}", faces)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
return img
def main(image_path='images/many_face.jpg', cascade_path='data/haarcascades/haarcascade_frontalface_default.xml'):
try:
# 读取图片
img = cv2.imread(image_path)
if img is None:
print('图片不存在')
return
# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建人脸识别分类器
face_cascade = cv2.CascadeClassifier(cascade_path)
if face_cascade.empty():
print('分类器加载失败')
return
# 识别人脸
faces = face_cascade.detectMultiScale(gray, 1.1, 3)
# 绘制人脸并获取结果图片
img_face_result = plot_face(img.copy(), faces)
# 创建画布
plt.figure(figsize=(10, 10))
plt.suptitle('Face Recognition', fontsize=16, fontweight='bold')
# 显示原始图片和绘制人脸后的图片
show_image(img, 'Original Image', 1)
show_image(img_face_result, 'Face Result', 2)
# 最后显示所有图像
plt.show()
# 释放所有资源
cv2.destroyAllWindows()
except Exception as e:
print(f"发生错误: {e}")
if __name__ == '__main__':
main()
haar从视频流中读取人脸
import cv2
import matplotlib.pyplot as plt
# 显示图片
def show_image(img, title, position):
# bgr -> rgb
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.title(title)
plt.subplot(2, 2, position)
plt.imshow(img_rgb)
plt.axis('off')
# 绘制人脸
def plot_face(img, faces):
print("检测到人脸{}", faces)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
return img
def main(image_path='images/many_face.jpg', cascade_path='data/haarcascades/haarcascade_frontalface_default.xml'):
try:
# 获取摄像头的视频流 默认写死0
capture = cv2.VideoCapture(0)
# 获取帧宽度、高度、fps
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = capture.get(cv2.CAP_PROP_FPS)
# 判断摄像头是否打开
if not capture.isOpened():
print('找不到摄像头视频流')
exit()
# 从摄像头读取视频,直到关闭
while capture.isOpened():
# 通过摄像头捕获帧
ret, frame = capture.read()
if not ret:
print('找不到视频帧')
break
# 把捕获的帧变成灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 显示原来视频流
cv2.imshow('frame', frame)
# 显示灰度的视频流
cv2.imshow('frame', gray)
# 创建人脸识别分类器
face_cascade = cv2.CascadeClassifier(cascade_path)
if face_cascade.empty():
print('分类器加载失败')
return
# 识别人脸
faces = face_cascade.detectMultiScale(gray, 1.1, 3)
# 绘制人脸并获取结果图片
img_face_result = plot_face(frame.copy(), faces)
# 显示绘制完的视频流
cv2.imshow('plotface', img_face_result)
# 键盘敲击q,退出
if cv2.waitKey(1) == ord('q'):
break
# 创建画布
# plt.figure(figsize=(10, 10))
# plt.suptitle('Face Recognition', fontsize=16, fontweight='bold')
#
# # 显示原始图片和绘制人脸后的图片
# show_image(img, 'Original Image', 1)
# show_image(img_face_result, 'Face Result', 2)
#
# # 最后显示所有图像
# plt.show()
# 释放所有资源
capture.release()
cv2.destroyAllWindows()
except Exception as e:
print(f"发生错误: {e}")
if __name__ == '__main__':
main()
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)