簡體   English   中英

Python Class 成員變量包含 OpenCV 數據初始化為指針

[英]Python Class Member Variable Containing OpenCV data initializes as a pointer

我創建了一個簡單的 Python class 在實例化它時將兩個值作為 arguments ( contentsresolution )。 然后將這些 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM