简介

由于给部门进行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()

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐