【OpenCV实现图像的算数运算,性能测试和优化,改变颜色空间】

文章目录

    • OpenCV功能概要
    • 图像的算数运算
    • 性能测试和优化
    • 改变颜色空间
    • 对象追踪

OpenCV功能概要

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习库,提供了丰富的图像处理和计算机视觉算法。它支持多种编程语言,包括Python、C++和Java。以下是OpenCV的主要功能概要:

  1. 图像的算数运算:
    OpenCV提供了多种算数运算函数,包括加法、减法、位运算等,可以用来处理图像。这些函数能够执行图像间的像素级别操作,例如图像加法和减法,以及与常数的算数运算。

  2. 性能测试和优化:
    OpenCV提供了丰富的性能测试工具和优化技术,可以帮助开发者评估和提高图像处理算法的性能。使用OpenCV的性能测试功能,可以度量不同操作的执行时间,从而找出性能瓶颈。优化技术包括使用OpenCV的内置函数,以及利用硬件加速(如CUDA和OpenCL)来加速图像处理任务。

  3. 改变颜色空间:
    OpenCV支持多种颜色空间的转换,例如RGB到灰度、RGB到HSV等。这些转换可以帮助开发者在不同颜色空间中进行图像处理,从而更好地理解和操作图像的颜色信息。

图像的算数运算

一些图像上的运算操作,就像加法,减法,位操作等等
函数:cv.add()、cv.addWeighted()等等

1.图像添加
图像的添加是图像处理中常见的操作之一,用于将两幅图像叠加在一起。在OpenCV中,你可以使用cv2.add()函数来实现图像的添加。另外,你也可以使用NumPy进行相似的操作,但需要注意OpenCV和NumPy在处理饱和运算方面的差异。

使用OpenCV的cv2.add()函数时,它会执行饱和运算(saturate operation),即当像素值超过255时,会被截断到255,不会溢出。这是因为图像的像素值通常是8位无符号整数(0到255之间的值),超出这个范围的值会被截断。

import cv2
import numpy as np# 读取两幅图像
img1 = cv2.imread('img.png')
img2 = cv2.imread('img_1.png')# 调整第二幅图像的尺寸与第一幅图像相同
img2_resized = cv2.resize(img2, (img1.shape[1], img1.shape[0]))# 使用NumPy进行图像相加(饱和运算)
added_image_numpy = np.clip(img1.astype(int) + img2_resized.astype(int), 0, 255).astype(np.uint8)# 输出结果
print("NumPy添加结果(饱和运算):", added_image_numpy)
cv2.imshow('Blended Image', added_image_numpy)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.add()函数执行了饱和运算,确保了结果图像的像素值不会超出255。而使用NumPy进行图像相加时,需要使用np.clip()函数来进行饱和运算,确保结果在合理范围内。
在这里插入图片描述

2.图片混合
这种图像叠加操作是通过赋予不同权重给两幅图像,从而实现混合或透明效果的一种方法。具体地,通过以下的线性组合公式:

g(x)=(1−α)f0(x)+αf1(x)g(x)=(1−α)f0​(x)+αf1​(x)

其中,f0(x)f0​(x)和f1(x)f1​(x)分别代表两幅输入图像的像素值,αα表示权重,可以调整从0到1,实现不同程度的混合。在OpenCV中,这种混合效果可以通过cv2.addWeighted()函数实现,其公式如下:

dst=α⋅img1+β⋅img2+γdst=α⋅img1+β⋅img2+γ

在这个公式中,img1和img2分别是两幅输入图像,αα和ββ是相应图像的权重,而γγ通常被设置为0。

以下是一个使用OpenCV进行两幅图像混合的例子:

import cv2# 读取两幅图像
img1 = cv2.imread('img.png')
img2 = cv2.imread('img_1.png')# 调整第二幅图像的尺寸与第一幅图像相同
img2_resized = cv2.resize(img2, (img1.shape[1], img1.shape[0]))# 设置权重
alpha = 0.7
beta = 0.3# 图像混合
blended_img = cv2.addWeighted(img1, alpha, img2_resized, beta, 0)# 显示混合结果
cv2.imshow('Blended Image', blended_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:
在这里插入图片描述

3.位操作
我想把OpenCV的图标放到一个图片上面。如果我直接相加两个图像,图标的颜色就会被改变。如果是选择混合他们,那么透明度就会受影响。但我希望它是不透明的。如果这是一个规则的区域,我就可以用上一个章节使用的ROI来操作。但是OpenCV图标并不是一个规则的形状。所以你可以通过下面的例子进行位运算。

使用位运算来处理两幅图像,将OpenCV的图标放置在另一幅图像的特定区域上,并确保它是不透明的。以下是代码的详细解释:

  1. 加载图片:
img1 = cv.imread('messi5.jpg')
img2 = cv.imread('opencv-logo-white.png')

2.创建ROI区域:
我们希望将img2(OpenCV的图标)放在img1的左上角。因此,我们创建一个ROI区域,其大小与img2相同。

rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]

3.创建徽标蒙版和反向蒙版:
我们将img2转换为灰度图像,然后使用阈值将其二值化(变为黑白图像)。接着,我们通过cv.bitwise_not()函数创建反向蒙版。

img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)

4.背景提取和前景提取:
使用cv.bitwise_and()函数,我们将ROI区域中的徽标区域涂黑,得到背景提取的图像(img1_bg)。然后,我们从徽标图像中提取徽标区域,得到前景提取的图像(img2_fg)。

img1_bg = cv.bitwise_and(roi, roi, mask=mask_inv)
img2_fg = cv.bitwise_and(img2, img2, mask=mask)

5.合并前景和背景:
将前景和背景图像相加,得到最终的结果图像。

dst = cv.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst

6.显示结果:
最终,通过cv.imshow()函数显示结果图像,你也可以在代码中插入其他步骤来查看中间结果。

  cv.imshow('res', img1)cv.waitKey(0)cv.destroyAllWindows()

这个例子中使用位运算,将OpenCV的图标合并到了另一幅图像的特定区域上,同时确保了不透明度。

性能测试和优化

函数:cv.getTickCount,cv.getTickFrequency 等等
在OpenCV中,你可以使用cv.getTickCount()函数来获取一个时间戳,该时间戳表示自系统启动以来的时钟周期数。你还可以使用cv.getTickFrequency()函数来获取时钟周期的频率,即每秒的时钟周期数。通过这两个函数,你可以计算函数的运行时间。

具体步骤如下:

使用cv.getTickCount()获取函数开始时的时间戳。
e1 = cv.getTickCount()
在你的代码执行完毕后,再次调用cv.getTickCount()获取函数结束时的时间戳。
  # 你的代码
e2 = cv.getTickCount()

计算函数的运行时间(以秒为单位)。

time = (e2 - e1) / cv.getTickFrequency()

这样,time变量将包含函数的运行时间(以秒为单位)。

OpenCV中默认的优化方法

OpenCV中的许多函数都利用了现代处理器的特殊指令集(如SSE2、AVX等)进行优化,以提高性能。OpenCV同时也包含了未经过优化的代码。因此,如果系统支持这些特殊指令集(几乎所有现代处理器都支持),应该充分利用它们。
在编译时,OpenCV默认会启用这些优化,因此在运行时,OpenCV会尽量使用经过优化的代码。只有在不支持这些指令集的情况下,OpenCV才会使用未优化的代码。可以使用cv.useOptimized()函数来检查优化是否启用,以及使用cv.setUseOptimized()函数来手动启用或禁用优化。

# 检查是否启用优化
print(cv.useOptimized())  # 输出: True# 使用优化进行中值滤波,循环10次,计算平均每次循环的时间
%timeit res = cv.medianBlur(img, 49)# 禁用优化
cv.setUseOptimized(False)# 检查是否禁用了优化
print(cv.useOptimized())  # 输出: False# 禁用优化后进行中值滤波,循环10次,计算平均每次循环的时间
%timeit res = cv.medianBlur(img, 49)

在IPython中的测量方法
在IPython中,你可以使用神奇的timeit命令来完成这个任务。timeit通过多次运行代码获取准确的结果,同样也适用于单行代码。

比如,你想知道以下几种操作哪个更快:x = 5; y = x**2,x = 5; y = x * x,x = np.uint8([5]); y = x * x,或者是 y = np.square(x)。我们可以在IPython中找到答案。

x = 5%timeit y = x**2
# 输出结果:10000000 loops, best of 3: 73 ns per loop%timeit y = x * x
# 输出结果:10000000 loops, best of 3: 58.3 ns per loopz = np.uint8([5])%timeit y = z * z
# 输出结果:1000000 loops, best of 3: 1.25 us per loop%timeit y = np.square(z)
# 输出结果:1000000 loops, best of 3: 1.16 us per loop

你会发现,x = 5; y = x * x 的速度要比Numpy的快20倍。如果考虑到创建一个数组,这个差距可能会更大,这真的很酷(实际上,Numpy就是用来解决这类问题的)。

需要注意的是,Python的标量运算远比Numpy的快。所以,如果你只是对一两个元素进行操作,可能没有必要使用Numpy。Numpy的真正优势体现在大量数据的矩阵运算上。

接下来,我们尝试比较cv.countNonZero()和np.count_nonzero()函数在操作同一张图片时的性能表现。

%timeit z = cv.countNonZero(img)
# 输出结果:100000 loops, best of 3: 15.8 us per loop%timeit z = np.count_nonzero(img)
# 输出结果:1000 loops, best of 3: 370 us per loop

可以看到,OpenCV的函数比Numpy的快了大约25倍。

需要注意的是,通常情况下,OpenCV的函数比Numpy的函数更快。因此,在进行相同操作时,OpenCV的性能会更好。不过,也有一些例外情况,具体取决于操作的性质,特别是当Numpy使用视图而不是副本时。

改变颜色空间

图像从一个颜色空间转换到另外一个,就像 BGR ↔ Gray, BGR ↔ HSV ,等等。
创建一个应用程序来提取视频中的色彩对象。
函数:cv.cvtColor(),cv.inRange()等等。
注意:Note 对于 HSV,色调范围为 [0,179],饱和度范围为 [0,255],值范围为 [0,255]。不同的软件使用不同的尺度。因此,如果您将 OpenCV 值与它们进行比较,则需要对这些范围进行归一化。

改变颜色空间

在OpenCV中,有超过150种颜色空间转换方法,但我们通常关注其中两种最常用的:BGR到灰度(BGR ↔ Gray)和BGR到HSV(BGR ↔ HSV)的转换。

在颜色转换中,我们使用cv.cvtColor(input_img, flag)函数,其中flag参数用于确定转换的类型。

对于BGR到灰度的转换,我们将cv.COLOR_BGR2GRAY传递给flag参数。类似地,对于BGR到HSV的转换,我们将cv.COLOR_BGR2HSV传递给flag参数。可以在Python中运行以下代码:

import cv2 as cvflags = [i for i in dir(cv) if i.startswith('COLOR_')]print(flags)

需要注意的是,在HSV颜色空间中,色调范围是0,1790,179,饱和度范围是0,2550,255,值范围是0,2550,255。不同的软件使用不同的尺度。因此,如果你想将OpenCV中的值与其他软件进行比较,你需要对这些范围进行归一化处理。

对象追踪

现在,我们已经学会如何将一幅BGR图像转换成HSV颜色空间。接下来,我们可以利用这个知识来提取特定颜色的对象。在这个例子中,我们将尝试提取蓝色对象的图像。

以下是具体的步骤:

获取每一帧图像: 从视频中捕获每一帧图像。颜色空间转换: 将BGR图像转换为HSV颜色空间,这样更容易提取特定颜色的对象。颜色阈值处理: 在HSV颜色空间中,指定蓝色的阈值范围(lower_blue和upper_blue)。这样,我们可以定位在该范围内的蓝色像素。创建掩码: 使用cv.inRange()函数创建一个掩码,该掩码仅包含在指定蓝色范围内的像素。提取蓝色对象: 将掩码应用到原始图像上,使用cv.bitwise_and()函数,这样就可以提取出蓝色对象的图像。显示图像: 分别显示原始图像、掩码和提取出的蓝色对象的图像。等待用户操作: 等待用户按下键盘上的ESC键(ASCII码为27)来退出循环。释放资源: 当用户按下ESC键后,释放所有窗口资源。
import cv2 as cv
import numpy as npcap = cv.VideoCapture(0)while True:# 获取每一帧_, frame = cap.read()# 从BGR转换到HSVhsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)# 在HSV中定位蓝色范围lower_blue = np.array([110, 50, 50])upper_blue = np.array([130, 255, 255])# 设置HSV图像仅获得蓝色图像mask = cv.inRange(hsv, lower_blue, upper_blue)# 按位与掩码和原始图像res = cv.bitwise_and(frame, frame, mask=mask)# 显示图像cv.imshow('Original', frame)cv.imshow('Mask', mask)cv.imshow('Blue Object', res)# 等待用户按下ESC键退出k = cv.waitKey(5) & 0xFFif k == 27:break# 释放资源
cap.release()
cv.destroyAllWindows()

在这里插入图片描述

Note 图像中有些噪声。我们将在后面演示如何去除它。这个是一个简单的项目追踪方法。一旦你学会了轮廓的函数,你就可以做一系列事情,就像是找到一个物体的质心并用它去跟踪物体,或者是只需要在相机前移动你的手就可以画出图表,或者其他有趣的事情。

要找到需要跟踪的颜色的HSV值,可以使用OpenCV中的cv.cvtColor()函数。不需要传递整个图像,只需传递所需的BGR值即可。以下是一个示例,假设想找到绿色的HSV值:

import numpy as np
import cv2 as cv# 定义一个绿色的BGR值
green = np.uint8([[[0, 255, 0]]])# 将BGR转换为HSV
hsv_green = cv.cvtColor(green, cv.COLOR_BGR2HSV)print(hsv_green)

运行这段代码,会得到绿色的HSV值:[[[60 255 255]]]。现在,可以将这个HSV值作为跟踪绿色的下限(Lower Bound):[H-10, 100, 100],和上限(Upper Bound):[H+10, 255, 255]。在这个例子中,绿色的H值为60,所以下限为50,上限为70。这个范围可以根据实际情况微调。

另外,除了使用代码计算HSV值外,也可以使用图像编辑工具(如GIMP)或在线颜色转换器来找到这些值。但是请记住,确保在使用这些工具时调整HSV范围,因为不同的工具可能使用不同的HSV标准。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS色域、色彩空间、CSS Color 4新标准 | 京东云技术团队

引言 近期,三大主流浏览器引擎均发布最新版本,支持W3C的CSS Color 4标准,包含新的取色方法color()和相应语法,可展示更多的色域及色彩空间,这意味着web端能展示更丰富更高清的色彩。虽然目前只有最新版本的现代浏览器…

一个Entity Framework Core的性能优化案例

概要 本文提供一个EF Core的优化案例,主要介绍一些EF Core常用的优化方法,以及在优化过程中,出现性能反复的时候的解决方法,并澄清一些对优化概念的误解,例如AsNoTracking并不包治百病。 本文使用的是Dotnet 6.0和EF…

Unity3D 如何用unity引擎然后用c#语言搭建自己的服务器

Unity3D是一款强大的游戏开发引擎,可以用于创建各种类型的游戏。在游戏开发过程中,经常需要与服务器进行通信来实现一些功能,比如保存和加载游戏数据、实现多人游戏等。本文将介绍如何使用Unity引擎和C#语言搭建自己的服务器,并给…

后端实现大文件分片上传

项目框架 net6 webapi 放开上传大小限制 放开代码 | 框架层限制 在 Program.cs 文件中添加如下代码 不然会出现下面的限制错误 From表单限制:Failed to read the request form. Multipart body length limit 134217728 exceeded 请求体超长:Request bo…

docker - DockerFile 编写 指令

文章目录 前言docker - DockerFile 编写 指令1. FROM2. MAINTAINER3. RUN4. CMD5. LABEL6. EXPOSE7. ENV8. ADD9. COPY10. ENTRYPOINT11. VOLUME12. USER13. WORKDIR14. ARG15. ONBUILD16. STOPSIGNAL 前言 如果您觉得有用的话,记得给博主点个赞,评论&am…

如何使用Abaqus进行摩擦生热仿真

Abaqus除了可以对结构进行强度分析,同样也有强大的固体传热分析功能,下面通过一个简单的实例演示Abaqus的双向热固耦合分析。 因为本案例涉及物体表面辐射,因此需要定义绝对零度和输入史蒂夫-波兹曼常数,如下: 本次分…

B链圆桌派 — 创新的去中心化存储网络 BNB GREENFIELD 主网上线

B链圆桌派 主題: BNB GREENFIELD主网上线 - 创新的去中心化资料储存网路 日期: 10/19, 8 pm utc8 頻道: BNB Chain 华语电报群 ○ AMA环节 ○ BNB GREENFIELD主网上线 一、回复主持人问题 嘉宾回答主持人提出的问题。本环节请大家保持安静,专注嘉宾…

一文搞懂 MineCraft 服务器启动操作和常见问题 2023年10月

文章目录 前言1. 新建文件夹2. 创建 bat 文件3. 编辑 bat 文件4. 启动服务器5. 恭喜完成 文章持续更新中,如果你有问题可以通过 qq 1317699264 获取免费协助,解决的问题将会被更新到本文章中 前言 无论你是使用服务端整合包,还是从上一篇我的…

为虚拟网络提供敏捷负载均衡:Everoute LB 特性解读

为了保证应用系统的可用性,同时避免并发访问导致后端服务器出现性能瓶颈,不少用户都通过负载均衡技术优化流量分发。随着虚拟化平台下用户业务规模的持续扩大,虚拟化网络的数据访问量也不断增加,而传统负载均衡通常通过硬件负载均…

漫谈广告机制设计 | 混排:广告与自然结果的交锋博弈(2)

话说前文,在彼此不同的利益面前,自然侧和广告侧在混排战场展开了一番较量,一个浑水摸鱼,一个暗渡陈仓。最终双方不得不坐下来,为了平台整体的利益,一起谈谈各自的诉求,商讨一下解决方案。 第三…

一个比较特别的串口工具

这是08年写的一个 并网带电池逆变器 的通讯工具,和普通的串口调试器相比,多了一个【脚本】功能。能够通过【脚本】完成通讯测试。 PC发给DSP的01命令 01 10 1B 00 CF A3 00 00 90 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 电…

【Linux】虚拟机部署与发布J2EE项目(Windows版本)

【Linux】虚拟机部署与发布J2EE项目(Windows版本) 1.将Java项目部署到虚拟机(Virtual Machine)有以下好处:2.单机项目1.将项目共享到虚拟机2.解压并将war包放入tomcat3.运行tomcat并查看该项目的数据库配置4.数据库导入…