Re: [问题] cv2.circle与内存位置

楼主: clang (llvm)   2018-05-11 12:59:51
小的就个人的理解稍做解释
错了还请板上大大指正
※ 引述《znmkhxrw (QQ)》之铭言:
: 想请问一下,为什么以下程式码会错误:
: import cv2
: img_rgb = cv2.imread("image.jpg")[:,:,::-1]
: cv2.circle(img_rgb, (616,44),4,[255, 0, 0], thickness=-1)
: TypeError: Layout of the output array img is incompatible with cv::Mat
: (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
: 但是!我只要加入.copy()就对了 即 ....[:,:,::-1].copy()
: 来龙去脉如下
: ==========================================================
: 首先举个例子厘清一件事情:
: a = [1,2]
: b = a[::-1]
: 则 b 就是 [2,1],而且内存位置不同! id(a) != id(b)
: 逻辑就是把 b 指向某个不同于a的内存位置,值为a = [1,2][::-1]
不管是 list 还是 numpy,值本身不是直接存在 array 中,这个 array/list 本身是个指标阵列,会指向值真正在的地方
从你举的范例可以对照一下
In []: a = [1, 2]
In []: b = a[::-1]
In []: id(a) == id(b)
Out[]: False
b 确实会相异于 a,但它只是建立了新的指标阵列,值没有被复制
In []: id(a[0]) == id(b[1])
Out[]: True
同样的行为适用在numpy上
In []: a = numpy.zeros((3, 5))
...: b = a[:, ::-1]
...: a[0, 0] = 1
...: print(b)
...:
[[0. 0. 0. 0. 1.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
明明改的是 a 的值,但 b 也被修改了
这边参考 numpy doc 的 indexing 说明
"All arrays generated by basic slicing are always views of the original array."
- https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html
这个函式库默认的规则就是回传 view 而不是拷贝,意即只是换换"看这个array的方式"而已
而 numpy 存阵列的方式是将资料存在连续的一维阵列中
然后用stride去纪录当我想取某个值的时候怎么去跳到正确的位子
以上图的 a/b 来说
In []: a.strides
Out[]: (40, 8)
In []: b.strides
Out[]: (40, -8)
你觉得值被反转了,但他只转了读data的顺序
直到你下了 .copy() 它才真正的复制了值,并且将值排好
In []: b = a[::-1].copy()
In []: b.strides
Out[]: (40, 8)
而为什么 cv2 不给吃呢
作者: znmkhxrw (QQ)   2018-05-11 13:35:00
上了一课,谢谢!然后关于你最后一段说.copy()很怪 是?或者是说 我如果以后要避免到这种错误 要有什么好习惯?因为我本意只是让ndarray的RGB跟BGR互调 才用[:,:,::-1]然后就出现这个错误 第一次遇到@@ 以后该怎么注意另外问个问题 [:,:,::-1]是创立新的指标阵列代表说 old_index , new_index 是两个不同指标(变量?)然后指向同一个值?我观念还在浅浅的 "a = b" 代表把a指向b值QQ
作者: laputaflutin (很恐怖,不要问)   2018-05-11 13:54:00
上面的说法也有点问题,a与b都是name "a = b"的意思是指将"b"这个name对应的object同样给"a"name对应另外要注意copy()也只是复制name引用(reference)真正要达成语意上的copy要用 copy.deepcopy()
作者: CaptainH (Cannon)   2018-05-11 22:01:00
不要乱教,那也是看实作. numpy的copy就是真的复制

Links booklink

Contact Us: admin [ a t ] ucptt.com