[英]Python Class Member Variable Containing OpenCV data initializes as a pointer
我创建了一个简单的 Python class 在实例化它时将两个值作为 arguments ( contents
和resolution
)。 然后将这些 arguments 分配给类' __init__
function 中的 class 成员。
出于某种原因,class 成员之一( contents
)似乎是引用/指针,而另一个不是( resolution
)。 如果我在一个 class 上编辑contents
,它会更新另一个,即使我已经实例化了两个完全独立的 class 实例。 这是精简的示例:
TestBaseClasses.py
import cv2
class Frame():
def __init__(self, contents, resolution):
self.contents = contents
self.resolution = [resolution[0], resolution[1]]
def resize(self, fx, fy):
self.contents = cv2.resize(self.contents, (0, 0), fx=fx, fy=fy)
测试.py
import cv2
from copy import deepcopy
from TestBaseClasses import Frame
frame = cv2.imread("test_img.png")
h, w, _ = frame.shape
ProcessFrame = Frame(frame, [h, w])
OriginalFrame = Frame(frame, [h, w])
print(type(frame))
print(ProcessFrame is OriginalFrame)
print(ProcessFrame.contents is OriginalFrame.contents)
print(ProcessFrame.resolution is OriginalFrame.resolution)
print(id(ProcessFrame.contents))
print(id(OriginalFrame.contents))
print("########################")
ProcessFrame = Frame(deepcopy(frame), [h, w])
OriginalFrame = Frame(deepcopy(frame), [h, w])
print(type(frame))
print(ProcessFrame is OriginalFrame)
print(ProcessFrame.contents is OriginalFrame.contents)
print(ProcessFrame.resolution is OriginalFrame.resolution)
print(id(ProcessFrame.contents))
print(id(OriginalFrame.contents))
来自 test.py 的 Output
<class 'numpy.ndarray'>
False
True
False
4405193824
4405193824
########################
<class 'numpy.ndarray'>
False
False
False
4409151200
4491382256
如您所见,我必须对frame
变量进行深度复制,以防止它链接到deepcopy
中的相同引用。 您还可以看到frame
变量的类型是 numpy 数组(不是某种引用/指针)。
当我使用示例一(没有deepcopy
)并编辑ProcessFrame
中的contents
成员时,它会编辑OriginalFrame
中的contents
成员。 当我对resolution
做同样的事情时,这不会发生。
这里到底发生了什么? 如果可以避免的话,我不想导入复制模块并使用 deepcopy。
需要注意的是,我使用的是 Python 3.6。
更新
我开始认为这与cv2.imread()
function 有关。 如果我创建一个新的 class 成员并为其分配内容,它使用id()
具有相同的值(即它指向内存中的相同位置)。
在 OpenCV 文档中:
https://docs.opencv.org/3.4/d5/d98/tutorial_mat_operations.html
在“内存管理和引用计数”部分中,它提到使用 OpenCV imread
function 读取的数据相当于 ZF6F87C9FDCF8B3C3F07F93F1EE8712 中的Mat
。 它继续:
Mat 是一种保持矩阵/图像特征(行数和列数、数据类型等)和指向数据的指针的结构。 因此,没有什么能阻止我们拥有多个 Mat 实例对应相同的数据。 Mat 保留一个引用计数,该计数告诉当 Mat 的特定实例被销毁时是否必须释放数据。
因此,虽然 Python 返回<class 'numpy.ndarray'>
作为类型,但它实际上是一个指针/引用(不知道 Python 的区别,请有人对此进行扩展)到 ZCD691B4957F098CDE288 中的该数组在它的示例中,他们使用 go 来展示如何制作图像数据的副本:
img = cv.imread('image.jpg')
_img1 = np.copy(img)
就我而言,我刚刚更新了Frame
class 中的代码,其中self.contents
被初始化为:
self.contents = np.copy(contents)
这解决了问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.