计算机视觉OpenCv学习系列:第二部分、图像操作

news2025/1/17 2:57:43

第二部分、图像操作

    • 第一节、图像读取与显示
      • 1.图像理解
      • 2.图像读取与显示
      • 3.代码练习与测试
    • 第二节、图像色彩空间转换
      • 1.图像色彩空间
      • 2.函数说明与解释
      • 3.代码练习与测试
    • 第三节、图像对象的创建与赋值
      • 1.图像对象属性
      • 2.图像对象创建与赋值
      • 3.代码练习与测试
    • 第四节、图像像素的读写操作
      • 1.图像像素
        • (1)**像素与分辨率**
        • (2)OpenCV中的像素
      • 2.像素遍历
        • (1)像素遍历
        • (2)像素读写
      • 3.代码练习与测试
    • 第五节、图像算术操作
      • 1.算术操作
      • (1)加、减、乘、除
      • 2.像素算术操作
      • (1)OpenCV函数实现算术操作
      • (2)mask参数
      • 3.代码练习于测试
    • 学习参考

第一节、图像读取与显示

1.图像理解


人眼中的图像–假设是一个灰度/彩色图片,而在计算机眼中都是像素点的数字。

在这里插入图片描述

灰度图像 – 单通道

彩色图像– 三通道

2.图像读取与显示


读取:2个Api函数–imread、imshow

# 导入OpenCV支持的包,这个cv2并不是opencv的版本号,只是这个包的名字
import cv2 as cv

# 导入Numpy支持的包,因为像素点对于计算机来说都是数组存储
import numpy as np

# 读取图像
imread()

# 显示图像
imshow()
#加载图像的顺序都是B-G-R

函数与参数:

cv.imread(filename[,flags])->retval(Numpy数组)
# filename表示文件路径
# []内的参数表示可选,也可以不填
# retval是读取之后返回的结果

cv.imshow(winname,mat)->None
# winname表示窗口标题(只能是英文的)
# mat表示图像对象,也就是上面返回的retval

显示与等待时间:

cv.waitKey(0)
# 表示一直等待,直到任意一个键盘操作
cv.waitKey(1000)
# 表示等待1000ms或者1s

# 如果不加等待结果就是一闪而过

3.代码练习与测试

代码示例:

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

def show_image():
    image = cv.imread("F:\python\研究生python\Datawhale\计算机视觉OpenCV\github_opencv\\lena.jpg") # BGR的读取顺序
    cv.imshow("lena",image)
    cv.waitKey(1000)
    cv.destroyAllWindows() # 销毁该程序创建的所有窗口

windows下读取文件路径的选择:

在这里插入图片描述

第二节、图像色彩空间转换

1.图像色彩空间


在OpenCV中我们最常用的色彩空间是HSV,RGB,YCrCb三种。

在这里插入图片描述

HSV和YCrCb空间对于亮色的区别比RGB好,所以在使用的时候需要灵活选择使用那种色彩空间。

  • RGB色彩空间,设备独立
  • HSV色彩空间,对计算机友好,区分各种色彩
  • YCrCb, Y分量表示信息,CrCb可以被压缩
  • RGB是计算机显示器的标准支持色彩系统
  • RGB的取值范围0~255
  • HSV取值范围H:0180,SV:0255

2.函数说明与解释


图像色彩转换都有下面的三个情况。

  • 从一个色彩空间转换到另外一个色彩空间
  • 信息传递与损失
  • 过程可逆与不可逆

实现色彩转换可以通过使用函数实现:

cv.cvtColor(src,code[,dst[,dstCn]])->dst # []表示的是可选的参数,也可以不写
# src表示输入图像,类型为CV_8U(字符类型)、CV_32F(浮点类型)
# code表示:从什么转换到什么,下面是cv的枚举类型对应的含义。
# cv::COLOR——BGR2RGB = 4 通道交换
# cv::COLOR——BGR2GRAY = 6 彩色到灰度
# cv::COLOR——GRAY2BGR = 8 灰度到彩色
# cv::COLOR——BGR2HSV = 40 彩色到彩色,BGR转换成HSV
# 注意从彩色到灰色,再从灰色到彩色,只是通道数恢复了,其中的信息损失是无法恢复的。

3.代码练习与测试


def color_space_demo():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\lena.jpg")
    cv.imshow("lena",image)
    hsv = cv.cvtColor(image,cv.COLOR_BGR2HSV)
    ycrcb = cv.cvtColor(image,cv.COLOR_BGR2YCrCb)
    cv.imshow("hsv",hsv)
    cv.imshow("ycrcb",ycrcb)
    cv.waitKey(0)
    cv.destroyAllWindows()

转换的示例:

在这里插入图片描述

def color_space_demo():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\lena.jpg")
    cv.imshow("lena", image)
    gray = cv.cvtColor(image, 6)  # 相当于cv.COLOR_BGR2GRAY
    image2 = cv.cvtColor(gray, 8)  # 相当于cv.COLOR_GRAY2BGR
    cv.imshow("gray", gray)
    cv.imshow("image2", image2)
    print("image's shape:", image.shape)
    print("gray's shape:", gray.shape)
    print("image2's shape:", image2.shape)
    cv.waitKey(0)
    cv.destroyAllWindows()

如果我们把彩色图片转换成灰度再转换回来,可以发现他丢失了色彩的信息,如果打印通道数的话发现虽然通道数转换回来了,但是里面的信息已经丢失了,也就是转换之后每个通道中的值是相同的,并不是原来彩色图片中通道的值。

但是BGR和HSV,YCrCb这些彩色之间是可以相互转换的。

在这里插入图片描述

第三节、图像对象的创建与赋值

1.图像对象属性


  • 图像宽高 image.shape (h, w, c) – (高,宽,通道数)

  • 图像深度 image

    如下图所示的一个png图片(不包含透明通道,一共3个通道)位深度表示每个通道占的1个字节(8bit),所以下图的一个png图片所有通道深度一共是24。如果使用folat32存储图片的话,一个png图片的深度就是3 * 32 = 96。

  • 图像数据类型 image.dtype

  • 图像通道 image.shape

  • 如何加载不同通道的图像

在这里插入图片描述

c/c++做opencv中的一些数据类型和opencv-python的一些数据类型。

左边是c/c++做opencv,其中U对应unit,S对应int,F对应float,C对应通道数。

右边是用python做opencv。

一般第一步都是将图像转成float32类型,以免后续计算的时候有精度丢失出现,最后再转成int类型得到图片。

在这里插入图片描述

2.图像对象创建与赋值


在OpenCV中所有图片对象都是Numpy Array

创建图像就是创建numpy array

# Numpy常用函数

1. numpy.array
2. numpy.zeros
3. numpy.zeros_like  # 生成一个和读入图片大小完全一致,但是黑色的图片,即在所有位置都填成0
4. numpy.asarray  # 把正常的python数组变成Numpy数组
5. numpy.copy
6. numpy.reshape

一些函数的解释:

  1. numpy.array(object, dtype=None, *, copy=True, order=‘K’, subok=False, ndmin=0, like=None)

    • object 数组

    • dtype 数据类型

  2. numpy.zeros(shape, dtype=float, order=‘C’, *, like=None)

    • 数组维度
    • dtype 数据类型
  3. numpy.asarray(a, dtype=None, order=None, *, like=None)

    • 数组对象

    • dtype 数据类型

  4. numpy.reshape(a, newshape, order=‘C’)

    • 数组维度

    • dtype 数据类型

创建图片一般不会像左图所示自己去写,而是使用右图中的函数去创建。

在这里插入图片描述

def make_numpy():
    m = np.zeros((3, 3, 3), dtype=np.uint8)
    print(m)
    m[:] = 255
    print(m)
    m[:] = (255, 0, 0)
    print(m)

在这里插入图片描述

3.代码练习与测试


自己创建一些numpy array并且输出图片

def make_numpy_show():
    m = np.zeros((512, 512, 3), dtype=np.uint8)
    m.shape  # 分别是H W C
    m[:] = 255
    cv.imshow("m1", m)
    n = np.zeros_like(m)  # 用m的大小去创造一个n,并且n中元素全为0
    print(n)
    cv.imshow("n", n)
    n[:256] = (255, 0, 0)
    cv.imshow("n2", n)
    cv.waitKey(0)
    cv.destroyAllWindows()

输出示例如下所示:

在这里插入图片描述

尝试给画布左右分隔添加颜色

def try_color():
    m = np.zeros((512, 512, 3), dtype=np.uint8)
    print(m.shape)  # 分别是H W C
    m[:256] = (255, 0, 0)
    m[0:256, 0:256] = (0, 0, 255)
    print(m)
    cv.imshow("m1", m)
    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述

第四节、图像像素的读写操作

1.图像像素


(1)像素与分辨率

如下图高分辨率就是8x8的像素,低分辨率就是2x2的像素。(高分辨率携带的像素数量多于低分辨率

例如,我们有一个大熊猫的图片,高分辨率就可以连大熊猫的毛发都能看到,低分辨率可能画出来大熊猫的轮廓都很吃力。

在这里插入图片描述

  • 像素实际大小:dpi x inches = 像素总数

  • 术语dpi:每英寸的点数目,96dpi — 针对打印

  • 术语ppi: 每英寸的像素数目 — 针对图像分辨率

    下图所示的就是相机像素从一百万到四百万对应的像素数目。

在这里插入图片描述

(2)OpenCV中的像素

  • 灰度图像排序
    • 灰度图片只有一个通道
    • 左上角的值就是图片中的左上角第一个像素点

在这里插入图片描述

  • 彩色图片排序
    • 彩色图片有三个通道
    • 开始的像素点在左上角,结束的像素点在右下角

在这里插入图片描述

2.像素遍历


(1)像素遍历

像素遍历参照上面灰度图片和彩色图片的示意图,使用for循环来遍历numpy数组,一个for循环管高度方向的,另一个for循环管宽度方向,从左到右,从上到下遍历数组。

  • 像素遍历本质就是numpy数组
  • 访问假设变量image
  • 获取图像维度信息: image.shape – 彩色图像分别是H(高) W(宽) C(通道数),灰度图片就是H(高) W(宽)
  • 图像访问像素: image[row, col]
  • 图像赋值像素: image[row, col] = (b,g,r) – 彩色图片每个位置对应三个值

(2)像素读写

  • 读写像素,彩色图像:
    • b, g, r = image[row, col]
    • image[row, col] = (255-b, 255-g, 255-r)
  • 读写像素,灰度图像:
    • pv = image[row, col]
    • image[row, col] = 255-pv

3.代码练习与测试


def visit_pixel_demo():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\lena.jpg")
    cv.imshow("lena",image)
    h, w, c = image.shape
    print("h: ", h, "w: ", w, "c:", c)
    for row in range(h):
        for col in range(w):
            b, g, r = image[row, col]
            image[row, col] = (255-b, 255-g, 255-r) # 取反色,把原图RGB,通过255-,变成反色。
    cv.imshow("visited", image)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

同理我们可以如上节所学代码实现在图片的某一个部分添加颜色快。

def visit_pixel_demo2():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\lena.jpg")
    cv.imshow("lena", image)
    h, w, c = image.shape
    print("h: ", h, "w: ", w, "c:", c)
    print(image.dtype)
    image[0:256, 256:512] = (0, 0, 255) # 在右上角添加了一个红色块
    cv.imshow("visited", image)
    cv.waitKey(0)
    cv.destroyAllWindows()

在这里插入图片描述

第五节、图像算术操作

1.算术操作


(1)加、减、乘、除

  1. 加法
img1[row, col] + img2[row, col] --> dst[row, col] # img1和img2的大小要相同,对应像素点相加结果给dst

黑色是(0, 0, 0)所以和什么像素值相加就是什么什么,而中间OpenCV绿色加粉色最后就是米黄色的OpenCV。

在这里插入图片描述

  1. 减法
img2[row, col] - img1[row, col] --> dst[row, col] # img1和img2的大小要相同,对应像素点相减结果给dst

在这里插入图片描述

  1. 乘法
img1[row, col] * img2[row, col] --> dst[row, col] # img1和img2的大小要相同,对应像素点相乘结果给dst

在这里插入图片描述

  1. 除法
img2[row, col] / img1[row, col] --> dst[row, col] # img1和img2的大小要相同,对应像素点相除结果给dst

在这里插入图片描述

2.像素算术操作


(1)OpenCV函数实现算术操作

但是在OpenCV中并不需要我们手动写计算式,而是调用现有的函数就可以。

1.加法 cv.add(src1, src2[, dst[, mask[, dtype]]]) ->dst
2.减法 cv.subtract(src1,src2[,dst[,mask[,dtype]]])->dst
3.乘法 cv.multiply(src1,src2[,dst[,scale[,dtype]]])->dst
4.除法 cv.divide(src1, src2[, dst[, scale[, dtype]]])->dst

参数说明:

  • src1 & src2都是图像
  • 加法,保证不越界:saturate(src1 + src2) --> 0~255 - 意思是两个数(0-255)做加法(0-512)如果大于255,就赋值成255;如果做减法小于0,就赋值成0。
  • 加法和减法是有mask的,乘法除法没有。

(2)mask参数

因为mask参数只在加法和减法中出现,所以以加法为例。

cv.add(src1, src2[, dst[, mask[, dtype]]]) --> dst
  • src1输入图像1
  • src2输入图像2
  • mask表示模板,只包括0和非零部分。

结果如下图所示:做加法的时候只将mask为1的部分做加法,其余部分和mask一样补0。

在这里插入图片描述

mask不同,提取的图像区域不同,所以当需要提取不规则区域的时候可以使用mask

3.代码练习于测试


# 算术操作实现加、减、乘、除
def arithmetic_demo():
    image1 = cv.imread(r"F:\python\opencv-4.x\samples\data\opencv-logo.png")
    image2 = np.zeros_like(image1)
    image2[:, :] = (110, 0, 250)
    image1 = cv.resize(image1, None, fx=0.5, fy=0.5)  # 调整图片大小
    image2 = cv.resize(image2, None, fx=0.5, fy=0.5)  # 调整图片大小
    cv.imshow("img1", image1)
    cv.imshow("img2", image2)
    added = cv.add(image1, image2)  # 加法
    subbed = cv.subtract(image1, image2)  # 减法
    multiplied = cv.multiply(image1, image2)  # 乘法
    divided = cv.divide(image1, image2)  # 除法
    cv.imshow("added", added)
    cv.imshow("subbed", subbed)
    cv.imshow("multiplied", multiplied)
    cv.imshow("divided", divided)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

使用mask之后的效果:

# 使用mask实现的算术(加法、减法)操作实现加法
def arithmetic_demo_mask():
    image1 = cv.imread(r"F:\python\opencv-4.x\samples\data\opencv-logo.png")
    image2 = np.zeros_like(image1)
    image2[:, :] = (110, 0, 250)
    image1 = cv.resize(image1, None, fx=0.5, fy=0.5)  # 调整图片大小
    image2 = cv.resize(image2, None, fx=0.5, fy=0.5)  # 调整图片大小
    cv.imshow("img1", image1)
    cv.imshow("img2", image2)
    h, w, c = image1.shape
    print("h: ", h, "w: ", w, "c:", c)
    mask = np.zeros((h, w), dtype=np.uint8)
    mask[100:200, 100:250] = 1
    added = cv.add(image1, image2, mask=mask)  # 使用mask参数对[100:200, 100:250]部分进行add操作,其余位置补0
    subbed = cv.subtract(image2, image1, mask=mask)  # 使用mask参数对[100:200, 100:250]部分进行sub操作,其余位置补0
    cv.imshow("added", added)
    cv.imshow("subbed", subbed)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

学习参考

本系列所有OpenCv相关的代码示例和内容均来自博主学习的网站:opencv_course

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

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

相关文章

SpringBoot——关于controller参数校验

参数校验主要使用两个标签Validated和Valid; Valid是Hibernate的注解校验,Validated是spring的,是Valid的增强;这两个标签也有一些不同之处,Valid可以标注在成员属性上也可以嵌套校验,而Validated不行&…

Node.js 操作MySQL数据库

在讲Node.js中引入mysql模块之前先讲一下关于MySQL数据库,首先是关于MySQL数据库的安装和mysql服务以及对mysql命令和可视化工具的一个基本使用;那么在这里已经准备好了关于MySQL数据库的内容了: MySQL 数据库安装详细 : MySQL数…

redis主从复制,一主多仆启动流程

文章目录一、安装redis二、复制修改配置文件三、添加conf配置文件四、开启主从复制五、薪火相传六、反客为主7、哨兵模式一、安装redis redis安装笔记 https://blog.csdn.net/G_GUi/article/details/128361131 二、复制修改配置文件 把redis.conf复制到一个新建文件夹里面&a…

安卓手机还有这么多神仙玩法,关键只有少数人知道

随着“智能手机”的快速更新迭代,手机系统逐渐融入了许多实用功能;今年Android手机市场竞争相当激烈,各大手机品牌都争先恐后地向消费者展示自己的新机型。今天我就来给大家分享几个只有安卓手机才有的隐藏黑科技功能,每个功能都非…

cocos creator新手教程:第003节3D模型的基本概念

3.1 计算机如何制作一个3D模型 讲述这个问题之前,我们先来看下现实生活中我们要做一个模型,应该如何做呢?首先我们要把模型的形状给雕刻构建出来,现实生活中的物体都是由分子组成的连续的表面,计算机是离散的无法做到这…

【jQuery】常用API——尺寸、位置操作

一、jQuery 尺寸 以上参数为空&#xff0c;则是获取相应值&#xff0c;返回的是数字型。如果参数为数字&#xff0c;则是修改相应值。参数可以不必写单位。 <style>div {width: 200px;height: 200px;background-color: pink;padding: 10px;border: 15px solid red;margin…

在Windows中安装Mysql数据库(shawn安装成功记录)

一、下载安装包 首先去官网下载mysql安装包 下载网址:https://dev.mysql.com/downloads/mysql/ 下载Windows系统版本,如下图 注意版本必须是8.xx, 5开头的版本不适合本教程   点击下载,选择自己的文件路径,C盘非C盘都可以(我没有放C盘),路径中不要出现中文…

【蓝桥杯简单篇】Python组刷题日寄Part08

刷题日记&#xff1f;刷题日寄&#xff01; 萌新备战蓝桥杯python组 &#x1f339; 发现有需要纠正的地方&#xff0c;烦请指正&#xff01; &#x1f680; 欢迎小伙伴们的三连关注&#xff01; 往期系列&#xff1a; 【蓝桥杯简单篇】Python组刷题日寄Part01 【蓝桥杯简单篇】…

SCRM开源营销平台MarketGo-创建员工活码

一、背景介绍 客户需求&#xff1a;企业在做营销活动的时候&#xff0c;会有大量的客户需要添加企业微信的联系方式。这样就有两个问题&#xff1a; 一个企业微信账号添加太多会受到企业微信的限制&#xff1b;如果有多个企业微信的账号&#xff0c;添加的客户的数量也不平均…

如何给PPT文件添加水印?

我们在制作PPT的时候&#xff0c;有时候需要在幻灯片上加入logo&#xff0c;或者特定的大小、颜色等一致的文字标题&#xff0c;而幻灯片通常都是很多页数的&#xff0c;如果一张张幻灯片来添加&#xff0c;那就很费功夫。 这种情况&#xff0c;我们就可以选择通过“幻灯片母版…

SSL/TLS协议详解 - https为什么比http更安全

概述 首先纠正一个错误&#xff0c;可能很多初学者都以为HTTPS跟HTTP一样&#xff0c;都属于应用层协议。但其实HTTPS并不是一个单独的协议。HTTPS是安全版本的HTTP&#xff0c;简单理解 HTTPS HTTP SSL/TLS&#xff0c;即HTTPS就是使用SSL/TLS协议对HTTP报文进行了加密处理…

一不小心进入“决赛圈”,没“阳过”的怎么办?

前两天看到一个央视新闻&#xff0c;说河南新冠病毒感染率接近90%&#xff0c;流行毒株是奥密克戎BA.5.2&#xff0c;数字让我挺吃惊的&#xff1a;真有这么多人感染了&#xff1f; 如果是这样&#xff0c;我就属于那幸运的10%了&#xff0c;没有经历过刀片嗓&#xff0c;水泥鼻…

机器学习--模型调参、超参数优化、网络架构搜索

目录 一、模型调参 手动调超参数 多次调参的管理 机器调参与人调参的成本比较 自动调参&#xff08;AutoML&#xff09; 总结 二、超参数优化 在搜索空间中选择超参数 HPO算法有哪些 Black-Box Multi-Fidelity 总结 三、网络架构搜索 Neural Architecture Sear…

【Java AWT 图形界面编程】LayoutManager 布局管理器 ② ( FlowLayout 流式布局 )

文章目录一、FlowLayout 流式布局二、FlowLayout 流式布局 API三、FlowLayout 流式布局代码示例1、FlowLayout 流式布局左对齐代码示例及执行效果2、FlowLayout 流式布局居中对齐代码示例及执行效果2、FlowLayout 流式布局右对齐代码示例及执行效果一、FlowLayout 流式布局 Flo…

上半年要完成的博客60

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

RT-Thread系列--对象容器

一、目的RT-Thread号称小而美&#xff0c;那具体美在哪里呢&#xff1f;下面我们就来说说首先&#xff0c;代码简练逻辑清晰明了&#xff1b;其次是框架设计。其创新性的对象容器系统是我认为最优美的设计亮点&#xff0c;本篇的目的就是给大家介绍一下对象容器的设计以及这样设…

sklearn聚类之谱聚类SpectralClustering

文章目录基本原理sklearn中谱聚类的构造实战基本原理 谱聚类是一种基于图论的聚类方法&#xff0c;所谓图&#xff0c;就是将空间中的所有点连接起来&#xff0c;只要这些连接中出现了一个圈&#xff0c;就可以称之为图。如果把这些连线加上一个权重&#xff0c;就叫做加权图。…

小程序开发经验分享(6)开发流程大全

一、准备的资料 我们在开发微信小程序前,需要准备下相关资料。这个资料主要是后面进行ICP备案,微信小程序认证以及申请支付接口时需要用到。 资料如下: 营业执照【个体经营户或公司都行】银行开户许可证【个体经营户可以用法人个人银行卡】,企业网银【最好开通】。相关类…

车载以太网 - DoIP实体状态信息AliveCheck - 08

我们知道车载以太网的实体在车内一般常见的就是网关和节点,而网关和节点的状态信息对我们的以太网通信尤为重要,我们只有知道节点或者网关所处的状态,才能更好的进行下一步处理或者诊断,今天我们就来详细的了解下DoIP实体的状态信息这部分在ISO 13400中的定义。 DoIP实体状…

多图解析manacher算法原理

什么是manacher算法 用于快速计算一个字符串的最长回文子串 什么是最长回文子串&#xff1f; 例如&#xff1a;abc12321中&#xff0c;最长回文子串为12321&#xff0c;即子字符串中最长&#xff0c;且是回文的那个 怎么用暴力做法找出最长回文子串呢&#xff1f; 长度为奇…