opencv-python入门学习(1)

2023-10-26

环境安装与配置

使用anaconda进行python环境的安装配置。

  1. 创建新的python环境
  2. 安装相关库(numpy、opencv-python、matplotlib)
  3. 使用pycharm时。import cv2在实际写代码的过程中,pycharm不会给出函数提醒等代码辅助,需要找到你的python环境,在文件路径中找到cv2.pyd文件并复制到上层目录,重启pycharm即可

anaconda/envs/python名/lib/site-packages/cv2

图像入门

学习简单的图像处理

图片的读取、显示和保存

三个函数:

cv.imread():读取图像

import numpy as np
import cv2 as cv
# 加载彩色灰度图像
# 参数为图片路径(相对绝对都可以)以及读取方式
# 读取方式分为:‘0’:灰度图、‘1’:彩色图、‘-1’:带alpha通道
img = cv.imread('pic1.jpg'0)

cv.imshow():显示图像

cv.imshow('image',img)
cv.waitKey(0) # 等待键盘操作
cv.destroyAllWindows()

也可以先创建窗口,再向窗口中添加图像来显示。
当创建一个新窗口时,可以传递一个整数参数(通常为 0),作为窗口的标志。该整数值可以是一组标志的按位或运算结果,其中包括:

  • WINDOW_NORMAL: 允许用户自由调整窗口大小。
  • WINDOW_AUTOSIZE: 窗口大小固定,无法更改。
  • WINDOW_OPENGL: 使用 OpenGL 渲染。
  • WINDOW_FULLSCREEN: 创建全屏窗口。

使用 WINDOW_NORMAL 标志,用户可以通过拖动边框或单击最大化/还原按钮来自由调整窗口大小。

cv.namedWindow('image',cv.WINDOW_NORMAL)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()

cv.imwrite():储存图像

import numpy as np
import cv2 as cv
img = cv.imread('pic1.jpg',0)
cv.imshow('image',img)
k = cv.waitKey(0)
if k == 27: # 等待ESC退出
 cv.destroyAllWindows()
elif k == ord('s'): # 等待关键字,保存和退出
 cv.imwrite('pic_copy.png',img)
 cv.destroyAllWindows()

视频的读取、显示和保存

从摄像机 / 文件中读取并显示视频

创建videocpture对象,创建时可以可以直接传递视频文件名(地址),或者输入摄影机的编号。对应创建出来的对象分别用于对视频文件和摄影机捕捉的画面进行操作。

import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
 print("Cannot open camera")
 exit()
while True:
 # 逐帧捕获
 ret, frame = cap.read()
 # 如果正确读取帧,ret为True
 if not ret:
 print("Can't receive frame (stream end?). Exiting ...")
 break
 # 我们在框架上的操作到这里
 gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
 # 显示结果帧e
 cv.imshow('frame', gray)
 if cv.waitKey(1) == ord('q'):
 break
# 完成所有操作后,释放捕获器
cap.release()
cv.destroyAllWindows()

还可以通过cap.get(propId) 方法访问该视频的特定信息其中,propId 表示要获取的属性标识符,可以是以下数字之一:

  • cv2.CAP_PROP_POS_MSEC: 当前帧与视频开始之间的时间(毫秒)
  • cv2.CAP_PROP_POS_FRAMES: 当前帧在视频中的索引(从 0 开始)
  • cv2.CAP_PROP_POS_AVI_RATIO: 视频文件中当前位置相对于文件末尾的比率
  • cv2.CAP_PROP_FRAME_WIDTH: 帧的宽度(像素)
  • cv2.CAP_PROP_FRAME_HEIGHT: 帧的高度(像素)
  • cv2.CAP_PROP_FPS: 帧率(每秒钟帧数)
  • cv2.CAP_PROP_FOURCC: 视频编解码器的四字码
  • cv2.CAP_PROP_FRAME_COUNT: 视频文件中的帧总数
  • cv2.CAP_PROP_FORMAT: 捕获的图像格式
  • cv2.CAP_PROP_MODE: 捕获模式
  • cv2.CAP_PROP_BRIGHTNESS: 亮度(仅适用于摄像头)
  • cv2.CAP_PROP_CONTRAST: 对比度(仅适用于摄像头)
  • cv2.CAP_PROP_SATURATION: 饱和度(仅适用于摄像头)
  • cv2.CAP_PROP_HUE: 色调(仅适用于摄像头)
  • cv2.CAP_PROP_GAIN: 增益(仅适用于摄像头)
  • cv2.CAP_PROP_EXPOSURE: 曝光(仅适用于摄像头)
  • cv2.CAP_PROP_BACKLIGHT: 背光补偿(仅适用于摄像头)
  • cv2.CAP_PROP_AUTOFOCUS: 自动对焦(仅适用于摄像头)

例如,可以通过以下代码获取视频捕获对象的宽度和高度:

import cv2

cap = cv2.VideoCapture(0)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
print("Width: ", width, " Height: ", height)

并且用cv.set(propId)可以修改视频的部分特征,其中(propId)与get函数对应

保存编辑后的视频

创建Videowriter对象,指定分辨率、帧率、视频编解码器等等,将处理后的每一帧逐帧添加进去(结束时记得释放)

  • FourCC码(视频编解码器):FourCC 是一个四字节码,用于指定视频编解码器的格式。在 OpenCV 中,FourCC 通常用于指定 VideoWriter 对象的编码格式。可以从一组预定义的编码器中选择一个或者定义自己的编码器。如果不知道要使用哪个编码器,可以使用默认的编码器(例如:MJPG)。只需将 fourcc 参数设置为 -1 或 不设置(即使用默认值)即可。
  • 在Fedora中:DIVX,XVID,MJPG,X264,WMV1,WMV2。(最好使用XVID。MJPG会生成大尺寸的视频。X264会生成非常小的尺寸的视频)
  • 在Windows中:DIVX(尚待测试和添加)
  • 在OSX中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。

下面是从摄像机捕获,沿垂直方向翻转每一帧并保存视频的代码

import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
# 定义编解码器并创建VideoWriter对象
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened():
 ret, frame = cap.read()
 if not ret:
 print("Can't receive frame (stream end?). Exiting ...")
 break
 frame = cv.flip(frame, 0)
 # 写翻转的框架
 out.write(frame)
 cv.imshow('frame', frame)
 if cv.waitKey(1) == ord('q'):
 break
# 完成工作后释放所有内容
cap.release()
out.release()
cv.destroyAllWindows()

注:cv.flip() 是 OpenCV 中的一个函数,用于图像的翻转操作。它可以实现将图像水平或垂直翻转,也可以同时进行水平和垂直方向的翻转。
0:沿 x 轴垂直翻转
1:沿 y 轴水平翻转
-1:同时沿 x 和 y 方向翻转

opencv中的绘图功能

绘制几何形状

  • 画线
    要绘制一条线,需要传递线的开始和结束坐标。我们将创建一个黑色图像,并从左上角到右下角在其上绘制一条蓝线。
import numpy as np
import cv2 as cv
# 创建黑色的图像
img = np.zeros((512,512,3), np.uint8)
# 绘制一条厚度为5的蓝色对角线
cv.line(img,(0,0),(511,511),(255,0,0),5)
  • 画矩形
    要绘制矩形,您需要矩形的左上角和右下角。这次,我们将在图像的右上角绘制一个绿色矩形。
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
  • 画圆圈
    要绘制一个圆,需要其中心坐标和半径。我们将在上面绘制的矩形内绘制一个圆。

(厚度为 ‘-1’ 代表填充)

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)

(256, 256):表示绘制椭圆的中心位置,本例中为坐标系中心点。 (100, 50):表示椭圆的长轴与短轴长度,本例中长轴为
100,短轴为 50。 0:表示椭圆相对于水平轴的旋转角度,本例中为 0。 0, 180:表示绘制的起始和结束角度,本例中从 0 度开始,到
180 度结束,即绘制半个椭圆。 255:表示绘制椭圆的颜色,本例中为白色。
-1:表示填充整个椭圆,本例中整个椭圆都被填充。

  • 画多边形
    要绘制多边形,首先需要顶点的坐标。将这些点组成形状为 ROWSx1x2 的数组,其中 ROWS 是顶点数,并且其类型应为int32。在这里,我们绘制了一个带有四个顶点的黄色小多边形。
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.polylines()可用于绘制多条线。只需创建要绘制的所有线条的列表,然后将其传递给函数即可。所有线条将单独绘制。与为每条线调用cv.line相比,绘制一组线是一种更好,更快的方法。
    pts = pts.reshape((-1,1,2)) 是 NumPy 库中的一个方法,用于将数组 pts 重新调整为新的形状。其中的参数 (-1,1,2) 表示新的形状为 (n,1,2),其中 n 的值可以由输入数组的长度和其他维度推导出来。

  • 对pts = pts.reshape((-1,1,2)): 在这个方法中,-1的含义是自动推导,表示该维度的大小将由其他维度和总长度来确定。对于 reshape 方法的第二个参数
    1,它的含义是将原来的一维数组变成一个列向量;而第三个参数 2 表示每个元素都有两个组成部分。 因此,pts.reshape((-1,1,2)) 的作用是将 pts 数组按照每行一个点,每点两个坐标的形式重构为一个三维数组,其中第一维(n, 1, 2) 表示共有 n 个点,每个点有一行两列表示其横纵坐标。

    例如,如果 pts 初始值如下:

    pts = [[0, 0], [1, 1], [2, 2], [3, 3]] 则经过 pts = pts.reshape((-1,1,2))
    处理后,pts 数组变为如下形式:

    array([[[0, 0]],
    
     [[1, 1]],
    
     [[2, 2]],
    
     [[3, 3]]]) 
    

    这个例子中,pts 数组原本是一个二维数组,其中每个元素都表示一个点的横纵坐标。通过 reshape 方法将其重构为了一个三维数组,其中第一维为点的数量,第二维为 1,第三维为 2,最终形成了一个列向量。

  • 向图像添加文本
    要将文本放入图像中,需要指定以下内容。
    • 要写入的文字数据
    • 要放置它的位置坐标(即数据开始的左下角)。
    • 字体类型(检查cv.putText文档以获取受支持的字体)
    • 字体比例(指定字体大小)
    • 常规的内容,例如颜色,厚度,线条类型等。为了获得更好的外观,建议使用lineType = cv.LINE_AA。

我们将在白色图像上写入OpenCV

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

用鼠标绘图

使用cv.setMouseCallback()
OpenCV 的鼠标事件包括:

cv.EVENT_MOUSEMOVE:鼠标在窗口上移动时触发。
cv.EVENT_LBUTTONDOWN:鼠标左键按下时触发。
cv.EVENT_RBUTTONDOWN:鼠标右键按下时触发。
cv.EVENT_MBUTTONDOWN:鼠标中键按下时触发。
cv.EVENT_LBUTTONUP:鼠标左键释放时触发。
cv.EVENT_RBUTTONUP:鼠标右键释放时触发。
cv.EVENT_MBUTTONUP:鼠标中键释放时触发。
cv.EVENT_LBUTTONDBLCLK:鼠标左键双击时触发。
cv.EVENT_RBUTTONDBLCLK:鼠标右键双击时触发。
cv.EVENT_MBUTTONDBLCLK:鼠标中键双击时触发。

这些鼠标事件可以通过 cv.setMouseCallback() 函数来绑定到窗口上。该函数的参数含义如下:

winname:窗口名称。
onMouse:回调函数,在指定的窗口上鼠标事件触发时被调用。
param:传递给回调函数的额外参数,一般为None。

下面是一个鼠标回调函数的应用。在这里,我们通过拖动鼠标来绘制矩形或圆形(取决于我们选择的模式) ,就像我们在 Paint 应用程序中所做的那样。所以我们的鼠标回调函数有两部分,一部分用于绘制矩形,另一部分用于绘制圆形。这个具体的例子对于创建和理解一些交互式应用程序非常有帮助,比如目标跟踪,图像分割地图等等。

import numpy as np
import cv2 as cv
drawing = False # 如果按下鼠标,则为真
mode = True # 如果为真,绘制矩形。按 m 键可以切换到曲线
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
	global ix,iy,drawing,mode
 	if event == cv.EVENT_LBUTTONDOWN:
	 	drawing = True
	 	ix,iy = x,y
 	elif event == cv.EVENT_MOUSEMOVE:
 		if drawing == True:
 			if mode == True:
 				cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
 			else:
 				cv.circle(img,(x,y),5,(0,0,255),-1)
 	elif event == cv.EVENT_LBUTTONUP:
 		drawing = False
 		if mode == True:
 			cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
 		else:
 			cv.circle(img,(x,y),5,(0,0,255),-1)

其中,程序开始时,drawing 和 mode 被初始化为 False 和 True。当用户按下鼠标左键时,cv.EVENT_LBUTTONDOWN 事件被触发,ix 和 iy 被设置为当前鼠标位置 (x, y),drawing 被设置为 True,表示正在绘制图形。

接着,当鼠标移动时,cv.EVENT_MOUSEMOVE 事件被触发,如果 drawing 为 True,则根据 mode 的值绘制矩形或圆形。如果 mode 为 True,则在图像 img 上绘制矩形;否则,在图像 img 上绘制半径为 5 的圆形。

当用户释放鼠标左键时,cv.EVENT_LBUTTONUP 事件被触发,drawing 被设置为 False,表示绘制结束。然后,根据 mode 的值再次在图像 img 上绘制矩形或圆形。

练习

在这里插入图片描述
代码:

import numpy as np
import cv2 as cv

drawing = False  # 如果按下鼠标,则为真
mode = True  # 如果为真,绘制矩形。按 m 键可以切换到曲线
ix, iy = -1, -1


# 鼠标回调函数
def draw_circle(event, x, y, flags, param):
    global ix, iy, drawing, mode
    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        if mode == True:
            cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 3)
        else:
            cv.circle(img, (x, y), 5, (0, 0, 255), -1)


# 创建一个黑色的图像,一个窗口,并绑定到窗口的功能
img = np.zeros((512, 512, 3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)
while (1):
    cv.imshow('image', img)
    if cv.waitKey(20) & 0xFF == 27:
        break
cv.destroyAllWindows()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv-python入门学习(1) 的相关文章

随机推荐

  • RestfulTool插件使用详解

    1 全局搜索 2 提供了一个 Services tree 的API接口显示窗口 右侧会有RestServices侧边栏 点击后会显示当前项目所有请求地址 可以进行输入查询 然后会直接把请求方式 地址以及参数列出来 默认请求服务器为本机 lo
  • 【python】socket-传输多个文件、大文件

    socket 传输多个文件 大文件 0 前言 1 发送单个文件流程 2 关于发送大文件 本地读取时报错 MemoryError 3 关于粘包 问题背景 排错过程 解决方案 4 备注 换算表 0 前言 看过挺多个发文件的例子 但是基本都是发单
  • 每日博客 :>

    1 交换数组 define CRT SECURE NO WARNINGS 1 include
  • 计算机网络34-学习笔记-IP地址

    IP地址属于网络层 这里主要介绍IP地址作用 与MAC地址配合 主机H1将数据包发送给路由器R1 在网络层封装的IP数据报首部中 源IP地址应填写主机H1的IP地址IP1 目的IP地址应填写主机H2的IP地址IP2 在数据链路层中源MAC地
  • python装饰器

    装饰器是python一个重要的部分 由它的名称我们就可以大致了解到它的功能 拓展其他函数 装饰器可以让我们的代码更加简洁 也更加pythonic 首先 我们先回顾一下基础概念 一 在python中 如果调用一个函数不带括号时 调用的是这个函
  • R语言多任务处理与并行运算包——foreach

    作者简介Introduction 杜雨 EasyCharts团队成员 R语言中文社区专栏作者 兴趣方向为 Excel商务图表 R语言数据可视化 地理信息数据可视化 个人公众号 数据小魔方 微信ID datamofang 数据小魔方 创始人
  • SpringBoot原理

    1 SpringBoot实现原理 SpringBoot是由自动配置和启动器以及大量注解实现 Stater stater就是启动器 也就是我们在pom xml文件中引入的带stater的依赖 springboot框架会根据依赖加载与该启动器有
  • Shell脚本入门

    Shell脚本入门 1 基本概念 Shell是一门弱类型 解释型 非编译型语言 Shell中无数据类型 Shell的作用是解释执行用户的命令 Shell执行命令的方式有两种 1 交互式 用户输入一条命令 shell就解释执行一条 2 批处理
  • 名为dash的蓝色插嘴小机器人_全球最出色的十大教育机器人

    2016年 阿尔法狗战胜围棋世界冠军李世石 成为人工智能发展的标志性事件 万物互联的时代 人工智能正掀起一场影响深刻的技术革命 谷歌 苹果 BAT 华为巨头们纷纷布局人工智能 有人猜测 互联网 过后 我们可能会迎来机器人 听到这个消息 爸爸
  • [PCIe] SR-IOV (单根虚拟化) 及linux驱动浅析(device的PF和VF及其驱动)

    网上从服务器和虚拟化层面介绍SR IOV应用的文章很多了 本文重点从支持SR IOV的设备 EP 及其驱动来讨论 对于SR IOV的设备 EP 来说 无非就是一个device通过物理功能 PF 虚拟出关联的若干个虚拟功能 VF host的驱
  • 某公司的雇员分为以下若干类: Employee:这是所有员工总的父类, 属性: 员工的姓名,员工的生日月份。 方法:getSalary(

    代码 某公司的雇员分为以下若干类 Employee 这是所有员工总的父类 属性 员工的姓名 员工的生日月份 方法 getSalary intmonth 根据参数月份来确定工资 如果该月员工过生日 则公司会额外奖励100 元 Salaried
  • 在proteus中继电器的驱动与使用

    在进行proteus仿真驱动继电器时候 因为第一次接触和学习继电器遇到了无论采用电源驱动还是三极管放大驱动都无法驱动的问题 所以就查了继电器的资料和proteus中的默认设置 发现原来是proteus中继电器默认驱动电压为12V 所以我们需
  • CF 709C

    感谢这个题让我进了前1000 思路 特殊条件切入 一开始想跑网络流 但边数 点数太多 所以就需要找此题和常规网络流的区别 看到 M 2 gt 尽可能使用M 2这个条件构造解 gt 少于M 2的全选 gt 剩下的全是大于M 2的 gt 如果每
  • linux-docker

    unix liunx windows linux 文件系统 所有的资源都是目录在 root 根目录下 一 指令 ip addr ifconfig cd ls vim sudo 管理员身份 代表换行输入 pwd 查看所在目录 sudo sys
  • 12306模拟登陆一直提示系统繁忙_12306买高铁火车票显示待核验怎么办,最新解决方案...

    知道有些人没耐心 先说解决核心是12306里面人脸识别 亲测有效 全文没几个字一定要看不用去车站走冤枉路啊 身份信息不能自动核验 相信吃过亏的不止我一个 网上找了很多方法不行 问客服也没用 终于自己找到一个方法 相继解决了我妈和我朋友的待核
  • Maven项目中properties文件的加载方式

    Maven项目中 读取properties配置文件 1 properties文件在src main java的根目录中时加载文件使用 PropertyConfigurator configure log4j properties 2 pro
  • FFmpeg进阶: 音频滤镜大全

    在做音频处理模块的时候 为了对声音进行优化处理 我很多时候会使用各种算法对音频进行变换 效果包括变音变调 声音降噪等等 其实FFmpeg库里的滤镜模块包含了很多有用的音频滤镜算法 这对于提升开发效率避免重复造轮子是很有帮助的 这里翻译了一下
  • Android apk 项目一键打包并上传到蒲公英

    项目一键打包并上传到蒲公英 缘由 测试流程由 打包 找包准备上传 填写更新信息 然后上传 过于复杂 所以想要简化开发 阅读须知 需要读者了解如何在项目里面建立一个空的gradle plugin的过程 否则这篇文章不适合你 开始分析 我想要的
  • jdbc控制自动提交功能

    import java sql Connection import java sql DriverManager import java sql ResultSet import java sql SQLException import j
  • opencv-python入门学习(1)

    opencv python入门 环境安装与配置 图像入门 图片的读取 显示和保存 cv imread 读取图像 cv imshow 显示图像 cv imwrite 储存图像 视频的读取 显示和保存 从摄像机 文件中读取并显示视频 保存编辑后