मैं एक Numpy सरणी में नए आयाम कैसे जोड़ सकता हूं?


85

मैं एक छवि के एक सुन्न सरणी के साथ शुरू कर रहा हूँ।

In[1]:img = cv2.imread('test.jpg')

आकार वह है जो आप 640x480 RGB छवि के लिए उम्मीद कर सकते हैं।

In[2]:img.shape
Out[2]: (480, 640, 3)

हालांकि, यह छवि जो मेरे पास है वह एक वीडियो का एक फ्रेम है, जो 100 फ्रेम लंबा है। आदर्श रूप में, मैं एक ऐसा सरणी रखना चाहूंगा जिसमें इस वीडियो का सारा डेटा हो जैसे कि img.shapeरिटर्न (480, 640, 3, 100)

अगले फ्रेम को जोड़ने का सबसे अच्छा तरीका क्या है - अर्थात्, छवि डेटा का अगला सेट, दूसरा 480 x 640 x 3 सरणी - मेरे प्रारंभिक सरणी के लिए?

जवाबों:


98

आप पूछ रहे हैं कि एक नंबरी सरणी में एक आयाम कैसे जोड़ा जाए, ताकि नए डेटा को समायोजित करने के लिए उस आयाम को उगाया जा सके। एक आयाम इस प्रकार जोड़ा जा सकता है:

image = image[..., np.newaxis]

10
वर्तमान में, numpy.newaxisइसे None(फ़ाइल में numeric.py) परिभाषित किया गया है , इसलिए समकक्ष रूप से आप 'छवि = छवि [..., कोई नहीं] का उपयोग कर सकते हैं।
रे

58
उपयोग न करें None। उपयोग करें np.newaxisक्योंकि स्पष्ट निहितार्थ से बेहतर है।
नील जी

7
ऐसे कैसे हो सकता है? Noneकुछ भी मतलब नहीं है। यह स्पष्ट है। यह है None। स्पष्ट रूप से कहा। None है एक बात अजगर में। इसमें कोई शक नहीं है। Noneअंतिम विवरण है, आप गहराई तक नहीं जा सकते। दूसरी ओर, numpy.newaxisतात्पर्य है None। यह अनिवार्य रूप से, है None। यह है None। लेकिन Noneनिहित है। यह है None, हालांकि नहीं सीधे रूप में व्यक्त किया Noneस्पष्ट रूप से और विस्तार से स्पष्ट, भ्रम या संदेह के लिए कोई जगह नहीं छोड़ी। अंतर्निहित हालांकि सीधे नहीं व्यक्त सुझाव दिया। मुझे एक एपीआई परिप्रेक्ष्य से इसे जोड़ना होगा, यह उपयोग करने के लिए सुरक्षित है numpy.newaxis
पेड्रो रोड्रिग्स

2
यहाँ, स्पष्ट किया जा रहा है कि वाक्य-रचना / शब्दार्थ स्पष्टता के बजाय "कोडर आशय" को संदर्भित करता है।
गबर

जोश एडेल के जवाब को इस मामले में सही जवाब के रूप में चुना जाना चाहिए और अधिक वोटों की आवश्यकता है। उनका कहना इस मायने में महत्वपूर्ण है कि ओपी उच्च आयाम वाले नपरे को जोड़ना चाहता है क्योंकि वह जाता है। ndarray का आकार एक बार बनाए जाने के बाद नहीं बढ़ाया जा सकता है, एक प्रतिलिपि बनाई जानी चाहिए। यह उत्तर केवल आकृति (480, 640, 3, 1) बना देगा और हर बार जब आप एक नया फ्रेम जोड़ेंगे तो आप एक और प्रतिलिपि बना लेंगे। अच्छा नही।
डैन बॉशेन

59

वैकल्पिक रूप से

image = image[..., np.newaxis]

में @dbliss 'जवाब , आप भी उपयोग कर सकते हैं numpy.expand_dimsकी तरह

image = np.expand_dims(image, <your desired dimension>)

उदाहरण के लिए (ऊपर दिए गए लिंक से लिया गया):

x = np.array([1, 2])

print(x.shape)  # prints (2,)

फिर

y = np.expand_dims(x, axis=0)

पैदावार

array([[1, 2]])

तथा

y.shape

देता है

(1, 2)

नए डिमेशन में मूल्यों को कैसे जोड़ा जाए? अगर मैं ऐसा y[1,0]करता हूं तो यह सीमा को त्रुटि से बाहर कर देता है। y[0,1]सुलभ है
weima

@weima: आप के बाद क्या कर रहे हैं पूरी तरह से यकीन नहीं है। आपका वांछित आउटपुट क्या है?
क्लेब जूल

24

आप सही आकार के सामने वाले हिस्से को बना सकते हैं और उसे भर सकते हैं:

frames = np.empty((480, 640, 3, 100))

for k in xrange(nframes):
    frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))

यदि फ़्रेम व्यक्तिगत jpg फ़ाइल थे, जिन्हें किसी विशेष तरीके से नाम दिया गया था (उदाहरण में, फ्रेम_0.jpg, फ़्रेम_1.जेपीजी, आदि)।

केवल एक नोट, आप (nframes, 480,640,3)इसके बजाय एक आकार सरणी का उपयोग करने पर विचार कर सकते हैं ।


1
मुझे लगता है कि यह जाने का रास्ता है। यदि आप समवर्ती का उपयोग करते हैं, तो आपको हर बार जब आप इसे जोड़ते हैं, तो आपको मेमोरी में सरणी को स्थानांतरित करने की आवश्यकता होगी। 100 फ्रेम के लिए जो बिल्कुल भी मायने नहीं रखना चाहिए, लेकिन अगर आप बड़े वीडियो में जाना चाहते हैं। BTW, मैंने पहले आयाम के रूप में फ्रेम की संख्या का उपयोग किया होगा ताकि एक (100,480,640,3) सरणी हो जिस तरह से आप व्यक्तिगत फ्रेम तक पहुंच सकते हैं (क्या आमतौर पर आप चाहते हैं कि आप सही देखना चाहते हैं?) आसान (एफ [1] ] के बजाय F [:,:,:, 1])। बेशक प्रदर्शन के लिहाज से यह बिल्कुल भी मायने नहीं रखना चाहिए।
मैगलन88

मैं JoshAdel और Magellan88 से सहमत हूं, अन्य उत्तर बहुत ही अक्षम मेमोरी वार और प्रोसेसिंग टाइम हैं- ndarrays को एक बार बनाए जाने के बाद आकार में वृद्धि नहीं की जा सकती है, इसलिए एक कॉपी हमेशा बनाई जाएगी यदि आपको लगता है कि आप इसे जोड़ रहे हैं।
डैन बॉशेन

10

pythonic

X = X[:, :, None]

जो के बराबर है

X = X[:, :, numpy.newaxis] तथा X = numpy.expand_dims(X, axis=-1)

लेकिन जैसा कि आप स्पष्ट रूप से स्टैकिंग छवियों के बारे में पूछ रहे हैं, मैं आपको उन listछवियों के स्टैकिंग के लिए जाने की सलाह दूंगा np.stack([X1, X2, X3])जो आपने लूप में एकत्र किए होंगे।

यदि आप उन आयामों के क्रम को पसंद नहीं करते हैं जिनके साथ आप पुनर्व्यवस्थित कर सकते हैं np.transpose()


6

आप इसका उपयोग np.concatenate()करके निर्दिष्ट कर सकते हैं कि कौन सा axisआवेदन करना है np.newaxis:

import numpy as np
movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)

यदि आप कई फाइलों से पढ़ रहे हैं:

import glob
movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)

2

संख्यात्मक में कोई संरचना नहीं है जो आपको बाद में अधिक डेटा संलग्न करने की अनुमति देती है।

इसके बजाय, numpy आपके सभी डेटा को संख्याओं (मूल रूप से; एक C सरणी) के एक सन्निहित भाग में रखता है, और किसी भी आकार को इसे धारण करने के लिए एक नया हिस्सा मेमोरी को आवंटित करने की आवश्यकता होती है। Numpy की गति मेमोरी के एक ही चंक में सभी डेटा को एक सुस्पष्ट सरणी में रखने में सक्षम होने से आती है; उदाहरण के लिए, गणितीय क्रियाओं को गति के लिए समानांतर किया जा सकता है और आपको कम कैश मिसेज़ मिलते हैं

तो आपके पास दो तरह के उपाय होंगे:

  1. स्मृति को पूर्व-आबंटित सरणी के लिए आवंटित करें और मानों में भरें, जैसे जोश एडेल के उत्तर में, या
  2. अपने डेटा को एक सामान्य अजगर सूची में रखें, जब तक कि वास्तव में उन सभी को एक साथ रखने की आवश्यकता न हो (नीचे देखें)

images = []
for i in range(100):
    new_image = # pull image from somewhere
    images.append(new_image)
images = np.stack(images, axis=3)

ध्यान दें कि पहले व्यक्तिगत छवि सरणियों के आयामों का विस्तार करने की आवश्यकता नहीं है, न ही आपको यह जानने की आवश्यकता है कि आप समय से पहले कितनी छवियों की अपेक्षा करते हैं।


2

दृष्टिकोण 1 विधि के साथ दृष्टिकोण 1 और दृष्टिकोण 2 np.newaxis विधि के साथ विचार करें जो समान परिणाम उत्पन्न करते हैं:

#Lets suppose, we have:
x = [1,2,3,4,5,6,7,8,9]
print('I. x',x)

xNpArr = np.array(x)
print('II. xNpArr',xNpArr)
print('III. xNpArr', xNpArr.shape)

xNpArr_3x3 = xNpArr.reshape((3,3))
print('IV. xNpArr_3x3.shape', xNpArr_3x3.shape)
print('V. xNpArr_3x3', xNpArr_3x3)

#Approach 1 with reshape method
xNpArrRs_1x3x3x1 = xNpArr_3x3.reshape((1,3,3,1))
print('VI. xNpArrRs_1x3x3x1.shape', xNpArrRs_1x3x3x1.shape)
print('VII. xNpArrRs_1x3x3x1', xNpArrRs_1x3x3x1)

#Approach 2 with np.newaxis method
xNpArrNa_1x3x3x1 = xNpArr_3x3[np.newaxis, ..., np.newaxis]
print('VIII. xNpArrNa_1x3x3x1.shape', xNpArrNa_1x3x3x1.shape)
print('IX. xNpArrNa_1x3x3x1', xNpArrNa_1x3x3x1)

हमारे पास परिणाम हैं:

I. x [1, 2, 3, 4, 5, 6, 7, 8, 9]

II. xNpArr [1 2 3 4 5 6 7 8 9]

III. xNpArr (9,)

IV. xNpArr_3x3.shape (3, 3)

V. xNpArr_3x3 [[1 2 3]
 [4 5 6]
 [7 8 9]]

VI. xNpArrRs_1x3x3x1.shape (1, 3, 3, 1)

VII. xNpArrRs_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

VIII. xNpArrNa_1x3x3x1.shape (1, 3, 3, 1)

IX. xNpArrNa_1x3x3x1 [[[[1]
   [2]
   [3]]

  [[4]
   [5]
   [6]]

  [[7]
   [8]
   [9]]]]

1

मैंने इस दृष्टिकोण का अनुसरण किया:

import numpy as np
import cv2

ls = []

for image in image_paths:
    ls.append(cv2.imread('test.jpg'))

img_np = np.array(ls) # shape (100, 480, 640, 3)
img_np = np.rollaxis(img_np, 0, 4) # shape (480, 640, 3, 100).
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.