图像基础(OpenCV)

OpenCV

  • OpenCV(开放源代码计算机视觉库)介绍
    • 是一个开源计算机视觉机器学习软件库。由一系列C++类和函数构成,用于图像处理、计算机视觉领域的算法实现
  • OpenCV优势
    • 开源免费
    • 多语言支持
    • 跨平台
    • 丰富API
  • OpenCV-Python
    • 为原始OpenCV C++实现的python包装器,结合了OpenCV C++ API的高性能和python语言的易用性和简洁性
    • 如何解决Python与C/C++等语言相比,速度较慢的问题?
      • python可以使用C/C++扩展
      • 在C/C++中编写计算密集型代码
      • 创建可用作python模块的python包装器

           如此可在python中调用后台的C/C++代码,速度将和C/C++一样快,同时在python中编写代码也更加容易。

  • OpenCV-Python使用Numpy,所有OpenCV数组结构都转换为Numpy数组。
  • Numpy是一个高度优化的数据操作库,OpenCV使用Numpy也使得OpenCV使用Numpy的其他库集成变得更加容易。

环境安装

win+R调出窗口后输入cmd打开命令行界面

输“ activate 环境名”激活虚拟环境

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

完成安装(在pycharm中使用需要进行虚拟环境配置,具体步骤在这不详细赘述)

图像表示

这里所需的理论知识有:

  • OpenCV常用8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0-255,0代表最黑,1表示最白
  • 日常生活常见图像由RGB三原色(R:红色,G:绿色,B:蓝色)三个颜色按比例混合而成
  • 计算机中称RGB三原色为RGB三通道,每个通道取值为0-255,根据三个通道存储的像素值来对应不同颜色

图像存储

在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。

  • 彩色图像:三维数组
  • 灰度图像:二维

图像本质上是像素值的二维或三维矩阵(对于彩色图像)。

  • 形状(Shape):图像的尺寸由其高(height)、宽(width)和通道数(channels)决定。可以通过img.shape属性获取这些信息。
    • 对于彩色图像(如RGB),返回的是一个包含三个值的元组 (height, width, channels)。
    • 对于灰度图像,返回的是一个包含两个值的元组 (height, width),因为灰度图像只有一个通道。
  • 数据类型(dtype):图像中的每个像素值的数据类型决定了可以存储的最大值。例如,8位无符号整数(uint8)允许的范围是从0到255。
  • 像素表示
    • 单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越低(接近0),颜色越暗;值越高(接近255),颜色越亮。
    • 多通道图像(彩色图像):在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储
  • 彩色图像

    • 每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,分量介于(0,255)。
    • RGB图像每一个像素的颜色值(由RGB三原色表示)直接存放在图像矩阵中,由于每一像素的颜色需由R、G、B三个分量来表示,M、N分别表示图像的行列数,三个M x N的二维矩阵分别表示各个像素的R、G、B三个颜色分量
    • RGB图像的数据类型一般为8位无符号整型,通常用于表示和存放彩色图像。

基本图像操作

  • 创建窗体:cv.nameWindow()
import cv2 as cv

#创建窗体
cv.namedWindow("mywindow", cv.WINDOW_AUTOSIZE)
cv.namedWindow("mywindow2", cv.WINDOW_NORMAL)
#autosize:无法手动调整窗口大小;normal:正常,可以手动调整
  • 读取图像:cv.imshow(winname,img)
img = cv.imread("../images/1.jpg")
gray = cv.imread("../images/1.jpg",cv.IMREAD_GRAYSCALE)#读取灰度图片
# print(img)
# print(img.shape)#(h,w,c)
# print(img.dtype)
#print(gray,gray.shape,gray.dtype)

注意这里的路径,不要写错了,放在同一个根目录下的文件可以../读取的方式,当然直接找到文件复制文件路径也可。

  • 保存图片(cv.imwrite)
cv.imwrite("./gray.jpg",gray)
  • 显示图像(cv.imshow)
cv.imshow("mywindow", img)
cv.imshow("mywindow2", gray)
#留下绘制时间,等待n毫秒,0代表一直等代
cv.waitKey(0)
#销毁窗口释放资源
cv.destroyAllWindows()

运行结果分别弹出两个弹窗:

注意:在调用显示图像的API后,要调用cv.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应的情况,并且图像无法显示出来

cv.waitKey(0):表示无限期等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户关闭它

cv.waitKey(n):n>0,意味着程序将等待n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。

  • 创建黑白、随机像素的图片文件

这里使用np.zeros()创建全黑图像,再修改像素值成为全白图像。

import cv2 as cv
import  numpy as np
#创建黑色图像
black=np.zeros((640,480,3),dtype=np.uint8)
cv.imshow("black",black)
#创建白色图像
white=np.ones((640,480,3),255,dtype=np.uint8)
cv.imshow("white",white)
#修改黑图里面的像素值为255
black[:,:,:]=255
cv.imshow("white2",black)
#创建随机像素的图像
random=np.random.randint(0,256,(640,480,3),dtype=np.uint8)
cv.imshow("random",random)

cv.waitKey(0)
cv.destroyAllWindows()

运行结果有两个弹窗图片:

  • 图像切片
    • OpenCV中图像切片用于从图像中提取一个子区域(矩形区域)
    • 一个图像img,类型为numpy.ndarray
    • img[y:y+h,x:x+w]的含义如下
      • x:子区域左上角的x坐标
      • y:子区域左上角的y坐标
      • w:子区域的宽度
      • h:子区域的高度
    • 切片操作
      • img[y:y+h,x:x+w]提取的是从(x,y)开始,高度为h,宽度为w的矩形区域

注意:

边界检查:确保(y,x)(y+h,x+w)都在图像的边界内,否则会出现索引越界错误。

数据类型:img通常是numpy.ndarray类型,切片操作返回的也是numpy.ndarray类型。

import cv2 as cv
#读图
cat = cv.imread("../images/cat1.png")
#剪裁(380,240)(477,374)
roi=cat[240:374,380:477]
roi2=cat[370:454,426:516]
cv.imshow("eye",roi)
cv.imshow("nose",roi2)
cv.waitKey(0)
cv.destroyAllWindows()

剪裁结果如下:例子中进行了两次截取,分别实时眼睛和鼻子

注意:如在截取的对象上做修改,原图也会跟着被修改,是因为提取的对象内存地址与原图被截取部分的内存地址相同

  • 图像大小调整
    • cv.resize(img,dsize):用于调整图像大小,对图像进行缩放
    • img:输入图像,通常为二维或三维Numpy数组
    • dsize:输出图像所需尺寸,是一个元组(w,h)
import cv2 as cv
#读图
cat=cv.imread("../images/cat1.png")
#调整图像大小(w,h)
dst=cv.resize(cat,(640,480))
cv.imshow("cat",cat)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()

输出结果如下图:原图像尺寸被缩小

  • 图像绘制

    • 绘制直线(cv.line(img,sart,end,color,thickness))
      • img:需要绘制直线的图像
      • sart/end:直线的起点和重点,一般为两个坐标点
      • color:直线的颜色(对于彩色图像,使用BGR格式指定颜色)
      • thickness:线条宽度
      • import cv2 as cv
        #读图
        cat = cv.imread("../images/cat1.png")
        #绘制直线
        cv.line(cat,(200,250),(200,350),(0,0,255),2)
        cv.imshow("cat",cat)

    • 绘制矩形(cv.rectangle(img,leftupper,rightdown,color,thickness))
      • img:需要绘制矩形的图像
      • leftupper/rightdown:矩形的左上角和右下角坐标
      • color:线条颜色
      • thickness:线条宽度
      • #绘制矩形
        cv.rectangle(cat,(426,370),(516,454),(0,255,0),2)

    • 绘制圆(cv.circle(img,centerpoint,r,color,thickness))
      • img:需要绘制圆形的图片
      • centerpoint\r:圆心和半径
      • color:线条颜色
      • thickness:线条宽度,为-1时生成闭合图案并填充颜色
      • #绘制圆
        cv.circle(cat,(427,309),30,(255,0,0),1,cv.LINE_AA)#line_aa抗锯齿,平滑

完整绘图代码如下:

import cv2 as cv
#读图
cat = cv.imread("../images/cat1.png")
#绘制直线
cv.line(cat,(200,250),(200,350),(0,0,255),2)
cv.imshow("cat",cat)
#绘制矩形
cv.rectangle(cat,(426,370),(516,454),(0,255,0),2)
#绘制圆
cv.circle(cat,(427,309),30,(255,0,0),1,cv.LINE_AA)#line_aa抗锯齿,平滑
cv.imshow("cat",cat)
cv.waitKey(0)
cv.destroyAllWindows()

绘制结果如下所示:

  • 读取视频
    • cap=cv.VideoCapture(path)
      • path:视频流资源路径设置为0时,代表默认摄像头捕获视频流
    • ret,frame=cap.read()
      • 返回值cap调用read()方法得到一个布尔值和一帧画像
      • 布尔值代表是否成功读取到帧,若为False可能因为视频结束或者读取失败
      • 布尔值若为True,frame则是当前帧的图像数据
import cv2 as cv
#创建一个videocapture对象
#传具体路径、读取视频文件
cap=cv.VideoCapture("../images/videocap.mp4")
#循环读取每一帧图像
while True:
    ret,frame=cap.read()
    #判断是否读取成功
    if not ret:
        print("读取失败!")
        break
    cv.imshow("video",frame)
    if cv.waitKey(40)&0xFF==ord('q'):
        print("按键退出")
        break
cap.release()
cv.destroyAllWindows()

读出的视频文件会跳出自动进行播放,其中循环语句中的代码解释如下:

  • while True创建无限循环持续读取视频
  • cap.read()读取一帧视频,ret表示读取是否成功,frame是帧数据
  • 如果读取失败则打印提示并退出循环
  • cv.imshow()显示当前帧
  • cv.waitKey(40)等待40毫秒,按'q'键退出程序

这里注意cv.waitKey(40)&0xFF==ord("q")中:

  • cv.waitKey(40):等待40毫秒检测按键事件
  • &0xFF:按位与操作,确保只取低8位字节值
  • ==ord('q'):比较按键的ASCII码是否等于'q'字符的ASCII码(113)
  • 整体用于OpenCV中退出循环的条件判断

读取摄像头视频流只需读取视频路径时输入值为0即可,代码如下:
 

import cv2 as cv
#创建一个videocapture对象
#传具体路径、读取视频文件
#传0。从默认摄像头获取实时视频流
cap2=cv.VideoCapture(0)
#循环读取每一帧图像
while True:
    ret,frame=cap.read()
    #判断是否读取成功
    if not ret:
        print("读取失败!")
        break
    cv.imshow("video",frame)
    if cv.waitKey(40)&0xFF==ord('q'):
        print("按键退出")
        break
cap.release()
cv.destroyAllWindows()

此时会弹出摄像头所获取的实时画面。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值