9月9日OpenCV学习笔记——保存摄像头读取到的视频、图像变换、灰度直方图


前言

本文为9月9日OpenCV学习笔记——保存摄像头读取到的视频、图像变换、灰度直方图,分为四个章节:

  • 从视频文件读取;
  • 保存摄像头读取到的视频;
  • 图像的8种变换;
  • 灰度直方图。

一、从视频文件读取

# 从视频文件读取

import cv2 as cv
import argparse

# 获取参数
parser = argparse.ArgumentParser()

# 添加参数
parser.add_argument("video_path", help="视频文件的路径")

# 解析参数
args = parser.parse_args()

# 加载视频文件
capture = cv.VideoCapture(args.video_path)

# 读取视频
ret, frame = capture.read() # ret: 是否读取到了帧(图片)
while ret:
    cv.imshow("video", frame)
    ret, frame = capture.read() # 继续读取帧
    if cv.waitKey(20) & 0xFF == ord("q"):
        break

capture.release()
cv.destroyAllWindows()

1


二、保存摄像头读取到的视频

  • 视频编码:fourcc = cv2.VideoWriter_fourcc(*'XVID')
  • 灰度写入视频文件:cv2.VideoWriter(args.video_output, fourcc, int(fps), (int(frame_width), int(frame_height)), False) .
# 保存从摄像头保存到的视频

import cv2 as cv
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("video_output", help="保存视频的路径")
args = parser.parse_args()

# 捕获摄像头
capture = cv.VideoCapture(0)

# 判断是否打开摄像头
if capture.isOpened() is False:
    print("Camera Error!")

# 获取帧的属性:宽、高、FPS
frame_width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
fps = capture.get(cv.CAP_PROP_FPS)

print("帧的宽度: {}".format(frame_width))
print("帧的高度: {}".format(frame_height))
print("FPS: {}".format(fps))

# 对视频进行编码
fourcc = cv.VideoWriter_fourcc(*"XVID")
output_gray = cv.VideoWriter(args.video_output, fourcc, int(fps), (int(frame_width), int(frame_height)), False)

# 读取摄像头
while capture.isOpened():
    ret, frame = capture.read() # 一帧一帧读取
    if ret:
        # 将读取到的帧转换为灰度
        gray_frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        # 将转换后的帧写入到新的视频文件中
        output_gray.write(gray_frame)
        # 显示转换后的效果
        cv.imshow("gray", gray_frame)
        # 等待或按 q 键退出
        if cv.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        break

# 释放资源
capture.release()
output_gray.release()
cv.destroyAllWindows()

三、图像的8种变换

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv.imread("images/blades.png")
plt.imshow(img)

# h, w, c
height, width, channel = img.shape
print(height, width, channel)
>>> 550 865 3

2

  1. 图像放大、缩小:
# cv.resize() 放大
resized_img = cv.resize(img, (width*2, height*2), interpolation=cv.INTER_LINEAR)
plt.imshow(resized_img)

# 缩小
small_img = cv.resize(img, None, fx=0.5, fy=0.5, interpolation=cv.INTER_LINEAR)
plt.imshow(small_img)

3
4

  1. 图像平移:
# 平移 transformation cv.warpAffine()
height, width, = img.shape[:2]
M1 = np.float32([[1, 0, 200], [0, 1, 50]]) # 平移矩阵,图像向右移动 200个像素,向下移动 50个像素
move_img = cv.warpAffine(img, M1, (width, height))
plt.imshow(move_img)

M1 = np.float32([[1, 0, -100], [0, 1, -50]]) # 平移矩阵,图像向左移动 200个像素,向上移动 50个像素
move_img2 = cv.warpAffine(img, M1, (width, height))
plt.imshow(move_img2)

5
6

  1. 图像旋转:
height, width = img.shape[:2]
center = (width // 2, height // 2) # 中心点
M3 = cv.getRotationMatrix2D(center, 180, 1) # 正数:逆时针;1:旋转过程中没有缩放
rotation_img = cv.warpAffine(img, M3, (width, height))
plt.imshow(rotation_img)

7

  1. 图像仿射变换:
# cv.getAffineTransform(p1, p2)
p1 = np.float32([[120, 35], [215, 45], [135, 120]])
p2 = np.float32([[135, 45], [300, 110], [130, 230]])
M4 = cv.getAffineTransform(p1, p2) # 计算一个变换矩阵
trans_img = cv.warpAffine(img, M4, (width, height))
plt.imshow(trans_img)

8

  1. 图像裁剪:
crop_img = img[20:200, 200:300]
plt.imshow(crop_img)

9

  1. 图像的位运算(AND, OR, XOR):
# 长方形
rectangle = np.zeros((300, 300), dtype="uint8")
rect_img = cv.rectangle(rectangle, (25, 25), (275, 275), 255, -1)
plt.imshow(rect_img)

10

# 圆形
rectangle = np.zeros((300, 300), dtype="uint8")
circle_img = cv.circle(rectangle, (150, 150), 150, 255, -1)
plt.imshow(circle_img)

11

# 与运算 cv.bitwise_and()
and_img = cv.bitwise_and(rect_img, circle_img)
plt.imshow(and_img)

12

# 或运算
or_img = cv.bitwise_or(rect_img, circle_img)
plt.imshow(or_img)

13

# 异或运算:两者不相同为 1
xor_img = cv.bitwise_xor(rect_img, circle_img)
plt.imshow(xor_img)

14

  1. 图像的分离和融合:
(B, G, R) = cv.split(img) # 分离
# print(B, G, R)
plt.imshow(B) 

15

# 融合
zeros = np.zeros(img.shape[:2], dtype="uint8")
plt.imshow(cv.merge([B, zeros, zeros]))

16

  1. 图像的颜色空间:
# 灰度
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
plt.imshow(gray)

17

# HSV(色度、饱和度、纯度)
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
plt.imshow(hsv)

18

# Lab
lab = cv.cvtColor(img, cv.COLOR_BGR2LAB)
plt.imshow(lab)

19


四、灰度直方图

  • 定义: 二位统计图表,两个坐标分别是统计样本(图像、视频帧)和样本的某种属性(亮度,像素值,梯度,方向,色彩等等任何特征)。

  • 意义:

    1. 图像中像素强度分布的图形表达方式;
    2. 统计了每一个强度值所具有的像素个数。
  • 特征:

    1. 不再表征任何的图像纹理信息,而是对图像像素的统计;
    2. 由于同一物体无论是旋转还是平移在图像中都具有相同的灰度值,因此直方图有平移不变性、放缩不变性等。
  • 参数: cv2.calcHist(images, channels, mask, histSize, range[hest[, accumulate]])

    1. images:整型类型(uint8和float32)的原图(list形式显示);
    2. channels : 通道的索引,例如:[0]代表灰度图片,[0],[1],[2]代表多通道;
    3. mask : 计算图片指定区域的直方图。如果mask为none,那么计算整张图;
    4. histSize( bins ) : 每个色调值(范围: 0 ~ 255)对应的像素数量。在OpenCV中,用histSize表示bins;
    5. range : 强度值的范围,[0, 256]。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

# 方法:显示图片
def show_image(image, title, pos):
    # BGR to RGB
    image_RGB = image[:, :, ::-1] # 倒序 channel
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos)  # 定位
    plt.imshow(image_RGB)

# 方法:显示图片的灰度直方图
def show_histogram(hist, title, pos, color):
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos)
    plt.xlabel("Bins")
    plt.ylabel("Pixels")
    plt.xlim([0, 256]) # 横轴范围
    plt.plot(hist, color=color) # 绘制直方图


# 主函数
def main():
    # 创建一个画布
    plt.figure(figsize=(15, 6)) # 画布大小
    plt.suptitle("Gray Image Histogram", fontsize=14, fontweight="bold") # 设置标题形式

    # 加载图片
    img = cv.imread("images/vonmises.png")

    img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # 计算灰度图的直方图
    hist_img = cv.calcHist([img_gray], [0], None, [256], [0, 256])

    # 展示灰度直方图
    # 灰度图转换成 BGR
    img_BGR = cv.cvtColor(img_gray, cv.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    show_histogram(hist_img, "gray image histogram", 4, "m")

    plt.show()

if __name__ == '__main__':
    main()

2

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

# 方法:显示图片
def show_image(image, title, pos):
    # BGR to RGB
    image_RGB = image[:, :, ::-1] # 倒序 channel
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos)  # 定位
    plt.imshow(image_RGB)

# 方法:显示图片的灰度直方图
def show_histogram(hist, title, pos, color):
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos)
    plt.xlabel("Bins")
    plt.ylabel("Pixels")
    plt.xlim([0, 256]) # 横轴范围
    plt.plot(hist, color=color) # 绘制直方图


# 主函数
def main():
    # 创建一个画布
    plt.figure(figsize=(15, 6)) # 画布大小
    plt.suptitle("Gray Image Histogram", fontsize=14, fontweight="bold") # 设置标题形式

    # 加载图片
    img = cv.imread("images/vonmises.png")

    img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # 计算灰度图的直方图
    hist_img = cv.calcHist([img_gray], [0], None, [256], [0, 256])

    # 展示灰度直方图
    # 灰度图转换成 BGR
    img_BGR = cv.cvtColor(img_gray, cv.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    show_histogram(hist_img, "gray image histogram", 4, "m")

    # 对图片中的每个像素值加 50
    M = np.ones(img_gray.shape, np.uint8) * 50 # 构建矩阵
    added_img = cv.add(img_gray, M)
    add_img_hist = cv.calcHist([added_img], [0], None, [256], [0, 256])  # 计算直方图
    added_img_BGR = cv.cvtColor(added_img, cv.COLOR_GRAY2BGR)
    show_image(added_img_BGR, "added image", 2)
    show_histogram(add_img_hist, "added image hist", 5, "m")

    # 对图片中的每个像素值减 50
    subtract_img = cv.subtract(img_gray, M)
    subtract_img_hist = cv.calcHist([subtract_img], [0], None, [256], [0, 256])
    subtract_img_BGR = cv.cvtColor(subtract_img, cv.COLOR_GRAY2BGR)
    show_image(subtract_img_BGR, "subtracted image", 3)
    show_histogram(subtract_img_hist, "subtracted image hist", 6, "m")


    plt.show()

if __name__ == '__main__':
    main()

3


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值