[英]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.