当前位置: 首页 > news >正文

初识opencv01——基本api操作


文章目录

  • 前言
  • 一、计算机中的图像
    • 1.1 环境安装
    • 1.2 计算机中的图像构成
    • 1.3 计算机中的图像存储
  • 二、基本图像操作
    • 2.1 图像读取
    • 2.2 图像创建与保存
    • 2.3 图形绘制
    • 2.4 图像修改尺寸
    • 2.5 读取视频
  • 总结


前言

OpenCV(开放源代码计算机视觉库)是一个开源的计算机视觉和机器学习软件库。由一系列 C++ 类和函数构成,用于图像处理、计算机视觉领域的算法实现。本文主要讲解的是OpenCV-Python的使用。


一、计算机中的图像

1.1 环境安装

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

或者

conda install opencv

1.2 计算机中的图像构成

在人眼中,以下图片是一只猫咪高举着前爪,好奇地注视着上方。而计算机并没有“猫咪”之类的存在于客观现实世界的概念。在计算机中,图像不过是像素点的有序集合。

而像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成了完整的图像,在计算机中,图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不同,每个像素可以用不同的二进制数表示。

1.3 计算机中的图像存储

计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数图像。opencv中常用的是8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0到255,其中0,代表最黑,1,表示最白。

  • 通道
    日常生活中常见的图像是RGB三原色图。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)三个颜色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机中,RGB三种颜色被称为RGB三通道,每个通道的取值都是0-255,根据这三个通道存储的像素值,来对应不同的颜色。

图像的每个通道都可看作一张独立的图像,将所有通道混合在一起即可合成原始图像

蓝色通道(B)绿色通道(G)红色通道(R)
  • 尺寸
    在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。其中二维图像是二维数组,彩色图像是三维数组。而图像的尺寸(形状)由其高、宽和通道数决定。
  • 像素
    • 单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越接近0,颜色越暗;值越接近255,颜色越亮。
    • 多通道图像(彩色图像):
      在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储

二、基本图像操作

2.1 图像读取

这里给出一份示例代码:

import cv2 as cv# 读取一张图片
img = cv.imread('path/to/your/image.jpg')# 创建一个名为 "Resizable" 的窗口,允许用户调整大小
cv.namedWindow('Resizable', cv.WINDOW_NORMAL)# 创建一个名为 "Fixed Size" 的窗口,大小固定为图像尺寸
cv.namedWindow('Fixed Size', cv.WINDOW_AUTOSIZE)# 将同一张图片显示在两个不同的窗口中
cv.imshow('Resizable', img)
cv.imshow('Fixed Size', img)# 等待按键
cv.waitKey(0)
cv.destroyAllWindows()

其中用到的api有:

  • cv2.namedWindow(winname [,窗口属性])
    使用 cv2.namedWindow() 方法创建一个新的窗口。你可以为这个窗口指定一个名称,并且可以选择窗口的属性。

winname为窗口名,窗口属性是一个可选属性,常用值有cv2.WINDOW_AUTOSIZE(默认,窗口会根据加载的图像自动调整到合适的大小)、cv2.WINDOW_NORMAL(窗口大小是可自由调整的)等。

  • cv2.imread(path [,读取方式])
    path为文件路径,字符串类型;读取方式为可选参数,接收参数可为整数或标志Flags

常用标志

  • cv2.IMREAD_COLOR 或 1: 以彩色模式读取图像,忽略透明度。这是默认值 。无论原图是 JPG、PNG 还是其他格式,都会返回一个 3 通道 (BGR) 的数组。
  • cv2.IMREAD_GRAYSCALE 或 0: 以灰度模式读取图像。返回一个 单通道 的二维数组。
  • cv2.IMREAD_UNCHANGED 或 -1: 以包含透明度(Alpha 通道)的方式读取图像。如果原图是 PNG 等支持透明度的格式,则返回一个 4 通道 (BGRA) 的数组。
  • cv2.imshow(winname,img)
    winname为窗口名称,类型为字符串,窗口名称必须是唯一的,否则会覆盖之前的窗口。如果窗口名称未提前通过 cv2.namedWindow() 声明,则 imshow() 会自动创建一个窗口。
    img为 要显示的图像数据,类型为NumPy 数组 (ndarray),数据类型通常是 uint8,表示每个像素值范围为 [0, 255]。

cv2.imshow() 不返回任何值,其主要功能是将图像显示在窗口中。

  • cv.waitKey(n)
    在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
  • cv.waitKey(0):表示无限期地等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户决定关闭它。
  • cv.waitKey(n):n>0,意味着程序将等待n毫秒,即当前窗口显示n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。
  • cv2.destroyAllWindows([winname])
    会在当前程序执行到该语句时立即销毁指定的窗口,并释放与这些窗口相关的资源。若参数为空则销毁所有打开的窗口,并释放资源。

2.2 图像创建与保存

这里给出一份示例代码:

import cv2 as cv
import numpy as np# 1. 创建一个空白图像
# 创建一个 600x400 像素的白色背景图像 (BGR 格式)
height, width = 600, 400
image = np.zeros((height, width, 3), dtype=np.uint8) + 255  # 白色背景# 2. 在图像上添加文本
text = "Hello, OpenCV!"
font = cv.FONT_HERSHEY_SIMPLEX
font_scale = 1.5
color = (0, 0, 255)  # BGR 颜色:红色
thickness = 2
position = (50, 200)  # 文本位置 (x, y)cv.putText(image, text, position, font, font_scale, color, thickness)# 3. 显示图像
cv.imshow("Created Image", image)
cv.waitKey(0)
cv.destroyAllWindows()# 4. 保存图像到文件
output_path = "./output_image.png"
cv.imwrite(output_path, image)print(f"Image saved successfully at: {output_path}")

其中用到的api有:

  • numpy.zeros((height,width,channels),dtype=np. uint8)
    会得到一个值全0的numpy数组,若作图片显示则为一张全黑图像,可修改其像素的颜色值。

  • cv2.putText(img,text,station,font,Fontscale,color,thickness,cv2.LINE_AA)
    用于在图片中插入文字,参数:

    • img:要添加文字的图像
    • text:要写入的文本数据
    • station:文本的放置位置
    • font:字体样式
    • Fontscale:字体大小
    • thickness:字体线条宽度
    • cv2.LINE_AA:使用反走样技术绘制文本边框,可选

反走样是一种提高图形质量的技术,通过混合颜色和像素边缘来减少锯齿状效果,使文本看起来更加平滑、清晰。

这个方法不支持中文,如果使用中文文本会显示??

  • cv2.imwrite(path,img)
    path为指定保存图像的路径和文件名,包括文件扩展名,类型为字符串。img要保存的图像数据,类型为NumPy 数组 (ndarray)。

2.3 图形绘制

这里给出一份示例代码:

import cv2 as cv
import numpy as np# 1. 创建一个空白的黑色图像作为画布 (高度=400, 宽度=600, 3个通道)
canvas = np.zeros((400, 600, 3), dtype=np.uint8)# --- 绘制直线 (line) ---
# 在画布上从点 (50, 50) 到点 (200, 100) 画一条绿色的线,线宽为 3 像素。
# 注意:OpenCV 使用 BGR 颜色,所以 (0, 255, 0) 是绿色。
start_point = (50, 50)
end_point = (200, 100)
color_green = (0, 255, 0)
thickness_line = 3
cv.line(canvas, start_point, end_point, color_green, thickness_line)# --- 绘制圆形 (circle) ---
# 在画布上以点 (300, 200) 为圆心,半径为 50 像素,画一个蓝色的圆,线宽为 2 像素。
# 如果将 thickness 设置为 -1,则会填充整个圆形。
center_point = (300, 200)
radius = 50
color_blue = (255, 0, 0) # BGR: 蓝色
thickness_circle = 2
cv.circle(canvas, center_point, radius, color_blue, thickness_circle)# --- 绘制矩形 (rectangle) ---
# 在画布上从左上角点 (400, 100) 到右下角点 (550, 250) 画一个红色的矩形,线宽为 4 像素。
left_upper = (400, 100)
right_down = (550, 250)
color_red = (0, 0, 255) # BGR: 红色
thickness_rect = 4
cv.rectangle(canvas, left_upper, right_down, color_red, thickness_rect)# --- 显示结果 ---
cv.imshow('Drawing Shapes', canvas)
cv.waitKey(0) # 等待按键
cv.destroyAllWindows() # 关闭所有窗口

其中用到的api有:

  • cv2.line(img,sart,end,color,thickness)
    用于绘制直线,参数:
  • img:要绘制直线的图像
  • start、end:直线的起点和终点
  • color:直线的颜色(对于彩色图像,使用 BGR 格式指定颜色)
  • thickness:线条宽度
  • cv2.circle(img,centerpoint,r,color,thickness)

用于绘制圆形,参数:

  • img:要绘制圆形的图片
  • centerpoint、r:圆心和半径
  • color:线条颜色
  • tnickness:线条宽度,为-1时生成闭合图案并填充颜色
  • cv2.rectangle(img,leftupper,rightdown,color,thickness)
    用于绘制矩形,参数:
  • img:要绘制矩形的图像
  • leftupper、rightdown:矩形的左上角和右下角坐标
  • color:线条的颜色
  • thickness:线条的宽度

2.4 图像修改尺寸

这里给出一份示例代码:

import cv2 as cv# 1. 读取一张图片
image = cv.imread('./path/to/your/image.jpg') # 请将路径替换为你的图片路径# 检查图片是否成功加载
if image is None:print("Error: Could not load image.")exit()# --- 图像切片 (Image Slicing) ---
# 示例1: 提取图像左上角的一个 200x200 的区域
roi_top_left = image[0:200, 0:200] # 从第0行到第199行,第0列到第199列# 示例2: 提取图像中间的一个矩形区域
height, width = image.shape[:2] # 获取图像的高度和宽度
center_y, center_x = height // 2, width // 2
half_size = 150
roi_center = image[center_y-half_size:center_y+half_size,center_x-half_size:center_x+half_size]# 示例3: 只提取蓝色通道 (BGR中的B, 索引为0)
blue_channel = image[:, :, 0] # :,: 表示所有行和所有列
# 注意:这会返回一个单通道的灰度图。要保留颜色,需要像之前那样用全黑背景复制。# --- 使用 cv2.resize() 调整图像大小 ---
# 方法1: 指定目标尺寸 (dsize)
# 将图像缩小到 300x300 像素
resized_small = cv.resize(image, (300, 300)) # dsize 参数是 (width, height)# 方法2: 指定缩放因子 (fx, fy)
# 将图像宽度和高度都放大到原来的 2 倍
resized_large = cv.resize(image, None, fx=2, fy=2)# --- 显示结果 ---
cv.imshow('Original', image)
cv.imshow('Top Left ROI', roi_top_left)
cv.imshow('Center ROI', roi_center)
cv.imshow('Blue Channel', blue_channel)
cv.imshow('Resized Small', resized_small)
cv.imshow('Resized Large', resized_large)cv.waitKey(0)
cv.destroyAllWindows()

其中使用的到的api有:

  • 图像切片:
    切片语法: image[起始行:结束行, 起始列:结束列],确保(y,x)(y+h,x+w)都在图像的边界内,否则会出现索引越界错误。img通常是numpy.ndarray类型,切片操作返回的也是numpy.ndarray类型。
    OpenCV 中图像是按 [行, 列, 通道] 存储的,所以 y 坐标在前,x 坐标在后。
  • cv2.resize(src, dsize, fx=None, fy=None)
    用于调整图像大小的函数,在图像处理中很常用,参数:
  • src: 输入的源图像。
  • dsize: 输出图像的大小,格式为 (width, height) 元组。如果指定了 dsize,则 fx 和 fy 会被忽略。
  • fx, fy: 在 X 轴和 Y 轴方向上的缩放因子。如果 dsize 是 None,则使用 fx 和 fy 来计算新的尺寸。

2.5 读取视频

这里给出一份示例代码:

import cv2 as cv# 创建一个 VideoCapture 对象,参数是视频文件的路径
video_path = './path/to/your/video.mp4' # 请将路径替换为你的视频文件路径
cap = cv.VideoCapture(video_path)# --- 主循环:逐帧读取和显示 ---
while True:# 从视频流中读取一帧ret, frame = cap.read()# `ret` 是一个布尔值,表示是否成功读取了帧# `frame` 是包含图像数据的 NumPy 数组if not ret:print("End of video or cannot receive frame. Exiting...")break# 显示当前帧cv.imshow('Video Playback', frame)# 等待按键。如果按 'q' 键,则退出循环# cv.waitKey(25) 表示每帧显示25毫秒(约40fps),这与许多视频的帧率匹配key = cv.waitKey(25) & 0xFF if key == ord('q'):break# --- 清理资源 ---
# 释放 VideoCapture 对象,关闭所有窗口
cap.release()
cv.destroyAllWindows()

其中使用的到的api有:

  • cap = cv2.VideoCapture(path)
    用于获取视频文件。path为视频流资源路径,若设置为0,代表从默认摄像头捕获视频流。
  • ret,frame = cap.read()
    用于读取视频文件,返回值为一个布尔值和一帧图像,布尔值表示是否成功读取到帧,如果为False,可能是因为视频结束或读取失败,如果为True,则frame是当前帧的图像数据。

总结

本博客“简要地介绍OpenCV的基础api。文章探讨了计算机中图像的构成与存储原理,聚焦于OpenCV最常用的基本API操作。

http://www.lryc.cn/news/596063.html

相关文章:

  • 分布式高可用ELK平台搭建及使用保姆级教程指南
  • 大数据之Hive:Hive中week相关的几个函数
  • 分布式数据库中间件ShardingSphere
  • Protobuf学习
  • SysMind:Go 语言驱动的AI系统运维助手
  • 用Python实现神经网络(六)
  • 【计算机网络 篇】TCP基本认识和TCP三次握手相关问题
  • WebSocket心跳机制实现要点
  • 深入浅出理解 TCP 与 UDP:网络传输协议的核心差异与应用
  • 基于SpringBoot+Vue的高校特长互助系统(WebSocket实时聊天、协同过滤算法、ECharts图形化分析)
  • JavaScript,发生异常,try...catch...finally处理,继续向上层调用者传递异常信息
  • zabbix“专家坐诊”第295期问答
  • 服务器无法访问公网的原因及解决方案
  • 在 WebSocket 中使用 @Autowired 时遇到空指针异常
  • XML高效处理类 - 专为Office文档XML处理优化
  • 智能制造——解读52页汽车设计制造一体化整车产品生命周期PLM解决方案【附全文阅读】
  • 智慧制造合同解决方案
  • React 项目性能优化概要
  • 客户案例 | Jabil 整合 IT 与运营,大规模转型制造流程
  • 厚铜板载流革命与精密压合工艺——高可靠性PCB批量制造的新锚点
  • 中小制造企业如何对技术图纸进行管理?
  • OneCode 3.0 @FormAnnotation 注解速查手册
  • 漫画版:细说金仓数据库
  • Qt/C++源码/监控设备模拟器/支持onvif和gb28181/多路批量模拟/虚拟监控摄像头
  • 秋招Day17 - Spring - AOP
  • 《基于蛋白质组学的精准医学》:研究进展与未来展望
  • 双指针算法介绍及使用(上)
  • GitHub 上的开源项目 ticktick(滴答清单)
  • MSTP技术
  • 【加解密与C】Rot系列(四)RotSpecial