Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenCV和Python:标量与所有像素和通道之间的算术运算_Python_Opencv - Fatal编程技术网

OpenCV和Python:标量与所有像素和通道之间的算术运算

OpenCV和Python:标量与所有像素和通道之间的算术运算,python,opencv,Python,Opencv,我正在尝试用Python对彩色图像(3个通道)进行操作,比如加法、乘法等。。。例如,使用cv.add(img,value),其中img是三通道图像,value是标量 import cv2 as cv import numpy as np img = np.zeros((4,4,3), np.uint8) print(img) cv.add(img, 2) 但这些功能只是改变了第一个通道。我发现在C++中,必须使用标量(value 1,value 2,value 3)< /> >将操作应用到所

我正在尝试用Python对彩色图像(3个通道)进行操作,比如加法、乘法等。。。例如,使用
cv.add(img,value)
,其中
img
是三通道图像,
value
是标量

import cv2 as cv
import numpy as np

img = np.zeros((4,4,3), np.uint8)
print(img)
cv.add(img, 2)
但这些功能只是改变了第一个通道。我发现在C++中,必须使用<代码>标量(value 1,value 2,value 3)< /> >将操作应用到所有通道。

在Python中如何实现这一点?有没有一种方法可以同时将这3个标量值传递给函数,这样我就不需要使用循环了

编辑:另外,我认为最好使用openCV函数,因为它们具有“饱和操作”的优点。例如,在处理uint8时,使用cv.add(250+10)将返回255,而不是260。使用numpy,250+10=260%256=4

示例代码和错误 我创建了一个4x4像素的图像,3个通道,然后尝试添加标量

import cv2 as cv
import numpy as np

img = np.zeros((4,4,3), np.uint8)
print(img)
cv.add(img, 2)
结果是:

array([[[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]]], dtype=uint8)
In [56]: %timeit res1 = img + 100
688 µs ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [57]: %timeit res2 = cv.add(img, 100)
129 µs ± 9.96 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [58]: %timeit res1 = img + 300
1.41 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [59]: %timeit res2 = cv.add(img, 300)
736 µs ± 9.04 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
但如果我只使用一个像素、一行或一列,结果是正确的:

a = img[1,1]; print(a)
cv.add(a, 2)

a = img[:,1]; print(a)
cv.add(a, 2)

a = img[1,:,]; print(a)
cv.add(a, 2)
上述三个示例中最后一个示例的结果:

In [341]: a = img[1,:,]; print(a)
[[0 0 0]
 [0 0 0]
 [0 0 0]
 [0 0 0]]

In [342]: cv.add(a, 2)
Out[342]: 
array([[2, 2, 2],
       [2, 2, 2],
       [2, 2, 2],
       [2, 2, 2]], dtype=uint8)
为什么使用opencv函数而不是numpy? 首先,我觉得很奇怪,你不能直接用opencv函数来实现这一点P(同样,该函数适用于1列或1行像素;这使我认为有一个简单的解决方案可以使它在opencv python中工作。)

其次,表现似乎非常不同。绝对时间并没有那么大,但如果你,比如,需要在一个实时视频中做一些繁重的处理,那可能会有所不同

我运行了一些简单的
cv.add()
vs.
numpy
,将标量添加到单通道图像中:

img = np.zeros((500,500,1), np.uint8)

# sum without saturation
%timeit res1 = img + 100 
%timeit res2 = cv.add(img, 100)

#sum with saturation (going over 255)
%timeit res1 = img + 300
%timeit res2 = cv.add(img, 300)
性能结果如下:

array([[[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]],

       [[2, 0, 0],
        [2, 0, 0],
        [2, 0, 0],
        [2, 0, 0]]], dtype=uint8)
In [56]: %timeit res1 = img + 100
688 µs ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [57]: %timeit res2 = cv.add(img, 100)
129 µs ± 9.96 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [58]: %timeit res1 = img + 300
1.41 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [59]: %timeit res2 = cv.add(img, 300)
736 µs ± 9.04 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
在没有饱和的操作上,numpy加法的速度大约是opencv的5倍。在饱和状态下,速度大约慢2倍。但是您仍然需要更正numpy结果,以便它显示一个饱和255;最后,您必须将其转换回
uint8
(numpy将结果转换为
uint16
,以适应结果):


因此,在Python OpenCV绑定中使用numpy…

时,整个操作的速度也要慢5倍左右。如果您希望将某个内容传递给OpenCV函数,该函数应解释为标量,则应使用包含4个元素的元组。大小很重要,这使包装器代码能够识别它。这对应于C++类型<代码> CV::标量< /C>,它也包含4个值。仅使用所需的值(对应于另一个操作数的通道深度),其余值将被忽略

例如:

import cv2
import numpy as np
img = np.ones((4,4,3), np.uint8)
print cv2.add(img, (1,2,255,0))
控制台输出:

[[[  2   3 255]
  [  2   3 255]
  [  2   3 255]
  [  2   3 255]]

 [[  2   3 255]
  [  2   3 255]
  [  2   3 255]
  [  2   3 255]]

 [[  2   3 255]
  [  2   3 255]
  [  2   3 255]
  [  2   3 255]]

 [[  2   3 255]
  [  2   3 255]
  [  2   3 255]
  [  2   3 255]]]

哇!我已经找了很多了!谢谢此外,我还做了一些性能测试,结果非常有趣(可能相关):运行
cv.add(img,10)
(添加一个简单的值)和
cv.add(img,(10,10,10,0))
(您的解决方案:同时添加3个值)需要相同的时间。因此,如果您运行
for
循环在所有三个通道上传播
cv.add(img,10)
,它将比简单的
cv.add(img,(10,10,10,0))
@GustavoK-Yes慢3倍,两者所需的时间应该相同。将此参数设置为单个整数或浮点值时,其解释方式与将其设置为
(n,0,0,0)
(其中
n
是值)时相同。因此,处理过程采取完全相同的路径。对于未来的人,只需注意一点:该解决方案适用于加法、减法、乘法、除法。。。但是
cv.pow(img,n)
一次对所有通道应用
^n
(我的预期行为),并且使用
cv.pow(img,(n,n,n,0))
会抛出错误。(我在测试伽马校正计算。使用Python 3.6和OpenCV 3.4.2)@ GuStavok,这是因为在C++中,第二个参数<代码> POW是类型<代码>双——这意味着你只能对所有的通道使用相同的指数。同样的情况也适用于Python。