在 python 中使用 OpenCV 分割图像

Posted

技术标签:

【中文标题】在 python 中使用 OpenCV 分割图像【英文标题】:Splitting Image using OpenCV in python 【发布时间】:2013-10-11 11:13:01 【问题描述】:

我有一个图像,想在 python 中使用 CV2 将其拆分为三个 RGB 通道图像。

我还想要好的文档,我可以在其中找到 openCV 的所有功能,因为我对 OpenCV 完全陌生。

【问题讨论】:

【参考方案1】:

正如documentation tutorial 中所提到的,就性能(时间)而言,cv2.split() 是一项代价高昂的操作如果您不想在所有通道上操作而只想操作一个/两个 strong>,因此首选 numpy 索引:

import cv2
import numpy as np
img = cv2.imread("foo.jpg")
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]

记住,opencv 将图像读取为 BGR 而不是 RGB

编辑: @Mitch McMabers,感谢您指出这一点。如果您只想单独处理一个/两个通道,请使用此方法以获得最大效率。如果您想在所有三个频道上进行操作,请使用 cv2.split() 访问频道,如@jabaldeno 的回答中所述。

【讨论】:

您误解了文档(您链接到的页面)。它说:如果您想在 1 个颜色通道上做一些基本的事情(例如将所有红色设置为零),只需使用 numpy 索引,例如img[:,:,2] = 0,或者您只想要三个通道中的一个,请使用b = img[:,:,0]。在这两种情况下,提取 3 个通道是没有意义的。但是如果你确实想要获得所有 3 个通道,使用 split 功能应该会更快。 @MitchMcMabers 实际上,在我使用timeit(1908, 2800, 3) 图像进行测试时,与拆分平均23.7 ms 相比,索引平均1.17 uscv2.split() 似乎是更昂贵的操作。 嗯,有趣...python -m timeit -s "import urllib.request as r; import cv2; from os.path import exists as ex; b='bench.jpg'; r.urlretrieve('https://i.imgur.com/7vGjNmZ.jpg',b) if not ex(b) else False; x=cv2.imread(b)" "b,g,r = cv2.split(x)" 提供 33.1 ms"b,g,r = x[:,:,0], x[:,:,1], x[:,:,2]" 提供 803 nsec (0.000803 ms)。诡异的!带有 numpy 索引的后者对 numpy C 扩展进行 3 次函数调用,而 OpenCV 方法仅进行 1 次 C 调用并且应该进行优化,但事实并非如此。除非我们做错了什么,否则很高兴知道,谢谢! 没关系,我已经想通了。 Numpy 方法使用 Numpy 切片,它创建了一个新的(非常低效的)Numpy 数组“视图”,它指向旧 RAM,并说“读取每 3 个字节,跳过第 1 个和第 2 个字节”以仅查看单个通道。这是“假分割”通道,但在图像处理方面效率极低。每次将假的 r,g 或 b(以这种方式创建)传递给 OpenCV 或其他库函数时,都会为每个函数调用造成 30 毫秒的延迟,因为它必须将“作弊”的 Numpy 数据重新创建为真实的图像对象。同时,OpenCV split 会创建 3 个真实的 img。 这是一篇关于通过 Numpy 以这种方式作弊的成本的文章。使用索引可能看起来很快(“哦,0.000803 毫秒通过 numpy 进行拆分,而不是 33.1 毫秒通过 OpenCV 进行拆分”),但这都是谎言——如果您滥用 Numpy 技巧,则不会拆分数据;没有在 RAM 中创建真正的“分割”图像——实际上 Numpy 技巧非常非常慢,因为每次你给 OpenCV 函数和其他库提供这样的“假分割”时都必须修复数据:answers.opencv.org/question/219040/… (cv2.split() 是真正的分裂)。【参考方案2】:

这就像使用cv2.imread 加载图像然后使用cv2.split 一样简单:

>>> import cv2
>>> import numpy as np
>>> img = cv2.imread("foo.jpg")
>>> b,g,r = cv2.split(img)

OpenCV 文档可从docs.opencv.org获得

【讨论】:

如何保存那些 b,g,r 图像?你能推荐我可以找到所有功能的文档吗? 如果要保存蓝色通道:cv2.imwrite('blue_channel.jpg', b) 为了安全起见,您可以使用 cv2.imread("foo.jpg", 1) 强制加载到 3 通道数组中 我运行了@jabaldonedo 的代码,得到一张 R 通道图像,一张 G 通道图像和一张 B 通道图像。当我打开 R 或 G 或 B 时,结果是黑白图像。这正常吗??我的意思是通道分离的图像中不应该存在红色、绿色、蓝色吗?? 如果你绘制每个通道你会得到一个黑白图像,这是正常的。你需要三个通道来组成一种颜色,只有一个通道你只能绘制黑白。

以上是关于在 python 中使用 OpenCV 分割图像的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python/Opencv 分割二进制图像中的附近元素

[opencv-python]学习-图像分割

毕业了,在Python中使用 OpenCV 和K-Means 聚类对毕业照进行图像分割

毕业了,在Python中使用 OpenCV 和K-Means 聚类对毕业照进行图像分割

OpenCV—Python 分水岭算法图像分割

OpenCV-Python实战——OpenCV用于图像分割的阈值技术(含大量示例,建议收藏)