2024-09-30 14:27:50 发布
网友
我试图理解opencvpython的cv2.bitwise_and函数。所以我试着:
cv2.bitwise_and
import cv2 cv2.bitwise_and(1,1)
以上代码返回
我不明白它为什么会返回这个。在
Documentation表示:
dst(I) = src1(I) ^ src2(I) if mask(I) != 0
根据这个输出应该是单值1。我哪里出错了?在
文档在这方面有点模糊,需要对这两个源以及文档进行一些挖掘,以正确地解释正在发生的事情。在
首先是标量。在数据类型的上下文中,我们有一个cv::Scalar,它实际上是模板^{}的专门化。它表示一个4元向量,并从^{}一个表示固定大小向量的模板派生而来,这又是^{}的一个特例,一个表示小的固定大小矩阵的类。在
cv::Scalar
这是标量数据类型,但是在bitwise_and(以及相关函数)的上下文中,标量和非标量的概念要宽松得多—实际上函数并不知道给它提供了一个cv::Scalar的实例。在
bitwise_and
如果你看一下signature of the function,你会注意到输入是^{}s。因此输入总是数组,但它们的某些属性可能不同(种类、元素类型、大小、维度等)。在
特定的check in the code验证大小、类型和种类是否匹配。如果是这样(在您的场景中也是这样),操作dst(I) = src1(I) ^ src2(I) if mask(I) != 0将运行。在
否则,它将检查其中一个输入数组是否表示标量。它使用函数^{}来完成此操作,return语句说明了其中的大部分内容:
return sz == Size(1, 1) || sz == Size(1, cn) || sz == Size(cn, 1) || (sz == Size(1, 4) && sc.type() == CV_64F && cn <= 4);
cn
最后一个例子既匹配默认的cv::Scalar(正如我们前面看到的,它是cv::Matx<double,4,1>),也匹配cv::Mat(4,1,CF_64F)。在
cv::Matx<double,4,1>
cv::Mat(4,1,CF_64F)
作为中场休息,让我们来测试一下上面所学的内容。在
代码:
输出:
[1; 0; 0; 0] size : [1 x 4] type==CV_64FC1 : yes
已经覆盖了底层C++接口,让我们看看Python绑定。为Python API创建包装器的生成器相当复杂,所以让我们跳过这一步,而是检查它为bitwise_and生成的内容的相关片段:
using namespace cv; { PyObject* pyobj_src1 = NULL; Mat src1; PyObject* pyobj_src2 = NULL; Mat src2; PyObject* pyobj_dst = NULL; Mat dst; PyObject* pyobj_mask = NULL; Mat mask; const char* keywords[] = { "src1", "src2", "dst", "mask", NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "OO|OO:bitwise_and", (char**)keywords, &pyobj_src1, &pyobj_src2, &pyobj_dst, &pyobj_mask) && pyopencv_to(pyobj_src1, src1, ArgInfo("src1", 0)) && pyopencv_to(pyobj_src2, src2, ArgInfo("src2", 0)) && pyopencv_to(pyobj_dst, dst, ArgInfo("dst", 1)) && pyopencv_to(pyobj_mask, mask, ArgInfo("mask", 0)) ) { ERRWRAP2(cv::bitwise_and(src1, src2, dst, mask)); return pyopencv_from(dst); } } PyErr_Clear();
我们可以看到对应于InputArray或OutputArray的参数被加载到cv::Mat实例中。让我们看看^{}中与您的场景对应的部分:
InputArray
OutputArray
cv::Mat
if( PyInt_Check(o) ) { double v[] = {static_cast<double>(PyInt_AsLong((PyObject*)o)), 0., 0., 0.}; m = Mat(4, 1, CV_64F, v).clone(); return true; }
包含转换为double的输入整数的cv::Mat(4, 1, CV_64F)(回想一下,这符合标量测试),其余3个位置用零填充。在
cv::Mat(4, 1, CV_64F)
由于没有提供目的地,因此将自动分配一个与输入大小和类型相同的Mat。返回Python时,Mat将成为numpy数组。在
Mat
文档清楚地指出,如果输入是两个大小相同的数组,那么函数将执行dst(I) = src1(I) ^ src2(I) if mask(I) != 0操作。在
所以试试看:
import numpy as np # Opecv works with numpy arrays import cv2 a = np.uint8([1]) b = np.uint8([1]) cv2.bitwise_and(a, b)
该代码返回:
这是一个包含数字1的一维数组。在
文档还提到可以使用数组和标量来完成操作,但不能使用两个标量,因此输入cv2.bitwise_and(1,1)是不正确的。在
cv2.bitwise_and(1,1)
文档在这方面有点模糊,需要对这两个源以及文档进行一些挖掘,以正确地解释正在发生的事情。在
首先是标量。在数据类型的上下文中,我们有一个} 的专门化。它表示一个4元向量,并从^{} 一个表示固定大小向量的模板派生而来,这又是^{} 的一个特例,一个表示小的固定大小矩阵的类。在
cv::Scalar
,它实际上是模板^{这是标量数据类型,但是在
bitwise_and
(以及相关函数)的上下文中,标量和非标量的概念要宽松得多—实际上函数并不知道给它提供了一个cv::Scalar
的实例。在如果你看一下signature of the function,你会注意到输入是^{} s。因此输入总是数组,但它们的某些属性可能不同(种类、元素类型、大小、维度等)。在
特定的check in the code验证大小、类型和种类是否匹配。如果是这样(在您的场景中也是这样),操作
dst(I) = src1(I) ^ src2(I) if mask(I) != 0
将运行。在否则,它将检查其中一个输入数组是否表示标量。它使用函数^{} 来完成此操作,return语句说明了其中的大部分内容:
cn
或cn
x1(其中cn
是另一个输入数组的通道数)。在最后一个例子既匹配默认的
cv::Scalar
(正如我们前面看到的,它是cv::Matx<double,4,1>
),也匹配cv::Mat(4,1,CF_64F)
。在作为中场休息,让我们来测试一下上面所学的内容。在
代码:
^{pr2}$输出:
已经覆盖了底层C++接口,让我们看看Python绑定。为Python API创建包装器的生成器相当复杂,所以让我们跳过这一步,而是检查它为
bitwise_and
生成的内容的相关片段:我们可以看到对应于} 中与您的场景对应的部分:
InputArray
或OutputArray
的参数被加载到cv::Mat
实例中。让我们看看^{包含转换为double的输入整数的
cv::Mat(4, 1, CV_64F)
(回想一下,这符合标量测试),其余3个位置用零填充。在由于没有提供目的地,因此将自动分配一个与输入大小和类型相同的
Mat
。返回Python时,Mat
将成为numpy数组。在文档清楚地指出,如果输入是两个大小相同的数组,那么函数将执行
dst(I) = src1(I) ^ src2(I) if mask(I) != 0
操作。在所以试试看:
该代码返回:
^{pr2}$这是一个包含数字1的一维数组。在
文档还提到可以使用数组和标量来完成操作,但不能使用两个标量,因此输入
cv2.bitwise_and(1,1)
是不正确的。在相关问题 更多 >
编程相关推荐