【OpenCV实现图片以及视频的读取、显示、保存以及绘图函数】

news2024/11/20 13:33:13

文章目录

    • 图片
    • 视频
    • 从文件读取视频
    • 保存一个视频
    • 绘图函数

图片

OpenCV(Open Source Computer Vision Library)是一个广泛应用于计算机视觉和图像处理领域的开源库。它提供了丰富的图像处理工具和算法,使得开发者能够轻松实现各种图像处理任务。
包括:
从文件中读取图像
通过OpenCV窗口展示图像
将一个图像写入文件
代码:


import cv2 as cv
import sys

# 通过cv.samples.findFile()函数读取图像文件
img = cv.imread(cv.samples.findFile("img_2.png"))

# 检查图像是否成功加载
if img is None:
    sys.exit("Could not read the image.")  # 如果加载失败,退出程序并显示错误消息

# 显示图像窗口
cv.imshow("Display window", img)

# 等待用户按键输入,返回按键的ASCII码(以毫秒为单位,0表示一直等待)
k = cv.waitKey(0)

# 如果用户按下键盘上的 "s" 键
if k == ord("s"):
    # 将图像保存为 "starry_night.png"
    cv.imwrite("starry_night.png", img)
    print("Image saved as 'starry_night.png'")  # 显示保存成功的消息

解释:使用OpenCV加载名为 “img_2.png” 的图像文件。如果图像加载失败,程序将显示错误消息并退出。然后,它将图像显示在一个窗口中,等待用户按键输入。如果用户按下键盘上的 “s” 键,程序将保存当前图像为 “starry_night.png” 并显示保存成功

视频

在图像处理中,经常需要从摄像头中捕获视频流进行处理。OpenCV为我们提供了一个简单而强大的接口来实现这个任务。在这个入门任务中,将如何从摄像头(通常是笔记本电脑上的摄像头)捕获视频流,将视频转换为灰度图像,然后显示出来。

包括:
读取视频,显示视频和保存视频。
从相机中捕获视频和展示它。
将会使用到这些函数:cv.VideoCapture(),cv.VideoWriter()

首先,我们需要创建一个VideoCapture对象,这个对象用于捕获视频。它的参数可以是设备的索引或者是视频文件的名称。设备的索引用于区分连接到计算机的不同摄像头,通常我们会使用0或者-1表示默认连接的摄像头,如果有多个摄像头,可以使用1、2等数字来指定不同的摄像头。

接着,我们可以使用VideoCapture对象的方法逐帧捕获视频,进行处理。在处理完视频之后,不要忘记释放摄像头资源,以确保其他应用程序可以正常使用摄像头。

import numpy as np
import cv2 as cv

# 打开摄像头(设备索引为0,通常表示默认连接的摄像头)
cap = cv.VideoCapture(0)

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("Cannot open camera")  # 如果打开失败,输出错误消息
    exit()

while True:
    # 逐帧捕获视频
    ret, frame = cap.read()

    # 如果ret为False,说明未成功捕获帧,可能是视频流结束
    if not ret:
        print("Can't receive frame (stream end?). Exiting...")
        break  # 退出循环

    # 将彩色帧转换为灰度图像
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    # 显示处理后的灰度帧
    cv.imshow('frame', gray)

    # 等待用户按键输入,如果是'q'键则退出循环
    if cv.waitKey(1) == ord('q'):
        break

# 释放摄像头资源
cap.release()

# 关闭所有窗口
cv.destroyAllWindows()

cap.read()函数返回一个布尔值,如果成功读取到帧,返回True,否则返回False。因此,我们可以通过检查这个返回值来判断视频是否到达结尾。

有时,cap对象可能没有成功初始化,这时候代码会出现错误。我们可以使用cap.isOpened()函数来检查是否成功初始化。如果返回True,说明初始化成功;否则,我们可以使用cap.open()函数尝试重新打开它。

此外,我们还可以使用cap.get(propld)函数获取视频的属性,其中propld是一个从0到18的数字,代表视频的不同属性。你可以查看OpenCV文档中关于cv::VideoCapture::get()函数的详细信息。一些属性的值可以使用cap.set(propld, value)函数进行设置,value是你想要设置的值。
在这里插入图片描述
当处理视频时,我们经常需要获取和设置帧的属性,例如宽度和高度。OpenCV提供了方便的方法来实现这些操作。例如,我们可以使用cap.get(cv.CAP_PROP_FRAME_WIDTH)和cap.get(cv.CAP_PROP_FRAME_HEIGHT)来获取帧的默认宽度和高度,它们默认返回值是640×480。
如果我们希望修改帧的尺寸,比如将宽度和高度设置为320×240,我们只需调用以下代码:

ret_width = cap.set(cv.CAP_PROP_FRAME_WIDTH, 320)  # 设置帧的宽度为320
ret_height = cap.set(cv.CAP_PROP_FRAME_HEIGHT, 240)  # 设置帧的高度为240

这里的ret_width和ret_height将返回设置操作的结果,通常为True表示设置成功,False表示设置失败。通过这种方式,我们可以方便地控制视频帧的尺寸,以满足特定需求。

注:如果一直报错,请确保摄像头开启。

从文件读取视频

从文件中读取视频和从摄像头中捕获视频的基本原理是相同的,唯一的区别在于需要将设备下标(在这种情况下是视频文件的路径)传递给cv.VideoCapture()函数。然后,在使用cv.waitKey()时,我们需要设置适当的等待时间来控制视频的播放速度。

如果等待时间设置得太短,视频将以非常快的速度播放,难以观察。而如果等待时间设置得太长,视频会变得非常慢,这就是制作慢动作视频的方法之一。通常情况下,等待时间应该在正常速度下的每帧间隔内,一般为25毫秒。

import numpy as np
import cv2 as cv

# 打开视频文件('fan.mp4'是视频文件的路径)
cap = cv.VideoCapture('fan.mp4')

while cap.isOpened():
    # 逐帧读取视频
    ret, frame = cap.read()

    # 如果ret为False,说明未成功读取帧,可能是视频流结束
    if not ret:
        print("Can't receive frame (stream end?). Exiting...")
        break  # 退出循环

    # 将彩色帧转换为灰度图像
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    # 显示处理后的灰度帧
    cv.imshow('frame', gray)

    # 等待25毫秒,如果用户按下'q'键则退出循环
    if cv.waitKey(25) == ord('q'):
        break

# 释放视频文件资源
cap.release()

# 关闭所有窗口
cv.destroyAllWindows()

确保安装了合适版本的ffmpeg或者gstreamer。大多数视频捕获出错就是因为安装了错误的ffmpeg/gstreamer。

保存一个视频

当我们想要一帧一帧地捕获视频、进行处理,并保存为视频文件时,我们需要创建一个 VideoWriter 对象。首先,我们要确定输出文件的名字(例如:‘output.avi’)。接下来,我们需要选择合适的 FourCC 编码,确定帧率(fps)和尺寸。最后,我们还需要设置一个标志 isColor,以确定编码器是接受彩色帧还是灰度帧。
FourCC是一个用来指定视频编解码器的4字节代码,可用代码列表可以在 fourcc.org 中找到。不同平台(系统)有不同代码,下面这些是我认为比较适用的:

•在Fedora(Linux):DIVX, XVID, MJPG, X264, WMV1, WMV2(XVID最合适,MJPG用来生成高规格的视频,而X264正相反)
•在Windows:DIVX(写这个的人也不确定是不是最好的)
•在OSX:MJPG (.mp4), DIVX (.avi), X264 (.mkv)

FourCC的传参方式(以MJPG为例)可以像cv.VideoWriter_fourcc(‘M’, ‘J’, ‘P’, ‘G’)或者cv.VideoWriter_fourcc(*‘MJPG’)

import numpy as np
import cv2 as cv

# 打开默认摄像头(设备下标为0)
cap = cv.VideoCapture(0)

# 定义视频编解码器和创建VideoWriter对象,fourcc是用于指定视频编码格式的四字符代码
fourcc = cv.VideoWriter_fourcc(*'DIVX')  # 使用DIVX编码器
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))  # 输出视频的文件名、编解码器、帧率和帧大小

while cap.isOpened():
    # 逐帧读取视频
    ret, frame = cap.read()

    # 如果ret为False,说明未成功读取帧,可能是视频流结束
    if not ret:
        print("Can't receive frame (stream end?). Exiting...")
        break  # 退出循环

    # 将帧上下颠倒(镜像效果)
    frame = cv.flip(frame, 0)

    # 将帧写入输出视频文件
    out.write(frame)

    # 显示处理后的帧
    cv.imshow('frame', frame)

    # 等待1毫秒,如果用户按下'q'键则退出循环
    if cv.waitKey(1) == ord('q'):
        break

# 释放摄像头和输出视频文件资源
cap.release()
out.release()

# 关闭所有窗口
cv.destroyAllWindows()

绘图函数

通过OpenCV绘画不同的几何形状
使用到这些函数:cv.line()、cv.circle()、cv.rectangle()、cv.ellipse()、cv.putText()等等。
包括:
img: 你想绘图的地方

color: 形状的颜色,通过元组给参。对于灰度,只需要传递标量值。

thickness: 线或者圆的厚度。如果是-1将填充封闭图形。缺省值 thickness = 1

lineType: 线条的种类,

画线

import numpy as np
import cv2 as cv

# 创建一个全黑的图像,大小为512x512,3表示RGB颜色通道
img = np.zeros((512, 512, 3), np.uint8)

# 画一条厚度为5px的蓝线,起点为(0, 0),终点为(511, 511),颜色为蓝色 (255, 0, 0),线宽为5px
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)

# 画一个矩形,左上角坐标为(384, 0),右下角坐标为(510, 128),颜色为绿色 (0, 255, 0),线宽为3px
cv.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)

# 画一个实心圆,圆心为(447, 63),半径为63,颜色为红色 (0, 0, 255)-1表示填充圆
cv.circle(img, (447, 63), 63, (0, 0, 255), -1)

# 画一个椭圆,中心为(256, 256),长轴和短轴分别为10050,椭圆角度为0180度,颜色为白色 (255, 255, 255)-1表示填充椭圆
cv.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1)

# 定义多边形的顶点坐标
pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
# 将多边形的顶点坐标变为3维数组
pts = pts.reshape((-1, 1, 2))
# 画一个多边形,True表示闭合多边形,颜色为黄色 (0, 255, 255)
cv.polylines(img, [pts], True, (0, 255, 255))

# 定义字体类型
font = cv.FONT_HERSHEY_SIMPLEX
# 在图像上添加文字'OpenCV',起始坐标为(10, 500),字体大小为4,颜色为白色 (255, 255, 255),线宽为2px,线型为抗锯齿
cv.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv.LINE_AA)

# 在窗口中显示图像
cv.imshow('demo', img)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)

在画一条线的时候,你需要传递线条的开始和结束的坐标。下面的代码创建了黑色的背景以及画了一条从左上到右下的蓝色直线。

画长方形
为了画矩形,你需要给出矩形的左上和右下坐标。这次会在右上画出一个绿色的矩形。

cv.circle(img, (447, 63), 63, (0, 0, 255), -1)

画椭圆
椭圆需要的参数会比较多。第一个参数是中心的位置(x, y)。第二个参数是垂直的两条轴的长度。angle是椭圆沿逆时针方向旋转的角度。startAngle和endAngle是沿顺时针方向椭圆弧端点的夹角(0和360代表了完整的椭圆)。更多的细节可以查看文档。下面的例子在中心画了半个椭圆弧。

cv.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1)

画多边形
首先你需要所有顶点的坐标。把这些坐标放入一个数据类型为int32的 1×2的矩阵中。下面的例子画了一个黄色四边形

pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
pts = pts.reshape((-1, 1, 2))
cv.polylines(img, [pts], True, (0, 255, 255))

如果第三个参数是False,你只会得到折线而不是封闭图形。 cv.pplylines()可以画出折线。只需要把所有你想画的线条放进一个列表,然后传参进去。这比用cv.lines一条一条画要快得多。

给图像添加文字

当使用cv.putText()函数时,确定以下信息:

要写入的文字数据:确定想要在图像上写入的文本内容,例如:"OpenCV"。

放置的位置坐标:选择文字的起始点坐标,通常是左下角作为起点,例如(10, 500)。

字体:选择适合的字体。OpenCV提供了不同的字体,可以在文档中查找支持的字体选项。

字的大小:指定文字的大小,通常以字体高度为单位。例如,字体大小为4。

颜色:选择文字的颜色,以RGB格式表示。例如,白色可以表示为(255, 255, 255)。

线宽和线条种类:可以选择文本的厚度,通常用整数表示。例如,线宽为2。同时,你也可以指定线条的种类,例如cv.LINE_AA,这样可以获得更好的视觉效果。

比如下面的代码在图像上写了白色的OpenCV

font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv.LINE_AA)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1111956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

办鹿uniapp小程序(一)

一、项目初始化 1. appid 》 公司给你 wxc82730a0fc15e28a 2. 开发者身份 》 公司给你添加 小程序官网:小程序 管理》成员管理》项目成员 1、 uniapp ui组件 (uView) 如果采用npm安装方式在 小程序端不生效 1.1 采用插件的形式安装&#xf…

pycharm操作git、前后端项目上传到gitee

pycharm操作git 之前用命令做的所有操作,使用pychrm点点就可以完成 克隆代码 上方工具栏Git ⇢ \dashrightarrow ⇢ Clone ⇢ \dashrightarrow ⇢ 填写地址(http、ssh) 提交到暂存区,提交到版本库,推送到远程 直接…

Nmap端口服务 之 CentOS7 关于启动Apache(httpd)服务、telnet服务、smtp服务、ftp服务、sftp服务

Nmap端口服务 之 CentOS7 关于启动Apache(httpd)服务、telnet服务、smtp服务、ftp服务、sftp服务 一. CentOS7 安装配置SFTP服务器详解一、SFTP简介二、关闭防火墙三、安装SSH服务在CentOS7中,sftp只是ssh的一部分,所以采用yum来安装ssh服务即可1. 查看是否已经安装了ssh2.…

promise返回值多层嵌套

实际上打印的是promise的res不是api接口返回值 因为用apifox测试开发服务器的代理接口,和不加代理测试返回值相同: http://localhost:3030是vue开发代理。 "D:\code\jeecg\vue\job-app-master\manifest.json" "proxy" : {"/ap…

嵌入式实习难找怎么办?

今日话题,嵌入式实习难找怎么办?个人建议如果找不到实习机会,可以回归学习嵌入式所需的知识,积累项目经验或者回顾之前参与过的项目,将它们整理复盘。如果还有时间,可以再尝试找实习,如果找不到…

【CANoe】Canoe的 I/O功能-以VN1640A为例

文章目录 一、配置CH5 IO通道二、Trace窗口勾选系统变量三、实例1、数字量输入2、模拟量输入设置电压值的读取周期为100ms在Trace窗口中显示当前电压 3、控制电源是否输出电压到外部电路3.1CAPL脚本编写3.2实操3.3补充:数字输出功能DOUT(Output OD)的使用 四、CANoe…

【算法练习Day23】 复原 IP 地址子集子集 II

​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 复原 IP 地址子集子集 II总…

Unity之ShaderGraph如何模拟水波实现顶点波动

前言 今天我们实现类似水波纹的顶点波动效果 如下所示: 主要节点 Tilling And Offset:分别通过输入Tiling和Offset平铺和偏移输入UV的值。这通常用于细节贴图和随时间滚动的纹理。 Gradient Noise:根据输入UV生成梯度或Perlin噪声。生成…

骰子涂色(Cube painting, UVa 253)rust解法

输入两个骰子,判断二者是否等价。每个骰子用6个字母表示,如图4-7所示。 例如rbgggr和rggbgr分别表示如图4-8所示的两个骰子。二者是等价的,因为图4-8(a)所示的骰子沿着竖直轴旋转90之后就可以得到图4-8(b&a…

民宿管理系统应该怎么选择?民宿系统有哪些作用?

开民宿的朋友都知道,虽然民宿少则5-6间房,多则100-200间房,体量看起来不大,但是管理起来却需要费很多精力。房态最主要的有5种:在住、预定、待打扫、待入住、空房,假如是5间房,那就是25种房态&a…

Unity3D 拖拽赋值组件与通过Find赋值组件的优点与缺点详解

Unity3D是一款流行的游戏开发引擎,提供了丰富的功能和工具,使开发人员能够轻松创建高质量的游戏。在Unity3D中,我们经常需要通过拖拽赋值组件或通过Find赋值组件来实现不同对象之间的交互。本文将详细介绍这两种方法的优点和缺点,…

Systemverilog断言介绍(一)

3 Introduction to systemverilog assertions 为了利用形式验证(FV)的力量来证明设计的正确性,首先必须有一种表达您的设计是否正确的方式。最流行的方法是通过property来实现,使用SystemVerilog Assertions(SVA&#…

Halcon 3D相关案例分享

文章目录 一、预处理1、平滑滤波算子说明平滑效果图 二、检测1、外观缺陷检测算子说明缺陷检测效果图 2、点云边界框算子说明边界框效果图 3、平面度检测算子说明平面度效果图 三、量测1、高度测量算子说明测量效果图 2、体积测量算子说明测量效果图 四、配准1、根据模型配准算…

【算法|动态规划No.23】leetcode376. 摆动序列

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 🍔本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望…

doris operator部署Doris集群教程

doris operator部署Doris集群教程 前言部署流程 前言 kubernetes Operator是遵循kubernetes API和控制器模式,它主要用来封装运维业务逻辑的软件。它利用kubernetes的自定义资源定义(CRD)扩展API,并通过控制器模式监听资源对象&a…

CVPR 2018 基于累积注意力的视觉定位 Visual Grounding via Accumulated Attention 详解

Abstract: VG面临的主要挑战有3个:1 )查询的主要焦点是什么;2 )如何理解图像;3 )如何定位物体。 在本文中,我们将这些挑战形式化为三个注意力问题,并提出了一个累积注意力( A-ATT )机制来共同推理其中的挑战…

找不到msvcr120.dll无法执行代码?教你6种方法快速解决问题

在现代的计算机编程中,我们经常会遇到各种各样的问题。其中,“由于找不到msvcr120.dll无法执行代码”的问题是许多开发者都会遇到的一个常见难题。这个问题通常发生在我们试图运行使用Visual Studio 2013编译的程序时,因为msvcr120.dll是Micr…

【QT】QTreeWidget

新建项目 第一步:设置头标签 第二步:设置item 第三步:创建子item,挂载在顶层item下 完整代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::W…

Unity Animation--动画剪辑(动画游戏对象)

保存新的动画剪辑后,就可以开始添加关键帧了。 可以使用两种不同的方法为GameObject设置动画。 Unity“动画”窗口:“记录模式”和“预览模式”。 记录模式下的动画窗口 在记录模式下,当您移动,旋转或以其他方式修改动画GameOb…

2022年下半年 软件设计师 上午试卷(前21题)

以下关于RISC(精简指令集计算机)特点的叙述中,错误的是 (1) 。 (1) A. 对存储器操作进行限制,使控制简单化 B. 指令种类多,指令功能强 C. 设置大量通用寄存器 D. 选…