【问题标题】:What is | (Pipe) symbol used for in Python Opencv functions ( cv2.threshold)什么是| (管道)符号用于 Python Opencv 函数(cv2.threshold)
【发布时间】:2021-10-31 21:13:12
【问题描述】:

我知道这是按位或,但我想知道它在给定函数中做了什么以及它如何用于函数调用

我在opencv函数中看到了一些使用|的代码,例如

t, im = cv2.threshold(blurred, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)

这个|是什么意思?是什么意思,我如何在随机函数foo(x|y) 中使用这个|?

【问题讨论】:

  • 至于为什么这是按位或:这是其他语言(例如编写OpenCV的C/C++)和(例如网络)协议中的常用方法对一组标志进行编码:每个标志都分配有一个数字,该数字是 2 的幂(1、2、4、8,...)。然后,您可以将它们组合在一起而不会丢失信息,并使用按位与提取单个标志的值。
  • 这两个常量被 ORed 在一起并作为单个参数传递给函数,该函数只看到组合结果并且不知道它是如何在调用中提供的。

标签: python opencv opencv3.0 opencv-python


【解决方案1】:

它是 OR 位运算符。如果两个位中的一个或两个为 1,则将每个位设置为 1。

让我们定义一个函数

def print_if_1(number):
    if number == 1:
        print(1)
    else:
        print(0)

还有两个变量a和b

a=1
b=0

现在让我们先验证一下:

print(a)

1

print(b)

0

下面是我们如何在这个函数中使用管道:

print(a|b)

1

【讨论】:

  • 我知道这是OR在正常情况下iut它是如何在一个函数中使用的,就像它在上面给定的函数中使用的一样。如果我必须创建一个函数,我该怎么做?
【解决方案2】:

您可以像平常一样创建一个函数来使用这些值。但请注意,通常将常量定义为 Or-ed,以便当两个或多个值一起 OR-ed 时,每个常量只设置一位。

在使用这些值的函数中,您通常会测试机器人的每个,最简单的方法是通过与值进行 AND 运算,如下例中的 myfn()。

正如其他人在 asnwers 中所说,这种按位 OR-ing 风格在 C/C++ 代码实现中很常见,例如opencv python 是底层 opencv C++ 实现的包装器。就个人而言,如果我正在设计一个 Python API,我会为每个标志使用单独的命名参数,即避免 OR-ing。

例如:

import cv2

def showvalue(v):
    print( f"{v=} {bin(v)=} {hex(v)=}" )

showvalue( cv2.THRESH_OTSU )
showvalue( cv2.THRESH_BINARY_INV )
showvalue( cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU )

abit = 0b0010
bbit = 0b0100

def myfn( v ):
    print( "+++++++" )
    print( f"{v=}" )
    if v & abit:
        print( f"abit is set" )
    if v & bbit:
        print( f"bbit is set" )
    print( "-------" )

myfn(abit)
myfn(bbit)
myfn(abit| bbit)

输出:

v=8 bin(v)='0b1000' hex(v)='0x8'
v=1 bin(v)='0b1' hex(v)='0x1'
v=9 bin(v)='0b1001' hex(v)='0x9'
+++++++
v=2
abit is set
-------
+++++++
v=4
bbit is set
-------
+++++++
v=6
abit is set
bbit is set
-------

【讨论】:

    【解决方案3】:

    编码人员通常会将一堆选项塞进一个变量中。如果你看一下二进制格式分配给各种ThresholdTypes的常量,就更容易理解了

    import cv2
    
    print('THRESH_BINARY:     ', format(cv2.THRESH_BINARY, '#08b'))
    print('THRESH_BINARY_INV: ', format(cv2.THRESH_BINARY_INV, '#08b'))
    print('THRESH_TRUNC:      ', format(cv2.THRESH_TRUNC, '#08b'))
    print('THRESH_TOZERO:     ', format(cv2.THRESH_TOZERO, '#08b'))
    print('THRESH_TOZERO_INV: ', format(cv2.THRESH_TOZERO_INV, '#08b'))
    print('THRESH_MASK:       ', format(cv2.THRESH_MASK, '#08b'))
    print('THRESH_OTSU:       ', format(cv2.THRESH_OTSU, '#08b'))
    print('THRESH_TRIANGLE:   ', format(cv2.THRESH_TRIANGLE, '#08b'))
    

    给出:

    THRESH_BINARY:      0b000000
    THRESH_BINARY_INV:  0b000001
    THRESH_TRUNC:       0b000010
    THRESH_TOZERO:      0b000011
    THRESH_TOZERO_INV:  0b000100
    THRESH_MASK:        0b000111
    THRESH_OTSU:        0b001000
    THRESH_TRIANGLE:    0b010000
    

    管道 (|) 是按位或,如果一个或两个输入位为 1,则将输出位设置为 1,否则为 0。在您的示例中,选项 THRESH_BINARY_INV 和 THRESH_OTSU 都可以使用按位或。在这种情况下,设置第 1 位和第 4 位并将0b001001 发送到函数。

    如果你尝试使用它会变得有点奇怪

    cv2.THRESH_BINARY | cv2.THRESH_BINARY_INV
    

    在这种情况下,第一位被设置 (0b00000001),您将获得一个反转阈值。在这种情况下,cv2.THRESH_BINARY 被有效地忽略了。

    Qt 库中有一个不太容易混淆的例子,InputMethodHints 的可能值都是按位互斥的:

    from PyQt5.QtCore import Qt
    
    print('Qt.ImhHiddenText:       ', format(Qt.ImhHiddenText, '#011b'))
    print('Qt.ImhSensitiveData:    ', format(Qt.ImhSensitiveData, '#011b'))
    print('Qt.ImhNoAutoUppercase:  ', format(Qt.ImhNoAutoUppercase, '#011b'))
    print('Qt.ImhPreferNumbers:    ', format(Qt.ImhPreferNumbers, '#011b'))
    print('Qt.ImhPreferUppercase:  ', format(Qt.ImhPreferUppercase, '#011b'))
    print('Qt.ImhPreferLowercase:  ', format(Qt.ImhPreferLowercase, '#011b'))
    print('Qt.ImhNoPredictiveText: ', format(Qt.ImhNoPredictiveText, '#011b'))
    print('Qt.ImhDate:             ', format(Qt.ImhDate, '#011b'))
    print('Qt.ImhTime:             ', format(Qt.ImhTime, '#011b'))
    
    Qt.ImhHiddenText:        0b000000001
    Qt.ImhSensitiveData:     0b000000010
    Qt.ImhNoAutoUppercase:   0b000000100
    Qt.ImhPreferNumbers:     0b000001000
    Qt.ImhPreferUppercase:   0b000010000
    Qt.ImhPreferLowercase:   0b000100000
    Qt.ImhNoPredictiveText:  0b001000000
    Qt.ImhDate:              0b010000000
    Qt.ImhTime:              0b100000000
    

    您可以按位 2 或更多或所有选项而不会发生冲突。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 2017-03-08
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      相关资源
      最近更新 更多