I try to run the picamera code as in the documentation here :

HOwever, when I run my code and get the dimensions of my array, the array I get has the x and y axes swapped! I have no idea why. This is the code I am running :

import picamera
import picamera.array
import cv2
import numpy as np
from numpy import unravel_index
from time import time

#Set resolution here
Width = 80
Height = 60

ArrayY = 0

# Inherit from PiYUVAnalysis
class MyAnalysisClass(picamera.array.PiYUVAnalysis):
    def analyse(self, array):
        global ArrayY   
        global y
        ArrayY = array
        y = ArrayY[:, :, 0]
        (cx, cy) =  unravel_index(y.argmax(), y.shape)  

with picamera.PiCamera() as camera:
    with picamera.array.PiYUVAnalysis(camera) as output:
        camera.framerate = 30
        output = MyAnalysisClass(camera)  
        camera.start_recording(output, format='yuv')

print ArrayY.nbytes
print ArrayY.itemsize
print ArrayY.shape

I don't understand what it is I have done wrong. The output I get from this is :

(60, 80, 3)
The size of y array is : 4800 (60, 80)

So as you can see, the x and y axes of the array have been flipped. Furthermore, I don't understand why the size of one element is 1 bit as opposed to 8 as I was expecting?

1 Answer 1


This is correct: image representations in memory (whether from the camera or from, for example, an image loaded in PIL) are always in row-order first, then columns (i.e. the shape of the resulting array will always be [y, x, colors]).

This is very likely because graphics hardware wants it in this order. Displays (at least historically - I'm not sure if this still entirely applies in the flat-screen era) wrote image data a line at a time as the electron gun scanned down the screen (see wikipedia's article on raster scanning). In other words, the slowest moving dimension (and therefore the first) is the Y-axis, and the faster moving dimension is the X-axis. If the image is in color, that'll be the last (fastest moving) dimension as every value from it is required to correctly light one pixel.

If it helps, you can think of it in terms of a series of nested for-loops. Given that the monitor is going to write the first line of pixels from left to right, then the next line of pixels from left to right, etc. how do you order a series of for-loops to read out pixel data from the array in the correct order?

for row in image:
    for pixel in row:
        for color in pixel:
            # light up the relevant color sub-pixel at the
            # required strength

So, why do we refer to camera resolution (or image size generally) in [width, height] order? I'm not so sure on this one, but I'd guess convention from mathematics. Either way, it's a well established convention (e.g. it's the way PIL and every other image library refers to image size), so I followed it in the construction of picamera's resolution property. However, as noted, PIL (and everything else out there) stores images internally in [row, column, color] order.

Incidentally, this is also the reason that y=0 is at the top of the display rather than the bottom (again, in contradiction to mathematical convention): because that's where the graphics hardware starts drawing from. Why does it start drawing there? Before monitors there were teletypes which effectively print from the "top left" by printing left-to-right and feeding the paper upwards at a line end. The first monitors emulated teletypes and so we wind up with this mathematically topsy-turvy coordinate system (although in practice it's actually much more useful than the mathematical convention given that a lot of the time we're dealing with text).

Finally: the itemsize is 1 because each element of the array (representing one color plane of one pixel) is a single byte, and therefore has a size of 1.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.