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

news2024/12/25 2:16:59

第六部分、图像操作-2

    • 第一节、图像几何形状绘制
      • 1.几何形状
      • 2.填充、绘制与着色
      • 3.代码练习与测试
    • 第二节、多边形填充与绘制
      • 1.多边形绘制函数
      • 2.绘制与填充
      • 3.代码练习与测试
    • 第三节、图像像素类型转换与归一化
      • 1.归一化方法与支持
      • 2.归一化函数
      • 3.代码练习与测试
    • 第四节、图像几何变换
      • 1.图像几何变换矩阵
      • 2.函数支持
      • 3.代码练习与测试
    • 学习参考

第一节、图像几何形状绘制

1.几何形状


  • 支持绘制线、矩形、圆形
  • 支持填充矩形、圆形、椭圆
  • 支持绘制文本

注意:绘制只能用英文

几何形状的函数:

相关函数
1.cv.line() # 线
2.cv.circle() # 圆形
3.cv.rectangle() # 矩形
4.cv.ellipse() # 椭圆
5.cv.putText() # 文本
# 相关参数解释:
# img表示输入图像
# color表示颜色,如(255, 0,0)表示蓝色,注意颜色维度要和通道数匹配
# thickness表示线宽, 大于0表示绘制,小于0表示填充
# lineType表示渲染模式, 默认LINE_8, LINE_AA表示反锯齿
# 渲染指的是,绘制一个图的时候会对每个像素点周围4个或8个点进行渲染,常用的是LINE_8
# 反锯齿是另一种渲染方式,使用反锯齿渲染的图片效果更好,但是会比较耗时
# 如果追求用户体验并且计算机带的动就用LINE_AA,如果追求性能就用LINE_8

文本绘制:

  • putText 默认只支持英文
  • org表示文字起始坐标点
  • fontFace表示字体类型
  • fontScale表示字体大小

计算文本区域大小:

# 计算文本区域大小的函数
getTextSize (
text,  # 表示文本信息
fontFace, # 表示字体类型
fontScale, # 表示字体大小
thickness # 表示线宽
) 
# 返回文本信息区域大小,与字体的基线baseline位置

如下图包裹OpenCV-Python的白色框就是文本区域大小

在这里插入图片描述

2.填充、绘制与着色


def draw_demo_1():
    # 创建一个512*512*3大小的图像作为画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # (100, 100)是起点坐标,(300, 300)是终点坐标
    # 绘制一个红色矩形
    cv.rectangle(canvas, (100, 100), (300, 300), (0, 0, 255), 2, 8)
    # 填充一个紫色矩形
    cv.rectangle(canvas, (400, 100), (450, 150), (255, 0, 255), -1, 8)
    # 绘制一个蓝色圆形
    cv.circle(canvas, (250, 250), 50, (255, 0, 0), 2, cv.LINE_8)
    # 填充一个蓝色圆形
    cv.circle(canvas, (425, 200), 20, (255, 0, 0), -1, cv.LINE_8)
    # 绘制一个绿色线段,lineType=8指的是8联通线型,涉及到线的产生算法,另一种是lineType=4指的是4联通线型
    cv.line(canvas, (100, 100), (300, 300), (0, 255, 0), 2, 8)
    # 添加一个文本
    cv.putText(canvas, "OpenCV-Python", (100, 100), cv.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 255), 2)
    cv.imshow("canvas", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:右图是矩形的参数列表

在这里插入图片描述

3.代码练习与测试


# 动态显示文本区域
def draw_demo_2():
    # 创建一个512*512*3大小的图像作为画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # 深度学习对象检测经典颜色:土耳其蓝(140, 199, 0)
    font_color = (140, 199, 0)
    cv.rectangle(canvas, (100, 100), (300, 300), font_color, 2, 8)

    label_txt = "OpenCV-Python"
    label_txt2 = "Hello world is a nice sentence."
    font = cv.FONT_HERSHEY_SIMPLEX  # 字体选择建议就是cv.FONT_HERSHEY_SIMPLEX 或者 cv.FONT_HERSHEY_PLAIN
    font_scale = 0.5  # 字体大小0.5
    thickness = 1  # 线宽1
    # cv.getTextSize动态获取文本,(fw, uph)是宽、高,dh是基线
    (fw, uph), dh = cv.getTextSize(label_txt, font, font_scale, thickness)
    (fw2, uph2), dh2 = cv.getTextSize(label_txt2, font, font_scale, thickness)
    cv.rectangle(canvas, (100, 80-uph-dh), (100+fw, 80), (255, 255, 255), -1, 8)
    cv.rectangle(canvas, (100, 100-uph2-dh2), (100+fw2, 100), (255, 255, 255), -1, 8)
    cv.putText(canvas, label_txt, (100, 80-dh), font, font_scale, (255, 0, 255), thickness)
    cv.putText(canvas, label_txt2, (100, 100-dh), font, font_scale, (255, 0, 255), thickness)
    cv.imshow("canvas", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

动态显示文本示例:

在这里插入图片描述

第二节、多边形填充与绘制

1.多边形绘制函数

# 填充多边形
1.cv.fillPoly(img, pts, color[, lineType[, shift[, offset]]]) ->img
# 绘制多边形
2.cv.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]] ) ->img
# pts表示一个或者多个点集
# color表示颜色
# thickness表示线宽,注意:必须大于0
# lineType 表示渲染方式

pts表示一个或多个点集

pts = []
pts.append((100, 100))
pts.append((200, 50))
pts.append((280, 100))
pts.append((290, 300))
pts.append((50, 300))
pts = np.asarray(pts, dtype=np.int32)
print(pts.shape)
# 要求:必须是CV_32S, 对应np.int32

2.绘制与填充


支持一次绘制多个图形

例如:红色边框是绘制、蓝色区域是填充

在这里插入图片描述

3.代码练习与测试


# 多边形绘制
def poly_demo():
    # 设置画布
    canvas = np.zeros((512, 512, 3), dtype=np.uint8)
    # pts = [(100, 100), (200, 50), (280, 100), (290, 300), (50, 300)]
    pts = []
    pts.append((100, 100))
    pts.append((200, 50))
    pts.append((280, 100))
    pts.append((290, 300))
    pts.append((50, 300))
    pts = np.array(pts, dtype=np.int32)
    print(pts.shape)

    pts2 = []
    pts2.append((300, 300))
    pts2.append((400, 250))
    pts2.append((500, 300))
    pts2.append((500, 500))
    pts2.append((250, 500))
    pts2 = np.array(pts2, dtype=np.int32)
    print(pts2.shape)

    # 同时绘制两个点集
    cv.polylines(canvas, [pts, pts2], True, (0, 0, 255), 2, 8)
    # 填充
    cv.fillPoly(canvas, [pts, pts2], (255, 0, 0), 8, 0)
    cv.imshow("poly-demo", canvas)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

第三节、图像像素类型转换与归一化

1.归一化方法与支持


图像归一化就是让图像在不同情况下来回转换。

OpenCV中常用的归一化方法:

  • NORM_MINMAX
  • NORM_INF
  • NORM_L1
  • NORM_L2
  • 最常用 NORM_MINMAX
  • NORM_L1与NORM_L2范数
    • 下图中L1范数 = x / (∑ xi),例如0.1 = 2.0 / (2.0 + 8.0 + 10.0)
    • 下图中L2范数 = x / (∑ xi ^ 2) ^ 1/2 ,例如0.15 = 2.0 / (4.0 + 64.0 +100.0) ^ 1/2

在这里插入图片描述

2.归一化函数


1.cv.normalize(	src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]	) -> dst
# src表示输入图像, dst表示输出图像
# alpha, beta 默认是1, 0,是归一化的区间值
# norm_type默认是NORM_L2, 
# norm_type常用是NORM_MINMAX
2.数据转换
# Imread读入默认是uint8, 转换为float32
# 通过imshow显示之前,必须归一化到[0~1]之间。

在这里插入图片描述

3.代码练习与测试


图像像素NORM_MINMAX归一化:

# 图像像素类型转换与归一化
def norm_demo():
    image_uint8 = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    cv.imshow("image_uint8", image_uint8)
    img_f32 = np.float32(image_uint8)
    cv.imshow("image_f32", img_f32)
    cv.normalize(img_f32, img_f32, 1, 0, cv2.NORM_MINMAX)
    cv.imshow("norm-img_f32", img_f32)
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:当图片类型从uint8转换到f32之后,如果不适用归一化结果如中间所示只有一堆点,使用归一化之后结果如右图所示。

因为imshow只支持两种类型显示,一种是uint8(0, 255),另一种是f32(0, 1)。

在这里插入图片描述

滚动条显示四种归一化方法:

# 定义滚动条的注册响应
def trackbar_norm_callback(pos):
    print(pos)


# 用滚动条实现四种归一化方式
def norm_trackbar_demo():
    image_uint8 = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    cv.namedWindow("norm-demo", cv.WINDOW_AUTOSIZE)
    # 注意使用cv.createTrackbar滚动条之前线要定义注册响应trackbar_norm_callback
    cv.createTrackbar("normtype", "norm-demo", 0, 3, trackbar_norm_callback)
    while True:
        dst = np.float32(image_uint8)
        pos = cv.getTrackbarPos("normtype", "norm-demo")
        if pos == 0:
            cv.normalize(dst, dst, 1, 0, cv.NORM_MINMAX)
        if pos == 1:
            cv.normalize(dst, dst, 1, 0, cv.NORM_L1)
        if pos == 2:
            cv.normalize(dst, dst, 1, 0, cv.NORM_L2)
        if pos == 3:
            cv.normalize(dst, dst, 1, 0, cv.NORM_INF)
        cv.imshow("norm-demo", dst)
        # 每过50ms就获取一个键值,默认键值为-1,ESC键值为27
        c = cv.waitKey(50)
        if c == 27:
            break
    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

第四节、图像几何变换

1.图像几何变换矩阵


图像的变化使用几何变换矩阵实现的

所以图像几何变换最重要的就是几何变换矩阵M(2x3),前面四个参数是控制放缩,最后一列是平移

例如:矩形变圆形

  • 平移变换
    在这里插入图片描述

  • 放缩变换
    在这里插入图片描述

  • 旋转变换
    在这里插入图片描述

2.函数支持


# 仿射变换
1. cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]	) --> dst
# src表示输入图像
# M 表示2x3变换矩阵
# dsize表示目标图像输出dst的大小
# 支持平移变换、放缩变换、旋转变换

输出dst形式如下所示:实现原坐标(x,y)到目标位置的变换

在这里插入图片描述

# 旋转矩阵获取
2. cv.getRotationMatrix2D
# Center表示旋转中心
# angle表示度数,>0表示逆时针旋转
# scale表示放缩尺度大小

# 翻转
3. cv.flip(src, flipCode[, dst]	) ->dst
# 特殊角度旋转
4. cv.rotate(src, rotateCode[, dst]	) -> dst
# src表示输入图像
# flipCode支持0水平、1垂直,-1对角线翻转,只表示翻转
# rotateCode只支持旋转90°,180°,270°,不支持任意角度旋转

3.代码练习与测试


# 图像几何旋转
def affine_demo():
    image = cv.imread(r"F:\python\opencv-4.x\samples\data\ml.png")
    h, w, c = image.shape
    # 获取中心位置
    cx = int(w/2)
    cy = int(h/2)
    cv.imshow("image", image)
    # 定义原图放缩0.7倍,上下均平移50的矩阵M
    M = np.zeros((2, 3), dtype=np.float32)
    M[0, 0] = .7
    M[1, 1] = .7
    M[0, 2] = 50
    M[1, 2] = 50
    print("M(2x3) = \n", M)
    dst = cv.warpAffine(image, M, (int(w*.7), int(h*.7)))
    cv.imshow("rescale-demo", dst)
    # 在指定路径写一个图片
    cv.imwrite(r"F:\python\opencv-4.x\result.png", dst)

    # 定义旋转,获取旋转矩阵degree>0,表示逆时针旋转,原点在左上角
    # (w/2, h/2)表示旋转中心,逆时针旋转45°,放缩1.0即不做放缩操作。
    M = cv.getRotationMatrix2D((w/2, h/2), 45.0, 1.0)
    dst = cv.warpAffine(image, M, (w, h))
    cv.imshow("rotate-demo", dst)

    # 图像翻转,0表示水平翻转
    dst = cv.flip(image, 0)
    cv.imshow("flip-demo", dst)

    # 图像特殊角度旋转,顺时针旋转90°
    dst = cv.rotate(image, cv.ROTATE_90_CLOCKWISE)
    cv.imshow("rotate-90-demo", dst)

    cv.waitKey(0)
    cv.destroyAllWindows()

结果示例:

在这里插入图片描述

学习参考

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

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

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

相关文章

小智学长嵌入式入门学习路线_1 C语言基础

原课程链接: 嵌入式开发系统学习路线 从基础到项目 精品教程 单片机工程师必备课程 物联网开发 c语言 2022追更 前言 在学习过程中,老师提到了一个很重要的思想:主要从学习嵌入式的角度学习各项技能。比如c语言,语法有很多&…

【Java|golang】1807. 替换字符串中的括号内容

给你一个字符串 s ,它包含一些括号对,每个括号中包含一个 非空 的键。 比方说,字符串 “(name)is(age)yearsold” 中,有 两个 括号对,分别包含键 “name” 和 “age” 。 你知道许多键对应的值,这些关系由…

Linux基本功系列之chmod命令实战

文章目录一. chmod命令介绍二. 语法格式及常用选项三. 参考案例3.1 对全部用户增加写的权限3.2 所有用户减去读的权限3.3 给文件的所有者和所有组加上读写权限3.4 设置所有用户为读写执行的权限3.5 文件拥有着为rwx,所属组为rw,其它为r3.6 去掉所有者的r…

高级Spring之ApplicationContext功能

第一步,我们先来看这个接口的内部结构,了解别人的内部,知己知彼,百战不殆: 这个接口的扩展功能主要体现在它继承的四个接口上: MessageSource:国际化功能 ResourcePatternResolver: 资源访问功…

第23章_Tomcat和JavaEE入门

一、JavaEE简介什么是JavaEEJavaEE(Java Enterprise Edition),Java企业版,是一个用于企业级web开发平台。最早由Sun公司定制并发布,后由Oracle负责维护。JavaEE平台规范了在开发企业级web应用中的技术标准.在JavaEE平台…

Acwing——第 87 场周赛

题目链接 4797. 移动棋子 4798. 打怪兽 4799. 最远距离 题目描述 4797. 移动棋子 给定一个 5 行 5 列的方格矩阵,其中一个方格中有一个棋子。 现在,我们希望将棋子移动至矩阵的最中心方格中,即将其移动至矩阵的第 3行第 3列方格中。 每次…

8种时间序列分类方法总结

对时间序列进行分类是应用机器和深度学习模型的常见任务之一。本篇文章将涵盖 8 种类型的时间序列分类方法。这包括从简单的基于距离或间隔的方法到使用深度神经网络的方法。这篇文章旨在作为所有时间序列分类算法的参考文章。 时间序列定义 在涵盖各种类型的时间序列 (TS) 分…

分布式锁与实现(一)-为什么需要分布式锁

1 在开发中的锁是什么 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。 在java中我们有两种资源控制方式Synchronized与AQS 1.2 基于Synchronized实现的锁控制 Synchronized是java提供的一…

JDK 8新特性之Lambda表达式

目录 一:使用匿名内部类存在的问题 Lambda表达式写法,代码如下: 二:Lambda的标准格式 三:Lambda的实现原理 四:Lambda省略格式 五:Lambda的前提条件 六:函数式接口 七:Lambd…

05回溯法

文章目录装载问题回溯算法优化算法构造最优解0-1背包问题批处理作业调度问题图的M着色问题N皇后问题最大团问题回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回&…

12. 字典dict类型详解

1. 基础知识 (1) 字典(dictionary)是Python中另一个非常有用的内置数据类型。 (2) 列表是有序的对象集合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。 (3) 字典是一种映射类型&#xff…

Flowable进阶学习(三)流程、流程实例挂起与激活;启动、处理、结束流程的原理以及相关表结构与变动

文章目录流程挂起与激活流程实例挂起与激活启动、处理、结束流程的原理一、启动流程的原理启动一个流程实例时涉及到的表及表结构:ACT_RU_EXECUTION 运行时流程执行实例ACT_RU_IDENTITYLINK 运行时用户关系信息ACT_RU_TASK 运行时任务表ACT_RU_VARIABLE 运行时变量表二、处理流…

过滤器Filter总结

过滤器Filter1. 简介2. 快速入门3. 执行流程4. 使用细节4.1 拦截路径4.2 过滤器链5. 案例5.1 需求5.2 LoginFilter1. 简介 过滤器是JavaWeb三大组件之一(Servlet、Filter,Listner); 作用: 把对资源(servl…

Ubuntu22.04 安装 ssh

文章目录Ubuntu22.04 安装 ssh一、 环境配置二、 启动远程连接三、 开放端口四、 远程连接Ubuntu22.04 安装 ssh 一、 环境配置 安装 Ubuntu 系统后,我们首先需要配置管理员 root 用户: sudo passwd root然后,进行软件源的更换&#xff1a…

14 Java集合(Map集合+HashMap+泛型使用+集合面试题)

集合14.11 Map集合14.11.1 Map集合特点14.11.2 Map集合体系结构14.12 HashMap14.12.1 HashMap基本使用14.12.2 HashMap实际应用14.12.3 HashMap练习14.12.4 HashMap底层实现原理14.12.5 put的过程原码14.12.6 resize过程原码14.12.7 get的过程原码14.13 HashTable14.14 泛型高级…

5-1中央处理器-CPU的功能和基本结构

文章目录一.CPU的功能二.CPU的基本结构(一)运算器1.运算器的基本组成2.专用数据通路方式3.CPU内部单总线方式(二)控制器1.基本组成2.实现过程(三)寄存器一.CPU的功能 中央处理器(CPU&#xff0…

并查集的入门与应用

目录 一、前言 二、并查集概念 1、并查集的初始化 2、并查集的合并 3、并查集的查找 4、初始化、查找、合并代码 5、复杂度 二、路径压缩 三、例题 1、蓝桥幼儿园(lanqiaoOJ题号1135) 2、合根植物(2017年决赛,lanqiaoO…

SQL注入篇 - 布尔盲注及延时注入

数据来源 盲注 什么是盲注: 布尔盲注原理 布尔盲注流程 手工盲注思路(以下的文章参考:DVWA-sql注入(盲注) - N0r4h - 博客园) 手工盲注的过程,就像你与一个机器人聊天,这个机器人知…

DGSEA | GSEA做完了不要停,再继续比较一下有意义的通路吧!~

1写在前面 GSEA大家都会用了,但GSEA也有它自己的缺点,就是不能比较两个基因集或通路的富集情况。🤒 今天介绍一个Differential Gene Set Enrichment Analysis (DGSEA),可以量化两个基因集的相对富集程度。😉 2用到的包…

Java中的位运算及其常见的应用

文章目录1、位运算1.1 原码、反码、补码1.2 位运算符2、位运算的应用2.1 取模运算2.2 奇偶性判断2.3 交换变量的值2.4 加法运算1、位运算 1.1 原码、反码、补码 计算机中所有数据的存储和运算都是以二进制补码的形式进行的。a —> 97,A —> 65,‘…